Skip to content

video_core: Account of runtime state changes when compiling shaders #575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Aug 29, 2024

Conversation

raphaelthegreat
Copy link
Contributor

@raphaelthegreat raphaelthegreat commented Aug 25, 2024

A lot of state used during shader compilation is stored in the resource definitions (sharps). For buffers the stride, format (in case of untyped buffer load/store) as well as the size are relevant to compilation. For images the type is most relevant as that determines the layout of the address stream.

Due to this, it is possible for these parameters to be modified while the same shader program is bound. This can cause a variety of issues which are difficult to debug. For example a read-only buffer may get compiled as a UBO first time, but then a larger buffer may be bound which cannot fit in the 16KB size limit. Some games can also use multiple image types with the same program.

To solve this, each Program (which represents a unique guest shader) can now store a collection of vulkan shader modules. After its fetched the resource layout is determined and a resource stage key is calculated which takes into account the position of the shader in the pipeline (start binding) as well as resource information relevant to compilation. Might fix issues in some games, but can also expose issues that where hidden before. This will allow us to remove another hack in bb-hacks branch but is not a fix for bloodborne specifically.

In addition memory usage from the shader cache should be significantly reduced. We only cache Shader::Info object per shader as well as the vulkan shader modules. Before this change, the generated SPIRV code was kept around which could be dozens of KBs per object as well as the IR::Program which stored blocks and translated gcn instructions that aren't much useful

@0xsegf4ult
Copy link
Contributor

This looks like a promising PR since as far as I can tell BB crashes due to device loss on main branch because some shader tries to access an uniform buffer with a size greater than 64k (the limit on most NVIDIA GPUs)

However, the game now crashes on startup due to this assertion. I suppose this shader could be skipped but I have no clue how to do that in the new architecture inside pipeline_cache

[Render.Vulkan] <Error> vk_platform.cpp:DebugUtilsCallback:59: UNASSIGNED-GPU-Assisted: Validation Error: [ UNASSIGNED-GPU-Assisted ] | MessageID = 0xfd41b5b6 | vkCreateShaderModule():  Error during shader instrumentation: line 0: Conflicting addressing models: Logical (input modules 1 through 1) vs PhysicalStorageBuffer64 (input module 2).
[Render.Vulkan] <Error> vk_platform.cpp:DebugUtilsCallback:59: UNASSIGNED-GPU-Assisted-Validation: Validation Error: [ UNASSIGNED-GPU-Assisted-Validation ] | MessageID = 0xea8d5c05 | vkCreateDevice():  Setup Error. Detail: (Failed to link Instrumented shader, spirv-link error:
-1 Proceeding with non instrumented shader.)
[Render.Vulkan] <Info> vk_pipeline_cache.cpp:CompileModule:269: Compiling cs shader 0xe2c27f0c (permutation)
[Render.Vulkan] <Error> vk_platform.cpp:DebugUtilsCallback:59: UNASSIGNED-GPU-Assisted: Validation Error: [ UNASSIGNED-GPU-Assisted ] | MessageID = 0xfd41b5b6 | vkCreateShaderModule():  Error during shader instrumentation: line 0: Conflicting addressing models: Logical (input modules 1 through 1) vs PhysicalStorageBuffer64 (input module 2).
[Render.Vulkan] <Error> vk_platform.cpp:DebugUtilsCallback:59: UNASSIGNED-GPU-Assisted-Validation: Validation Error: [ UNASSIGNED-GPU-Assisted-Validation ] | MessageID = 0xea8d5c05 | vkCreateDevice():  Setup Error. Detail: (Failed to link Instrumented shader, spirv-link error:
-1 Proceeding with non instrumented shader.)
[Render.Vulkan] <Error> image_view.cpp:ImageViewInfo:87: Storage image (num_comps = 4) requires swizzling [BGRA]
[Render.Vulkan] <Error> vk_platform.cpp:DebugUtilsCallback:59: VUID-VkImageViewCreateInfo-usage-02275: Validation Error: [ VUID-VkImageViewCreateInfo-usage-02275 ] Object 0: handle = 0x1983b0000000008a, name = Image 0xd1f3a800:0x100, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x618ab1e7 | vkCreateImageView(): pCreateInfo->format VK_FORMAT_R8G8B8A8_SRGB with tiling VK_IMAGE_TILING_OPTIMAL only supports VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT|VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT|VK_FORMAT_FEATURE_2_BLIT_SRC_BIT|VK_FORMAT_FEATURE_2_BLIT_DST_BIT|VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT|VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT|VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT|VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT|VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT. The Vulkan spec states: If usage contains VK_IMAGE_USAGE_STORAGE_BIT, then the image view's format features must contain VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkImageViewCreateInfo-usage-02275)
[Render.Vulkan] <Error> vk_platform.cpp:DebugUtilsCallback:59: VUID-vkCmdDispatch-OpTypeImage-07027: Validation Error: [ VUID-vkCmdDispatch-OpTypeImage-07027 ] Object 0: handle = 0xd3dd54000000008e, type = VK_OBJECT_TYPE_IMAGE_VIEW; | MessageID = 0xe4a1aa6a | vkCmdDispatch():  the descriptor (VkDescriptorSet 0x0[], binding 2, index 0) has VkImageView 0xd3dd54000000008e[] with format of VK_FORMAT_R8G8B8A8_SRGB which is missing VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT in its features (VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT|VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT|VK_FORMAT_FEATURE_2_BLIT_SRC_BIT|VK_FORMAT_FEATURE_2_BLIT_DST_BIT|VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT|VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT|VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT|VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT|VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT). The Vulkan spec states: For any VkImageView being written as a storage image where the image format field of the OpTypeImage is Unknown, the view's format features must contain VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdDispatch-OpTypeImage-07027)
[Render.Vulkan] <Info> vk_pipeline_cache.cpp:CompileModule:269: Compiling cs shader 0xe2c27f0c (permutation)
[Render.Vulkan] <Info> vk_pipeline_cache.cpp:CompileModule:269: Compiling cs shader 0xe2c27f0c (permutation)
[Debug] <Critical> liverpool.h:unhandled_exception:1095: Unreachable code!
Unhandled exception: Incompatible types F32 and U32
[Thread 0x7fffd7e006c0 (LWP 11657) exited]

Thread 8 "GPU_CommandProc" received signal SIGTRAP, Trace/breakpoint trap.```

@raphaelthegreat
Copy link
Contributor Author

raphaelthegreat commented Aug 25, 2024

Yes this PR has exposed some preexisting shader issues in BB that need to be solved (mainly writing to cubemaps with imageStore and more buffer store formats)

@bigol83
Copy link
Contributor

bigol83 commented Aug 25, 2024

With latest commits Bloodborne reaches character creator but immediately crashes with this error

[Debug] <Critical> emit_spirv_context_get_set.cpp:EmitStoreBufferFormatF32xN:540: Unreachable code!
Invalid format for conversion: Format16_16_16_16

shad_log.txt

@rafael-57
Copy link
Contributor

rafael-57 commented Aug 26, 2024

With latest commits Bloodborne reaches character creator but immediately crashes with this error

[Debug] <Critical> emit_spirv_context_get_set.cpp:EmitStoreBufferFormatF32xN:540: Unreachable code!
Invalid format for conversion: Format16_16_16_16

shad_log.txt

Can confirm, I also reproduced it by going into the loading menu. Instantly crashes, probably when trying to render character models.

shad_log.txt

...
[Render.Vulkan] vk_compute_pipeline.cpp:BindResources:110: Metadata update skipped
[Render.Vulkan] vk_compute_pipeline.cpp:BindResources:110: Metadata update skipped
[Render.Vulkan] vk_compute_pipeline.cpp:BindResources:110: Metadata update skipped
[Render.Vulkan] vk_pipeline_cache.cpp:CompileModule:274: Compiling cs shader 0x8b355b5a (permutation)
[Render.Vulkan] vk_pipeline_cache.cpp:CompileModule:274: Compiling cs shader 0x8b355b5a (permutation)
[Debug] emit_spirv_context_get_set.cpp:EmitStoreBufferFormatF32xN:540: Unreachable code!
Invalid format for conversion: Format16_16_16_16

Copy link
Contributor

@0xsegf4ult 0xsegf4ult left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit: this part in vk_pipeline_cache.h:GetProgram, I messed up something in the comment

const auto it = std::ranges::find(program->modules, stage_key, &Program::Module::first);
if (it == program->modules.end()) {
    auto new_info = MakeShaderInfo(stage, pgm->user_data, info.pgm_base, info.pgm_hash,
                                   liverpool->regs);
    const size_t perm_idx = program->modules.size();
    const auto module = CompileModule(new_info, pgm->Code(), perm_idx, binding);
    program->modules.emplace_back(stage_key, module);
} else {
    binding += info.NumBindings();
}


const u64 full_hash = HashCombine(hash, stage_key);
return std::make_tuple(&info, it->second, full_hash);

I can see how program->modules.end() points to the freshly emplaced element so you just reuse the iterator when returning from this function.

Some shaders cause the small_vector to allocate on the heap, invalidating this iterator and propagating VK_NULL_HANDLE to the pipeline creation functions.

@raphaelthegreat
Copy link
Contributor Author

Good catch, yes. The shader module needs to be copied and not use iterator

@raphaelthegreat
Copy link
Contributor Author

raphaelthegreat commented Aug 26, 2024

For the bloodborne asserts we need to switch to imageBuffer to get automatic format conversion on buffer store. This should reduce permutations in the generic cs clear shaders that trigger most often. Also we need a descriptor set per shader stage ideally to avoid needing to hash start binding

@raphaelthegreat raphaelthegreat force-pushed the permut branch 2 times, most recently from 77f10ce to 049a3df Compare August 29, 2024 15:25
@rafael-57
Copy link
Contributor

rafael-57 commented Aug 29, 2024

For now Bloodborne [CUSA03173] still crashes when making a new character. Game is completely unmodded for testing.

[Render.Vulkan] vk_shader_cache.cpp:CompileModule:116: Compiling fs shader 0x5e224cb6
[Render.Vulkan] vk_shader_cache.cpp:CompileModule:116: Compiling vs shader 0x41ae600f
[Render.Vulkan] tile_manager.cpp:TryDetile:389: Unsupported tiled image: R32Sfloat (Depth_MacroTiled)
[Debug] liverpool.cpp:ProcessGraphics:495: Unreachable code!
Unknown PM4 type 3 opcode 0x24 with count 4

shad_log_bb_new_game.txt

@raphaelthegreat raphaelthegreat merged commit 66e96dd into main Aug 29, 2024
9 checks passed
@hgh32
Copy link

hgh32 commented Aug 31, 2024

Seems to be corrupted on intel gpus
shad_log.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants