diff options
| author | 2020-03-05 11:42:46 -0500 | |
|---|---|---|
| committer | 2020-03-05 11:42:46 -0500 | |
| commit | 0361aa1915468ec55ea0e70778c041f13c0d6746 (patch) | |
| tree | 3b16308a82001e6bd9ff5576c3958b3fb1cb433a | |
| parent | Merge pull request #3469 from namkazt/patch-1 (diff) | |
| parent | vk_shader_decompiler: Implement indexed textures (diff) | |
| download | yuzu-0361aa1915468ec55ea0e70778c041f13c0d6746.tar.gz yuzu-0361aa1915468ec55ea0e70778c041f13c0d6746.tar.xz yuzu-0361aa1915468ec55ea0e70778c041f13c0d6746.zip | |
Merge pull request #3451 from ReinUsesLisp/indexed-textures
vk_shader_decompiler: Implement indexed textures
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 26 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 99 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 21 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 26 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 2 |
8 files changed, 107 insertions, 74 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index e1965fb21..3fcd319fd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -36,6 +36,7 @@ namespace OpenGL { | |||
| 36 | 36 | ||
| 37 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 37 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 38 | 38 | ||
| 39 | using Tegra::Engines::ShaderType; | ||
| 39 | using VideoCore::Surface::PixelFormat; | 40 | using VideoCore::Surface::PixelFormat; |
| 40 | using VideoCore::Surface::SurfaceTarget; | 41 | using VideoCore::Surface::SurfaceTarget; |
| 41 | using VideoCore::Surface::SurfaceType; | 42 | using VideoCore::Surface::SurfaceType; |
| @@ -56,8 +57,7 @@ namespace { | |||
| 56 | 57 | ||
| 57 | template <typename Engine, typename Entry> | 58 | template <typename Engine, typename Entry> |
| 58 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, | 59 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, |
| 59 | Tegra::Engines::ShaderType shader_type, | 60 | ShaderType shader_type, std::size_t index = 0) { |
| 60 | std::size_t index = 0) { | ||
| 61 | if (entry.IsBindless()) { | 61 | if (entry.IsBindless()) { |
| 62 | const Tegra::Texture::TextureHandle tex_handle = | 62 | const Tegra::Texture::TextureHandle tex_handle = |
| 63 | engine.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset()); | 63 | engine.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset()); |
| @@ -910,15 +910,10 @@ void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, const Shader& | |||
| 910 | const auto& maxwell3d = system.GPU().Maxwell3D(); | 910 | const auto& maxwell3d = system.GPU().Maxwell3D(); |
| 911 | u32 binding = device.GetBaseBindings(stage_index).sampler; | 911 | u32 binding = device.GetBaseBindings(stage_index).sampler; |
| 912 | for (const auto& entry : shader->GetShaderEntries().samplers) { | 912 | for (const auto& entry : shader->GetShaderEntries().samplers) { |
| 913 | const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage_index); | 913 | const auto shader_type = static_cast<ShaderType>(stage_index); |
| 914 | if (!entry.IsIndexed()) { | 914 | for (std::size_t i = 0; i < entry.Size(); ++i) { |
| 915 | const auto texture = GetTextureInfo(maxwell3d, entry, shader_type); | 915 | const auto texture = GetTextureInfo(maxwell3d, entry, shader_type, i); |
| 916 | SetupTexture(binding++, texture, entry); | 916 | SetupTexture(binding++, texture, entry); |
| 917 | } else { | ||
| 918 | for (std::size_t i = 0; i < entry.Size(); ++i) { | ||
| 919 | const auto texture = GetTextureInfo(maxwell3d, entry, shader_type, i); | ||
| 920 | SetupTexture(binding++, texture, entry); | ||
| 921 | } | ||
| 922 | } | 917 | } |
| 923 | } | 918 | } |
| 924 | } | 919 | } |
| @@ -928,16 +923,9 @@ void RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) { | |||
| 928 | const auto& compute = system.GPU().KeplerCompute(); | 923 | const auto& compute = system.GPU().KeplerCompute(); |
| 929 | u32 binding = 0; | 924 | u32 binding = 0; |
| 930 | for (const auto& entry : kernel->GetShaderEntries().samplers) { | 925 | for (const auto& entry : kernel->GetShaderEntries().samplers) { |
| 931 | if (!entry.IsIndexed()) { | 926 | for (std::size_t i = 0; i < entry.Size(); ++i) { |
| 932 | const auto texture = | 927 | const auto texture = GetTextureInfo(compute, entry, ShaderType::Compute, i); |
| 933 | GetTextureInfo(compute, entry, Tegra::Engines::ShaderType::Compute); | ||
| 934 | SetupTexture(binding++, texture, entry); | 928 | SetupTexture(binding++, texture, entry); |
| 935 | } else { | ||
| 936 | for (std::size_t i = 0; i < entry.Size(); ++i) { | ||
| 937 | const auto texture = | ||
| 938 | GetTextureInfo(compute, entry, Tegra::Engines::ShaderType::Compute, i); | ||
| 939 | SetupTexture(binding++, texture, entry); | ||
| 940 | } | ||
| 941 | } | 929 | } |
| 942 | } | 930 | } |
| 943 | } | 931 | } |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 9d5b8de7a..60f57d83e 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -73,7 +73,7 @@ UniqueDescriptorUpdateTemplate VKComputePipeline::CreateDescriptorUpdateTemplate | |||
| 73 | std::vector<vk::DescriptorUpdateTemplateEntry> template_entries; | 73 | std::vector<vk::DescriptorUpdateTemplateEntry> template_entries; |
| 74 | u32 binding = 0; | 74 | u32 binding = 0; |
| 75 | u32 offset = 0; | 75 | u32 offset = 0; |
| 76 | FillDescriptorUpdateTemplateEntries(device, entries, binding, offset, template_entries); | 76 | FillDescriptorUpdateTemplateEntries(entries, binding, offset, template_entries); |
| 77 | if (template_entries.empty()) { | 77 | if (template_entries.empty()) { |
| 78 | // If the shader doesn't use descriptor sets, skip template creation. | 78 | // If the shader doesn't use descriptor sets, skip template creation. |
| 79 | return UniqueDescriptorUpdateTemplate{}; | 79 | return UniqueDescriptorUpdateTemplate{}; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index b155dfb49..6a02403c1 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -97,8 +97,7 @@ UniqueDescriptorUpdateTemplate VKGraphicsPipeline::CreateDescriptorUpdateTemplat | |||
| 97 | u32 offset = 0; | 97 | u32 offset = 0; |
| 98 | for (const auto& stage : program) { | 98 | for (const auto& stage : program) { |
| 99 | if (stage) { | 99 | if (stage) { |
| 100 | FillDescriptorUpdateTemplateEntries(device, stage->entries, binding, offset, | 100 | FillDescriptorUpdateTemplateEntries(stage->entries, binding, offset, template_entries); |
| 101 | template_entries); | ||
| 102 | } | 101 | } |
| 103 | } | 102 | } |
| 104 | if (template_entries.empty()) { | 103 | if (template_entries.empty()) { |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 7ddf7d3ee..696e4b291 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -36,6 +36,13 @@ using Tegra::Engines::ShaderType; | |||
| 36 | 36 | ||
| 37 | namespace { | 37 | namespace { |
| 38 | 38 | ||
| 39 | // C++20's using enum | ||
| 40 | constexpr auto eUniformBuffer = vk::DescriptorType::eUniformBuffer; | ||
| 41 | constexpr auto eStorageBuffer = vk::DescriptorType::eStorageBuffer; | ||
| 42 | constexpr auto eUniformTexelBuffer = vk::DescriptorType::eUniformTexelBuffer; | ||
| 43 | constexpr auto eCombinedImageSampler = vk::DescriptorType::eCombinedImageSampler; | ||
| 44 | constexpr auto eStorageImage = vk::DescriptorType::eStorageImage; | ||
| 45 | |||
| 39 | constexpr VideoCommon::Shader::CompilerSettings compiler_settings{ | 46 | constexpr VideoCommon::Shader::CompilerSettings compiler_settings{ |
| 40 | VideoCommon::Shader::CompileDepth::FullDecompile}; | 47 | VideoCommon::Shader::CompileDepth::FullDecompile}; |
| 41 | 48 | ||
| @@ -119,23 +126,32 @@ ShaderType GetShaderType(Maxwell::ShaderProgram program) { | |||
| 119 | } | 126 | } |
| 120 | } | 127 | } |
| 121 | 128 | ||
| 129 | template <vk::DescriptorType descriptor_type, class Container> | ||
| 130 | void AddBindings(std::vector<vk::DescriptorSetLayoutBinding>& bindings, u32& binding, | ||
| 131 | vk::ShaderStageFlags stage_flags, const Container& container) { | ||
| 132 | const u32 num_entries = static_cast<u32>(std::size(container)); | ||
| 133 | for (std::size_t i = 0; i < num_entries; ++i) { | ||
| 134 | u32 count = 1; | ||
| 135 | if constexpr (descriptor_type == eCombinedImageSampler) { | ||
| 136 | // Combined image samplers can be arrayed. | ||
| 137 | count = container[i].Size(); | ||
| 138 | } | ||
| 139 | bindings.emplace_back(binding++, descriptor_type, count, stage_flags, nullptr); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 122 | u32 FillDescriptorLayout(const ShaderEntries& entries, | 143 | u32 FillDescriptorLayout(const ShaderEntries& entries, |
| 123 | std::vector<vk::DescriptorSetLayoutBinding>& bindings, | 144 | std::vector<vk::DescriptorSetLayoutBinding>& bindings, |
| 124 | Maxwell::ShaderProgram program_type, u32 base_binding) { | 145 | Maxwell::ShaderProgram program_type, u32 base_binding) { |
| 125 | const ShaderType stage = GetStageFromProgram(program_type); | 146 | const ShaderType stage = GetStageFromProgram(program_type); |
| 126 | const vk::ShaderStageFlags stage_flags = MaxwellToVK::ShaderStage(stage); | 147 | const vk::ShaderStageFlags flags = MaxwellToVK::ShaderStage(stage); |
| 127 | 148 | ||
| 128 | u32 binding = base_binding; | 149 | u32 binding = base_binding; |
| 129 | const auto AddBindings = [&](vk::DescriptorType descriptor_type, std::size_t num_entries) { | 150 | AddBindings<eUniformBuffer>(bindings, binding, flags, entries.const_buffers); |
| 130 | for (std::size_t i = 0; i < num_entries; ++i) { | 151 | AddBindings<eStorageBuffer>(bindings, binding, flags, entries.global_buffers); |
| 131 | bindings.emplace_back(binding++, descriptor_type, 1, stage_flags, nullptr); | 152 | AddBindings<eUniformTexelBuffer>(bindings, binding, flags, entries.texel_buffers); |
| 132 | } | 153 | AddBindings<eCombinedImageSampler>(bindings, binding, flags, entries.samplers); |
| 133 | }; | 154 | AddBindings<eStorageImage>(bindings, binding, flags, entries.images); |
| 134 | AddBindings(vk::DescriptorType::eUniformBuffer, entries.const_buffers.size()); | ||
| 135 | AddBindings(vk::DescriptorType::eStorageBuffer, entries.global_buffers.size()); | ||
| 136 | AddBindings(vk::DescriptorType::eUniformTexelBuffer, entries.texel_buffers.size()); | ||
| 137 | AddBindings(vk::DescriptorType::eCombinedImageSampler, entries.samplers.size()); | ||
| 138 | AddBindings(vk::DescriptorType::eStorageImage, entries.images.size()); | ||
| 139 | return binding; | 155 | return binding; |
| 140 | } | 156 | } |
| 141 | 157 | ||
| @@ -361,32 +377,45 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) { | |||
| 361 | return {std::move(program), std::move(bindings)}; | 377 | return {std::move(program), std::move(bindings)}; |
| 362 | } | 378 | } |
| 363 | 379 | ||
| 364 | void FillDescriptorUpdateTemplateEntries( | 380 | template <vk::DescriptorType descriptor_type, class Container> |
| 365 | const VKDevice& device, const ShaderEntries& entries, u32& binding, u32& offset, | 381 | void AddEntry(std::vector<vk::DescriptorUpdateTemplateEntry>& template_entries, u32& binding, |
| 366 | std::vector<vk::DescriptorUpdateTemplateEntry>& template_entries) { | 382 | u32& offset, const Container& container) { |
| 367 | static constexpr auto entry_size = static_cast<u32>(sizeof(DescriptorUpdateEntry)); | 383 | static constexpr u32 entry_size = static_cast<u32>(sizeof(DescriptorUpdateEntry)); |
| 368 | const auto AddEntry = [&](vk::DescriptorType descriptor_type, std::size_t count_) { | 384 | const u32 count = static_cast<u32>(std::size(container)); |
| 369 | const u32 count = static_cast<u32>(count_); | 385 | |
| 370 | if (descriptor_type == vk::DescriptorType::eUniformTexelBuffer && | 386 | if constexpr (descriptor_type == eCombinedImageSampler) { |
| 371 | device.GetDriverID() == vk::DriverIdKHR::eNvidiaProprietary) { | 387 | for (u32 i = 0; i < count; ++i) { |
| 372 | // Nvidia has a bug where updating multiple uniform texels at once causes the driver to | 388 | const u32 num_samplers = container[i].Size(); |
| 373 | // crash. | 389 | template_entries.emplace_back(binding, 0, num_samplers, descriptor_type, offset, |
| 374 | for (u32 i = 0; i < count; ++i) { | 390 | entry_size); |
| 375 | template_entries.emplace_back(binding + i, 0, 1, descriptor_type, | 391 | ++binding; |
| 376 | offset + i * entry_size, entry_size); | 392 | offset += num_samplers * entry_size; |
| 377 | } | ||
| 378 | } else if (count != 0) { | ||
| 379 | template_entries.emplace_back(binding, 0, count, descriptor_type, offset, entry_size); | ||
| 380 | } | 393 | } |
| 381 | offset += count * entry_size; | 394 | return; |
| 382 | binding += count; | 395 | } |
| 383 | }; | ||
| 384 | 396 | ||
| 385 | AddEntry(vk::DescriptorType::eUniformBuffer, entries.const_buffers.size()); | 397 | if constexpr (descriptor_type == eUniformTexelBuffer) { |
| 386 | AddEntry(vk::DescriptorType::eStorageBuffer, entries.global_buffers.size()); | 398 | // Nvidia has a bug where updating multiple uniform texels at once causes the driver to |
| 387 | AddEntry(vk::DescriptorType::eUniformTexelBuffer, entries.texel_buffers.size()); | 399 | // crash. |
| 388 | AddEntry(vk::DescriptorType::eCombinedImageSampler, entries.samplers.size()); | 400 | for (u32 i = 0; i < count; ++i) { |
| 389 | AddEntry(vk::DescriptorType::eStorageImage, entries.images.size()); | 401 | template_entries.emplace_back(binding + i, 0, 1, descriptor_type, |
| 402 | offset + i * entry_size, entry_size); | ||
| 403 | } | ||
| 404 | } else if (count > 0) { | ||
| 405 | template_entries.emplace_back(binding, 0, count, descriptor_type, offset, entry_size); | ||
| 406 | } | ||
| 407 | offset += count * entry_size; | ||
| 408 | binding += count; | ||
| 409 | } | ||
| 410 | |||
| 411 | void FillDescriptorUpdateTemplateEntries( | ||
| 412 | const ShaderEntries& entries, u32& binding, u32& offset, | ||
| 413 | std::vector<vk::DescriptorUpdateTemplateEntry>& template_entries) { | ||
| 414 | AddEntry<eUniformBuffer>(template_entries, offset, binding, entries.const_buffers); | ||
| 415 | AddEntry<eStorageBuffer>(template_entries, offset, binding, entries.global_buffers); | ||
| 416 | AddEntry<eUniformTexelBuffer>(template_entries, offset, binding, entries.texel_buffers); | ||
| 417 | AddEntry<eCombinedImageSampler>(template_entries, offset, binding, entries.samplers); | ||
| 418 | AddEntry<eStorageImage>(template_entries, offset, binding, entries.images); | ||
| 390 | } | 419 | } |
| 391 | 420 | ||
| 392 | } // namespace Vulkan | 421 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 8678fc9c3..92a670cc7 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -194,7 +194,7 @@ private: | |||
| 194 | }; | 194 | }; |
| 195 | 195 | ||
| 196 | void FillDescriptorUpdateTemplateEntries( | 196 | void FillDescriptorUpdateTemplateEntries( |
| 197 | const VKDevice& device, const ShaderEntries& entries, u32& binding, u32& offset, | 197 | const ShaderEntries& entries, u32& binding, u32& offset, |
| 198 | std::vector<vk::DescriptorUpdateTemplateEntry>& template_entries); | 198 | std::vector<vk::DescriptorUpdateTemplateEntry>& template_entries); |
| 199 | 199 | ||
| 200 | } // namespace Vulkan | 200 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 3bf86da87..3fe28c204 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -105,17 +105,20 @@ void TransitionImages(const std::vector<ImageView>& views, vk::PipelineStageFlag | |||
| 105 | 105 | ||
| 106 | template <typename Engine, typename Entry> | 106 | template <typename Engine, typename Entry> |
| 107 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, | 107 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, |
| 108 | std::size_t stage) { | 108 | std::size_t stage, std::size_t index = 0) { |
| 109 | const auto stage_type = static_cast<Tegra::Engines::ShaderType>(stage); | 109 | const auto stage_type = static_cast<Tegra::Engines::ShaderType>(stage); |
| 110 | if (entry.IsBindless()) { | 110 | if (entry.IsBindless()) { |
| 111 | const Tegra::Texture::TextureHandle tex_handle = | 111 | const Tegra::Texture::TextureHandle tex_handle = |
| 112 | engine.AccessConstBuffer32(stage_type, entry.GetBuffer(), entry.GetOffset()); | 112 | engine.AccessConstBuffer32(stage_type, entry.GetBuffer(), entry.GetOffset()); |
| 113 | return engine.GetTextureInfo(tex_handle); | 113 | return engine.GetTextureInfo(tex_handle); |
| 114 | } | 114 | } |
| 115 | const auto& gpu_profile = engine.AccessGuestDriverProfile(); | ||
| 116 | const u32 entry_offset = static_cast<u32>(index * gpu_profile.GetTextureHandlerSize()); | ||
| 117 | const u32 offset = entry.GetOffset() + entry_offset; | ||
| 115 | if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) { | 118 | if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) { |
| 116 | return engine.GetStageTexture(stage_type, entry.GetOffset()); | 119 | return engine.GetStageTexture(stage_type, offset); |
| 117 | } else { | 120 | } else { |
| 118 | return engine.GetTexture(entry.GetOffset()); | 121 | return engine.GetTexture(offset); |
| 119 | } | 122 | } |
| 120 | } | 123 | } |
| 121 | 124 | ||
| @@ -836,8 +839,10 @@ void RasterizerVulkan::SetupGraphicsTextures(const ShaderEntries& entries, std:: | |||
| 836 | MICROPROFILE_SCOPE(Vulkan_Textures); | 839 | MICROPROFILE_SCOPE(Vulkan_Textures); |
| 837 | const auto& gpu = system.GPU().Maxwell3D(); | 840 | const auto& gpu = system.GPU().Maxwell3D(); |
| 838 | for (const auto& entry : entries.samplers) { | 841 | for (const auto& entry : entries.samplers) { |
| 839 | const auto texture = GetTextureInfo(gpu, entry, stage); | 842 | for (std::size_t i = 0; i < entry.Size(); ++i) { |
| 840 | SetupTexture(texture, entry); | 843 | const auto texture = GetTextureInfo(gpu, entry, stage, i); |
| 844 | SetupTexture(texture, entry); | ||
| 845 | } | ||
| 841 | } | 846 | } |
| 842 | } | 847 | } |
| 843 | 848 | ||
| @@ -886,8 +891,10 @@ void RasterizerVulkan::SetupComputeTextures(const ShaderEntries& entries) { | |||
| 886 | MICROPROFILE_SCOPE(Vulkan_Textures); | 891 | MICROPROFILE_SCOPE(Vulkan_Textures); |
| 887 | const auto& gpu = system.GPU().KeplerCompute(); | 892 | const auto& gpu = system.GPU().KeplerCompute(); |
| 888 | for (const auto& entry : entries.samplers) { | 893 | for (const auto& entry : entries.samplers) { |
| 889 | const auto texture = GetTextureInfo(gpu, entry, ComputeShaderIndex); | 894 | for (std::size_t i = 0; i < entry.Size(); ++i) { |
| 890 | SetupTexture(texture, entry); | 895 | const auto texture = GetTextureInfo(gpu, entry, ComputeShaderIndex, i); |
| 896 | SetupTexture(texture, entry); | ||
| 897 | } | ||
| 891 | } | 898 | } |
| 892 | } | 899 | } |
| 893 | 900 | ||
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index f64354a0c..cfcca5af0 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -69,8 +69,9 @@ struct TexelBuffer { | |||
| 69 | 69 | ||
| 70 | struct SampledImage { | 70 | struct SampledImage { |
| 71 | Id image_type{}; | 71 | Id image_type{}; |
| 72 | Id sampled_image_type{}; | 72 | Id sampler_type{}; |
| 73 | Id sampler{}; | 73 | Id sampler_pointer_type{}; |
| 74 | Id variable{}; | ||
| 74 | }; | 75 | }; |
| 75 | 76 | ||
| 76 | struct StorageImage { | 77 | struct StorageImage { |
| @@ -833,16 +834,20 @@ private: | |||
| 833 | constexpr int sampled = 1; | 834 | constexpr int sampled = 1; |
| 834 | constexpr auto format = spv::ImageFormat::Unknown; | 835 | constexpr auto format = spv::ImageFormat::Unknown; |
| 835 | const Id image_type = TypeImage(t_float, dim, depth, arrayed, ms, sampled, format); | 836 | const Id image_type = TypeImage(t_float, dim, depth, arrayed, ms, sampled, format); |
| 836 | const Id sampled_image_type = TypeSampledImage(image_type); | 837 | const Id sampler_type = TypeSampledImage(image_type); |
| 837 | const Id pointer_type = | 838 | const Id sampler_pointer_type = |
| 838 | TypePointer(spv::StorageClass::UniformConstant, sampled_image_type); | 839 | TypePointer(spv::StorageClass::UniformConstant, sampler_type); |
| 840 | const Id type = sampler.IsIndexed() | ||
| 841 | ? TypeArray(sampler_type, Constant(t_uint, sampler.Size())) | ||
| 842 | : sampler_type; | ||
| 843 | const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, type); | ||
| 839 | const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant); | 844 | const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant); |
| 840 | AddGlobalVariable(Name(id, fmt::format("sampler_{}", sampler.GetIndex()))); | 845 | AddGlobalVariable(Name(id, fmt::format("sampler_{}", sampler.GetIndex()))); |
| 841 | Decorate(id, spv::Decoration::Binding, binding++); | 846 | Decorate(id, spv::Decoration::Binding, binding++); |
| 842 | Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); | 847 | Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); |
| 843 | 848 | ||
| 844 | sampled_images.emplace(sampler.GetIndex(), | 849 | sampled_images.emplace(sampler.GetIndex(), SampledImage{image_type, sampler_type, |
| 845 | SampledImage{image_type, sampled_image_type, id}); | 850 | sampler_pointer_type, id}); |
| 846 | } | 851 | } |
| 847 | return binding; | 852 | return binding; |
| 848 | } | 853 | } |
| @@ -1525,7 +1530,12 @@ private: | |||
| 1525 | ASSERT(!meta.sampler.IsBuffer()); | 1530 | ASSERT(!meta.sampler.IsBuffer()); |
| 1526 | 1531 | ||
| 1527 | const auto& entry = sampled_images.at(meta.sampler.GetIndex()); | 1532 | const auto& entry = sampled_images.at(meta.sampler.GetIndex()); |
| 1528 | return OpLoad(entry.sampled_image_type, entry.sampler); | 1533 | Id sampler = entry.variable; |
| 1534 | if (meta.sampler.IsIndexed()) { | ||
| 1535 | const Id index = AsInt(Visit(meta.index)); | ||
| 1536 | sampler = OpAccessChain(entry.sampler_pointer_type, sampler, index); | ||
| 1537 | } | ||
| 1538 | return OpLoad(entry.sampler_type, sampler); | ||
| 1529 | } | 1539 | } |
| 1530 | 1540 | ||
| 1531 | Id GetTextureImage(Operation operation) { | 1541 | Id GetTextureImage(Operation operation) { |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index a0a7b9111..a1828546e 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -299,7 +299,7 @@ private: | |||
| 299 | u32 index{}; ///< Emulated index given for the this sampler. | 299 | u32 index{}; ///< Emulated index given for the this sampler. |
| 300 | u32 offset{}; ///< Offset in the const buffer from where the sampler is being read. | 300 | u32 offset{}; ///< Offset in the const buffer from where the sampler is being read. |
| 301 | u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers). | 301 | u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers). |
| 302 | u32 size{}; ///< Size of the sampler if indexed. | 302 | u32 size{1}; ///< Size of the sampler. |
| 303 | 303 | ||
| 304 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) | 304 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) |
| 305 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. | 305 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. |