diff options
| author | 2021-08-01 18:57:45 -0300 | |
|---|---|---|
| committer | 2021-11-16 22:11:29 +0100 | |
| commit | e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf (patch) | |
| tree | 0107548906df0b9d42e89451489be6a54ed71bf3 /src/video_core | |
| parent | shader: Properly blacklist and scale image loads (diff) | |
| download | yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.tar.gz yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.tar.xz yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.zip | |
shader: Properly scale image reads and add GL SPIR-V support
Thanks for everything!
Diffstat (limited to 'src/video_core')
5 files changed, 57 insertions, 26 deletions
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 187a28e4d..d4dd10bb6 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <span> | 6 | #include <span> |
| 7 | 7 | ||
| 8 | #include "shader_recompiler/backend/glasm/emit_glasm.h" | ||
| 8 | #include "video_core/buffer_cache/buffer_cache.h" | 9 | #include "video_core/buffer_cache/buffer_cache.h" |
| 9 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 10 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| 10 | #include "video_core/renderer_opengl/gl_device.h" | 11 | #include "video_core/renderer_opengl/gl_device.h" |
| @@ -229,8 +230,10 @@ void BufferCacheRuntime::BindStorageBuffer(size_t stage, u32 binding_index, Buff | |||
| 229 | .padding = 0, | 230 | .padding = 0, |
| 230 | }; | 231 | }; |
| 231 | buffer.MakeResident(is_written ? GL_READ_WRITE : GL_READ_ONLY); | 232 | buffer.MakeResident(is_written ? GL_READ_WRITE : GL_READ_ONLY); |
| 232 | glProgramLocalParametersI4uivNV(PROGRAM_LUT[stage], binding_index, 1, | 233 | glProgramLocalParametersI4uivNV( |
| 233 | reinterpret_cast<const GLuint*>(&ssbo)); | 234 | PROGRAM_LUT[stage], |
| 235 | Shader::Backend::GLASM::PROGRAM_LOCAL_PARAMETER_STORAGE_BUFFER_BASE + binding_index, 1, | ||
| 236 | reinterpret_cast<const GLuint*>(&ssbo)); | ||
| 234 | } | 237 | } |
| 235 | } | 238 | } |
| 236 | 239 | ||
| @@ -250,8 +253,10 @@ void BufferCacheRuntime::BindComputeStorageBuffer(u32 binding_index, Buffer& buf | |||
| 250 | .padding = 0, | 253 | .padding = 0, |
| 251 | }; | 254 | }; |
| 252 | buffer.MakeResident(is_written ? GL_READ_WRITE : GL_READ_ONLY); | 255 | buffer.MakeResident(is_written ? GL_READ_WRITE : GL_READ_ONLY); |
| 253 | glProgramLocalParametersI4uivNV(GL_COMPUTE_PROGRAM_NV, binding_index, 1, | 256 | glProgramLocalParametersI4uivNV( |
| 254 | reinterpret_cast<const GLuint*>(&ssbo)); | 257 | GL_COMPUTE_PROGRAM_NV, |
| 258 | Shader::Backend::GLASM::PROGRAM_LOCAL_PARAMETER_STORAGE_BUFFER_BASE + binding_index, 1, | ||
| 259 | reinterpret_cast<const GLuint*>(&ssbo)); | ||
| 255 | } | 260 | } |
| 256 | } | 261 | } |
| 257 | 262 | ||
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 60c65047b..9af61c340 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp | |||
| @@ -181,33 +181,40 @@ void ComputePipeline::Configure() { | |||
| 181 | texture_binding += num_texture_buffers; | 181 | texture_binding += num_texture_buffers; |
| 182 | image_binding += num_image_buffers; | 182 | image_binding += num_image_buffers; |
| 183 | 183 | ||
| 184 | u32 scaling_mask{}; | 184 | u32 texture_scaling_mask{}; |
| 185 | for (const auto& desc : info.texture_descriptors) { | 185 | for (const auto& desc : info.texture_descriptors) { |
| 186 | for (u32 index = 0; index < desc.count; ++index) { | 186 | for (u32 index = 0; index < desc.count; ++index) { |
| 187 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | 187 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; |
| 188 | textures[texture_binding] = image_view.Handle(desc.type); | 188 | textures[texture_binding] = image_view.Handle(desc.type); |
| 189 | if (texture_cache.IsRescaling(image_view)) { | 189 | if (texture_cache.IsRescaling(image_view)) { |
| 190 | scaling_mask |= 1u << texture_binding; | 190 | texture_scaling_mask |= 1u << texture_binding; |
| 191 | } | 191 | } |
| 192 | ++texture_binding; | 192 | ++texture_binding; |
| 193 | } | 193 | } |
| 194 | } | 194 | } |
| 195 | u32 image_scaling_mask{}; | ||
| 195 | for (const auto& desc : info.image_descriptors) { | 196 | for (const auto& desc : info.image_descriptors) { |
| 196 | for (u32 index = 0; index < desc.count; ++index) { | 197 | for (u32 index = 0; index < desc.count; ++index) { |
| 197 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | 198 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; |
| 198 | if (desc.is_written) { | 199 | if (desc.is_written) { |
| 199 | texture_cache.MarkModification(image_view.image_id); | 200 | texture_cache.MarkModification(image_view.image_id); |
| 200 | } | 201 | } |
| 201 | images[image_binding++] = image_view.StorageView(desc.type, desc.format); | 202 | images[image_binding] = image_view.StorageView(desc.type, desc.format); |
| 203 | if (texture_cache.IsRescaling(image_view)) { | ||
| 204 | image_scaling_mask |= 1u << image_binding; | ||
| 205 | } | ||
| 206 | ++image_binding; | ||
| 202 | } | 207 | } |
| 203 | } | 208 | } |
| 204 | if (info.uses_rescaling_uniform) { | 209 | if (info.uses_rescaling_uniform) { |
| 205 | const f32 float_scaling_mask{Common::BitCast<f32>(scaling_mask)}; | 210 | const f32 float_texture_scaling_mask{Common::BitCast<f32>(texture_scaling_mask)}; |
| 211 | const f32 float_image_scaling_mask{Common::BitCast<f32>(image_scaling_mask)}; | ||
| 206 | if (assembly_program.handle != 0) { | 212 | if (assembly_program.handle != 0) { |
| 207 | glProgramLocalParameter4fARB(GL_COMPUTE_PROGRAM_NV, 0, float_scaling_mask, 0.0f, 0.0f, | 213 | glProgramLocalParameter4fARB(GL_COMPUTE_PROGRAM_NV, 0, float_texture_scaling_mask, |
| 208 | 0.0f); | 214 | float_image_scaling_mask, 0.0f, 0.0f); |
| 209 | } else { | 215 | } else { |
| 210 | glProgramUniform4f(source_program.handle, 0, float_scaling_mask, 0.0f, 0.0f, 0.0f); | 216 | glProgramUniform4f(source_program.handle, 0, float_texture_scaling_mask, |
| 217 | float_image_scaling_mask, 0.0f, 0.0f); | ||
| 211 | } | 218 | } |
| 212 | } | 219 | } |
| 213 | if (texture_binding != 0) { | 220 | if (texture_binding != 0) { |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 11559d6ce..f8495896c 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -464,8 +464,10 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 464 | views_it += num_texture_buffers[stage]; | 464 | views_it += num_texture_buffers[stage]; |
| 465 | views_it += num_image_buffers[stage]; | 465 | views_it += num_image_buffers[stage]; |
| 466 | 466 | ||
| 467 | u32 scaling_mask{}; | 467 | u32 texture_scaling_mask{}; |
| 468 | u32 image_scaling_mask{}; | ||
| 468 | u32 stage_texture_binding{}; | 469 | u32 stage_texture_binding{}; |
| 470 | u32 stage_image_binding{}; | ||
| 469 | 471 | ||
| 470 | const auto& info{stage_infos[stage]}; | 472 | const auto& info{stage_infos[stage]}; |
| 471 | for (const auto& desc : info.texture_descriptors) { | 473 | for (const auto& desc : info.texture_descriptors) { |
| @@ -473,7 +475,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 473 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | 475 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; |
| 474 | textures[texture_binding] = image_view.Handle(desc.type); | 476 | textures[texture_binding] = image_view.Handle(desc.type); |
| 475 | if (texture_cache.IsRescaling(image_view)) { | 477 | if (texture_cache.IsRescaling(image_view)) { |
| 476 | scaling_mask |= 1u << stage_texture_binding; | 478 | texture_scaling_mask |= 1u << stage_texture_binding; |
| 477 | } | 479 | } |
| 478 | ++texture_binding; | 480 | ++texture_binding; |
| 479 | ++stage_texture_binding; | 481 | ++stage_texture_binding; |
| @@ -485,20 +487,26 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 485 | if (desc.is_written) { | 487 | if (desc.is_written) { |
| 486 | texture_cache.MarkModification(image_view.image_id); | 488 | texture_cache.MarkModification(image_view.image_id); |
| 487 | } | 489 | } |
| 488 | images[image_binding++] = image_view.StorageView(desc.type, desc.format); | 490 | images[image_binding] = image_view.StorageView(desc.type, desc.format); |
| 491 | if (texture_cache.IsRescaling(image_view)) { | ||
| 492 | image_scaling_mask |= 1u << stage_image_binding; | ||
| 493 | } | ||
| 494 | ++image_binding; | ||
| 495 | ++stage_image_binding; | ||
| 489 | } | 496 | } |
| 490 | } | 497 | } |
| 491 | if (info.uses_rescaling_uniform) { | 498 | if (info.uses_rescaling_uniform) { |
| 492 | const f32 float_scaling_mask{Common::BitCast<f32>(scaling_mask)}; | 499 | const f32 float_texture_scaling_mask{Common::BitCast<f32>(texture_scaling_mask)}; |
| 500 | const f32 float_image_scaling_mask{Common::BitCast<f32>(image_scaling_mask)}; | ||
| 493 | const bool is_rescaling{texture_cache.IsRescaling()}; | 501 | const bool is_rescaling{texture_cache.IsRescaling()}; |
| 494 | const f32 config_down_factor{Settings::values.resolution_info.down_factor}; | 502 | const f32 config_down_factor{Settings::values.resolution_info.down_factor}; |
| 495 | const f32 down_factor{is_rescaling ? config_down_factor : 1.0f}; | 503 | const f32 down_factor{is_rescaling ? config_down_factor : 1.0f}; |
| 496 | if (use_assembly) { | 504 | if (use_assembly) { |
| 497 | glProgramLocalParameter4fARB(AssemblyStage(stage), 0, float_scaling_mask, | 505 | glProgramLocalParameter4fARB(AssemblyStage(stage), 0, float_texture_scaling_mask, |
| 498 | down_factor, 0.0f, 0.0f); | 506 | float_image_scaling_mask, down_factor, 0.0f); |
| 499 | } else { | 507 | } else { |
| 500 | glProgramUniform4f(source_programs[stage].handle, 0, float_scaling_mask, | 508 | glProgramUniform4f(source_programs[stage].handle, 0, float_texture_scaling_mask, |
| 501 | down_factor, 0.0f, 0.0f); | 509 | float_image_scaling_mask, down_factor, 0.0f); |
| 502 | } | 510 | } |
| 503 | } | 511 | } |
| 504 | }}; | 512 | }}; |
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index bce4220c6..85ae726d1 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "shader_recompiler/backend/spirv/emit_spirv.h" | ||
| 13 | #include "shader_recompiler/shader_info.h" | 14 | #include "shader_recompiler/shader_info.h" |
| 14 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 15 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 15 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 16 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| @@ -20,7 +21,7 @@ | |||
| 20 | 21 | ||
| 21 | namespace Vulkan { | 22 | namespace Vulkan { |
| 22 | 23 | ||
| 23 | constexpr size_t MAX_RESCALING_WORDS = 4; | 24 | using Shader::Backend::SPIRV::NUM_TEXTURE_AND_IMAGE_SCALING_WORDS; |
| 24 | 25 | ||
| 25 | class DescriptorLayoutBuilder { | 26 | class DescriptorLayoutBuilder { |
| 26 | public: | 27 | public: |
| @@ -74,7 +75,8 @@ public: | |||
| 74 | .stageFlags = static_cast<VkShaderStageFlags>( | 75 | .stageFlags = static_cast<VkShaderStageFlags>( |
| 75 | is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS), | 76 | is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS), |
| 76 | .offset = 0, | 77 | .offset = 0, |
| 77 | .size = (is_compute ? 0 : sizeof(f32)) + sizeof(std::array<u32, MAX_RESCALING_WORDS>), | 78 | .size = (is_compute ? 0 : sizeof(f32)) + |
| 79 | sizeof(std::array<u32, NUM_TEXTURE_AND_IMAGE_SCALING_WORDS>), | ||
| 78 | }; | 80 | }; |
| 79 | return device->GetLogical().CreatePipelineLayout({ | 81 | return device->GetLogical().CreatePipelineLayout({ |
| 80 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | 82 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
| @@ -146,14 +148,25 @@ public: | |||
| 146 | } | 148 | } |
| 147 | } | 149 | } |
| 148 | 150 | ||
| 149 | const std::array<u32, MAX_RESCALING_WORDS>& Data() const noexcept { | 151 | void PushImage(bool is_rescaled) noexcept { |
| 152 | *image_ptr |= is_rescaled ? image_bit : 0; | ||
| 153 | image_bit <<= 1; | ||
| 154 | if (image_bit == 0) { | ||
| 155 | image_bit = 1u; | ||
| 156 | ++image_ptr; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | const std::array<u32, NUM_TEXTURE_AND_IMAGE_SCALING_WORDS>& Data() const noexcept { | ||
| 150 | return words; | 161 | return words; |
| 151 | } | 162 | } |
| 152 | 163 | ||
| 153 | private: | 164 | private: |
| 154 | std::array<u32, MAX_RESCALING_WORDS> words{}; | 165 | std::array<u32, NUM_TEXTURE_AND_IMAGE_SCALING_WORDS> words{}; |
| 155 | u32* texture_ptr{words.data()}; | 166 | u32* texture_ptr{words.data()}; |
| 167 | u32* image_ptr{words.data() + Shader::Backend::SPIRV::NUM_TEXTURE_SCALING_WORDS}; | ||
| 156 | u32 texture_bit{1u}; | 168 | u32 texture_bit{1u}; |
| 169 | u32 image_bit{1u}; | ||
| 157 | }; | 170 | }; |
| 158 | 171 | ||
| 159 | inline void PushImageDescriptors(TextureCache& texture_cache, | 172 | inline void PushImageDescriptors(TextureCache& texture_cache, |
| @@ -181,6 +194,7 @@ inline void PushImageDescriptors(TextureCache& texture_cache, | |||
| 181 | } | 194 | } |
| 182 | const VkImageView vk_image_view{image_view.StorageView(desc.type, desc.format)}; | 195 | const VkImageView vk_image_view{image_view.StorageView(desc.type, desc.format)}; |
| 183 | update_descriptor_queue.AddImage(vk_image_view); | 196 | update_descriptor_queue.AddImage(vk_image_view); |
| 197 | rescaling.PushImage(texture_cache.IsRescaling(image_view)); | ||
| 184 | } | 198 | } |
| 185 | } | 199 | } |
| 186 | } | 200 | } |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 691ef0841..eb8b4e08b 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -139,9 +139,6 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program | |||
| 139 | } else { | 139 | } else { |
| 140 | info.previous_stage_stores.mask.set(); | 140 | info.previous_stage_stores.mask.set(); |
| 141 | } | 141 | } |
| 142 | for (const auto& stage : programs) { | ||
| 143 | info.num_textures += Shader::NumDescriptors(stage.info.texture_descriptors); | ||
| 144 | } | ||
| 145 | const Shader::Stage stage{program.stage}; | 142 | const Shader::Stage stage{program.stage}; |
| 146 | const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough}; | 143 | const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough}; |
| 147 | const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; | 144 | const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; |