diff options
| author | 2021-06-24 02:41:09 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:39 -0400 | |
| commit | 7dafa96ab59892b7f1fbffdb61e4326e6443955f (patch) | |
| tree | 5ab58d56860db635542ea1ec24be258bd86b40b9 /src/video_core | |
| parent | vk_graphics_pipeline: Implement conservative rendering (diff) | |
| download | yuzu-7dafa96ab59892b7f1fbffdb61e4326e6443955f.tar.gz yuzu-7dafa96ab59892b7f1fbffdb61e4326e6443955f.tar.xz yuzu-7dafa96ab59892b7f1fbffdb61e4326e6443955f.zip | |
shader: Rework varyings and implement passthrough geometry shaders
Put all varyings into a single std::bitset with helpers to access it.
Implement passthrough geometry shaders using host's.
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/shader_environment.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 6 |
7 files changed, 43 insertions, 15 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index da2ded671..471d5686a 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -961,7 +961,11 @@ public: | |||
| 961 | 961 | ||
| 962 | SamplerIndex sampler_index; | 962 | SamplerIndex sampler_index; |
| 963 | 963 | ||
| 964 | INSERT_PADDING_WORDS_NOINIT(0x25); | 964 | INSERT_PADDING_WORDS_NOINIT(0x2); |
| 965 | |||
| 966 | std::array<u32, 8> gp_passthrough_mask; | ||
| 967 | |||
| 968 | INSERT_PADDING_WORDS_NOINIT(0x1B); | ||
| 965 | 969 | ||
| 966 | u32 depth_test_enable; | 970 | u32 depth_test_enable; |
| 967 | 971 | ||
| @@ -1628,6 +1632,7 @@ ASSERT_REG_POSITION(zeta_width, 0x48a); | |||
| 1628 | ASSERT_REG_POSITION(zeta_height, 0x48b); | 1632 | ASSERT_REG_POSITION(zeta_height, 0x48b); |
| 1629 | ASSERT_REG_POSITION(zeta_depth, 0x48c); | 1633 | ASSERT_REG_POSITION(zeta_depth, 0x48c); |
| 1630 | ASSERT_REG_POSITION(sampler_index, 0x48D); | 1634 | ASSERT_REG_POSITION(sampler_index, 0x48D); |
| 1635 | ASSERT_REG_POSITION(gp_passthrough_mask, 0x490); | ||
| 1631 | ASSERT_REG_POSITION(depth_test_enable, 0x4B3); | 1636 | ASSERT_REG_POSITION(depth_test_enable, 0x4B3); |
| 1632 | ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); | 1637 | ASSERT_REG_POSITION(independent_blend_enable, 0x4B9); |
| 1633 | ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); | 1638 | ASSERT_REG_POSITION(depth_write_enabled, 0x4BA); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 5af9b7745..06e39a503 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -61,10 +61,10 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, | |||
| 61 | bool glasm_use_storage_buffers, bool use_assembly_shaders) { | 61 | bool glasm_use_storage_buffers, bool use_assembly_shaders) { |
| 62 | Shader::RuntimeInfo info; | 62 | Shader::RuntimeInfo info; |
| 63 | if (previous_program) { | 63 | if (previous_program) { |
| 64 | info.previous_stage_stores_generic = previous_program->info.stores_generics; | 64 | info.previous_stage_stores = previous_program->info.stores; |
| 65 | } else { | 65 | } else { |
| 66 | // Mark all stores as available | 66 | // Mark all stores as available for vertex shaders |
| 67 | info.previous_stage_stores_generic.flip(); | 67 | info.previous_stage_stores.mask.set(); |
| 68 | } | 68 | } |
| 69 | switch (program.stage) { | 69 | switch (program.stage) { |
| 70 | case Shader::Stage::VertexB: | 70 | case Shader::Stage::VertexB: |
| @@ -187,6 +187,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo | |||
| 187 | .support_demote_to_helper_invocation = false, | 187 | .support_demote_to_helper_invocation = false, |
| 188 | .support_int64_atomics = false, | 188 | .support_int64_atomics = false, |
| 189 | .support_derivative_control = device.HasDerivativeControl(), | 189 | .support_derivative_control = device.HasDerivativeControl(), |
| 190 | .support_geometry_shader_passthrough = false, // TODO | ||
| 190 | .support_gl_nv_gpu_shader_5 = device.HasNvGpuShader5(), | 191 | .support_gl_nv_gpu_shader_5 = device.HasNvGpuShader5(), |
| 191 | .support_gl_amd_gpu_shader_half_float = device.HasAmdShaderHalfFloat(), | 192 | .support_gl_amd_gpu_shader_half_float = device.HasAmdShaderHalfFloat(), |
| 192 | .support_gl_texture_shadow_lod = device.HasTextureShadowLod(), | 193 | .support_gl_texture_shadow_lod = device.HasTextureShadowLod(), |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 70e183e65..6d664ed6b 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -487,10 +487,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 487 | static_vector<VkVertexInputBindingDivisorDescriptionEXT, 32> vertex_binding_divisors; | 487 | static_vector<VkVertexInputBindingDivisorDescriptionEXT, 32> vertex_binding_divisors; |
| 488 | static_vector<VkVertexInputAttributeDescription, 32> vertex_attributes; | 488 | static_vector<VkVertexInputAttributeDescription, 32> vertex_attributes; |
| 489 | if (key.state.dynamic_vertex_input) { | 489 | if (key.state.dynamic_vertex_input) { |
| 490 | const auto& input_attributes = stage_infos[0].input_generics; | ||
| 491 | for (size_t index = 0; index < key.state.attributes.size(); ++index) { | 490 | for (size_t index = 0; index < key.state.attributes.size(); ++index) { |
| 492 | const u32 type = key.state.DynamicAttributeType(index); | 491 | const u32 type = key.state.DynamicAttributeType(index); |
| 493 | if (!input_attributes[index].used || type == 0) { | 492 | if (!stage_infos[0].loads.Generic(index) || type == 0) { |
| 494 | continue; | 493 | continue; |
| 495 | } | 494 | } |
| 496 | vertex_attributes.push_back({ | 495 | vertex_attributes.push_back({ |
| @@ -526,10 +525,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 526 | }); | 525 | }); |
| 527 | } | 526 | } |
| 528 | } | 527 | } |
| 529 | const auto& input_attributes = stage_infos[0].input_generics; | ||
| 530 | for (size_t index = 0; index < key.state.attributes.size(); ++index) { | 528 | for (size_t index = 0; index < key.state.attributes.size(); ++index) { |
| 531 | const auto& attribute = key.state.attributes[index]; | 529 | const auto& attribute = key.state.attributes[index]; |
| 532 | if (!attribute.enabled || !input_attributes[index].used) { | 530 | if (!attribute.enabled || !stage_infos[0].loads.Generic(index)) { |
| 533 | continue; | 531 | continue; |
| 534 | } | 532 | } |
| 535 | vertex_attributes.push_back({ | 533 | vertex_attributes.push_back({ |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index ec06b124f..7aaa40ef2 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -123,18 +123,21 @@ Shader::AttributeType AttributeType(const FixedPipelineState& state, size_t inde | |||
| 123 | return Shader::AttributeType::Disabled; | 123 | return Shader::AttributeType::Disabled; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineCacheKey& key, | 126 | Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> programs, |
| 127 | const GraphicsPipelineCacheKey& key, | ||
| 127 | const Shader::IR::Program& program, | 128 | const Shader::IR::Program& program, |
| 128 | const Shader::IR::Program* previous_program) { | 129 | const Shader::IR::Program* previous_program) { |
| 129 | Shader::RuntimeInfo info; | 130 | Shader::RuntimeInfo info; |
| 130 | if (previous_program) { | 131 | if (previous_program) { |
| 131 | info.previous_stage_stores_generic = previous_program->info.stores_generics; | 132 | info.previous_stage_stores = previous_program->info.stores; |
| 133 | if (previous_program->is_geometry_passthrough) { | ||
| 134 | info.previous_stage_stores.mask |= previous_program->info.passthrough.mask; | ||
| 135 | } | ||
| 132 | } else { | 136 | } else { |
| 133 | // Mark all stores as available | 137 | info.previous_stage_stores.mask.set(); |
| 134 | info.previous_stage_stores_generic.flip(); | ||
| 135 | } | 138 | } |
| 136 | const Shader::Stage stage{program.stage}; | 139 | const Shader::Stage stage{program.stage}; |
| 137 | const bool has_geometry{key.unique_hashes[4] != 0}; | 140 | const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough}; |
| 138 | const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; | 141 | const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; |
| 139 | const float point_size{Common::BitCast<float>(key.state.point_size)}; | 142 | const float point_size{Common::BitCast<float>(key.state.point_size)}; |
| 140 | switch (stage) { | 143 | switch (stage) { |
| @@ -302,6 +305,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw | |||
| 302 | .support_demote_to_helper_invocation = true, | 305 | .support_demote_to_helper_invocation = true, |
| 303 | .support_int64_atomics = device.IsExtShaderAtomicInt64Supported(), | 306 | .support_int64_atomics = device.IsExtShaderAtomicInt64Supported(), |
| 304 | .support_derivative_control = true, | 307 | .support_derivative_control = true, |
| 308 | .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), | ||
| 305 | 309 | ||
| 306 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), | 310 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), |
| 307 | 311 | ||
| @@ -518,7 +522,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 518 | const size_t stage_index{index - 1}; | 522 | const size_t stage_index{index - 1}; |
| 519 | infos[stage_index] = &program.info; | 523 | infos[stage_index] = &program.info; |
| 520 | 524 | ||
| 521 | const Shader::RuntimeInfo runtime_info{MakeRuntimeInfo(key, program, previous_stage)}; | 525 | const auto runtime_info{MakeRuntimeInfo(programs, key, program, previous_stage)}; |
| 522 | const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)}; | 526 | const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)}; |
| 523 | device.SaveShader(code); | 527 | device.SaveShader(code); |
| 524 | modules[stage_index] = BuildShader(device, code); | 528 | modules[stage_index] = BuildShader(device, code); |
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index d463e2b56..429cab30d 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | namespace VideoCommon { | 22 | namespace VideoCommon { |
| 23 | 23 | ||
| 24 | constexpr std::array<char, 8> MAGIC_NUMBER{'y', 'u', 'z', 'u', 'c', 'a', 'c', 'h'}; | 24 | constexpr std::array<char, 8> MAGIC_NUMBER{'y', 'u', 'z', 'u', 'c', 'a', 'c', 'h'}; |
| 25 | constexpr u32 CACHE_VERSION = 4; | 25 | constexpr u32 CACHE_VERSION = 5; |
| 26 | 26 | ||
| 27 | constexpr size_t INST_SIZE = sizeof(u64); | 27 | constexpr size_t INST_SIZE = sizeof(u64); |
| 28 | 28 | ||
| @@ -155,6 +155,10 @@ void GenericEnvironment::Serialize(std::ofstream& file) const { | |||
| 155 | .write(reinterpret_cast<const char*>(&shared_memory_size), sizeof(shared_memory_size)); | 155 | .write(reinterpret_cast<const char*>(&shared_memory_size), sizeof(shared_memory_size)); |
| 156 | } else { | 156 | } else { |
| 157 | file.write(reinterpret_cast<const char*>(&sph), sizeof(sph)); | 157 | file.write(reinterpret_cast<const char*>(&sph), sizeof(sph)); |
| 158 | if (stage == Shader::Stage::Geometry) { | ||
| 159 | file.write(reinterpret_cast<const char*>(&gp_passthrough_mask), | ||
| 160 | sizeof(gp_passthrough_mask)); | ||
| 161 | } | ||
| 158 | } | 162 | } |
| 159 | } | 163 | } |
| 160 | 164 | ||
| @@ -202,6 +206,7 @@ GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_, | |||
| 202 | u32 start_address_) | 206 | u32 start_address_) |
| 203 | : GenericEnvironment{gpu_memory_, program_base_, start_address_}, maxwell3d{&maxwell3d_} { | 207 | : GenericEnvironment{gpu_memory_, program_base_, start_address_}, maxwell3d{&maxwell3d_} { |
| 204 | gpu_memory->ReadBlock(program_base + start_address, &sph, sizeof(sph)); | 208 | gpu_memory->ReadBlock(program_base + start_address, &sph, sizeof(sph)); |
| 209 | gp_passthrough_mask = maxwell3d->regs.gp_passthrough_mask; | ||
| 205 | switch (program) { | 210 | switch (program) { |
| 206 | case Maxwell::ShaderProgram::VertexA: | 211 | case Maxwell::ShaderProgram::VertexA: |
| 207 | stage = Shader::Stage::VertexA; | 212 | stage = Shader::Stage::VertexA; |
| @@ -319,6 +324,9 @@ void FileEnvironment::Deserialize(std::ifstream& file) { | |||
| 319 | .read(reinterpret_cast<char*>(&shared_memory_size), sizeof(shared_memory_size)); | 324 | .read(reinterpret_cast<char*>(&shared_memory_size), sizeof(shared_memory_size)); |
| 320 | } else { | 325 | } else { |
| 321 | file.read(reinterpret_cast<char*>(&sph), sizeof(sph)); | 326 | file.read(reinterpret_cast<char*>(&sph), sizeof(sph)); |
| 327 | if (stage == Shader::Stage::Geometry) { | ||
| 328 | file.read(reinterpret_cast<char*>(&gp_passthrough_mask), sizeof(gp_passthrough_mask)); | ||
| 329 | } | ||
| 322 | } | 330 | } |
| 323 | } | 331 | } |
| 324 | 332 | ||
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 7b184d2f8..da4721e6b 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -350,6 +350,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 350 | LOG_INFO(Render_Vulkan, "Device doesn't support viewport masks"); | 350 | LOG_INFO(Render_Vulkan, "Device doesn't support viewport masks"); |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | if (!nv_geometry_shader_passthrough) { | ||
| 354 | LOG_INFO(Render_Vulkan, "Device doesn't support passthrough geometry shaders"); | ||
| 355 | } | ||
| 356 | |||
| 353 | VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout; | 357 | VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout; |
| 354 | if (khr_uniform_buffer_standard_layout) { | 358 | if (khr_uniform_buffer_standard_layout) { |
| 355 | std430_layout = { | 359 | std430_layout = { |
| @@ -768,6 +772,8 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 768 | }; | 772 | }; |
| 769 | test(nv_viewport_swizzle, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME, true); | 773 | test(nv_viewport_swizzle, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME, true); |
| 770 | test(nv_viewport_array2, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, true); | 774 | test(nv_viewport_array2, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, true); |
| 775 | test(nv_geometry_shader_passthrough, VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME, | ||
| 776 | true); | ||
| 771 | test(khr_uniform_buffer_standard_layout, | 777 | test(khr_uniform_buffer_standard_layout, |
| 772 | VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, true); | 778 | VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, true); |
| 773 | test(khr_spirv_1_4, VK_KHR_SPIRV_1_4_EXTENSION_NAME, true); | 779 | test(khr_spirv_1_4, VK_KHR_SPIRV_1_4_EXTENSION_NAME, true); |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index a9c0a0e4d..d0adc0127 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -194,6 +194,11 @@ public: | |||
| 194 | return nv_viewport_array2; | 194 | return nv_viewport_array2; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | /// Returns true if the device supports VK_NV_geometry_shader_passthrough. | ||
| 198 | bool IsNvGeometryShaderPassthroughSupported() const { | ||
| 199 | return nv_geometry_shader_passthrough; | ||
| 200 | } | ||
| 201 | |||
| 197 | /// Returns true if the device supports VK_KHR_uniform_buffer_standard_layout. | 202 | /// Returns true if the device supports VK_KHR_uniform_buffer_standard_layout. |
| 198 | bool IsKhrUniformBufferStandardLayoutSupported() const { | 203 | bool IsKhrUniformBufferStandardLayoutSupported() const { |
| 199 | return khr_uniform_buffer_standard_layout; | 204 | return khr_uniform_buffer_standard_layout; |
| @@ -363,6 +368,7 @@ private: | |||
| 363 | bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil. | 368 | bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil. |
| 364 | bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle. | 369 | bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle. |
| 365 | bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2. | 370 | bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2. |
| 371 | bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough. | ||
| 366 | bool khr_uniform_buffer_standard_layout{}; ///< Support for scalar uniform buffer layouts. | 372 | bool khr_uniform_buffer_standard_layout{}; ///< Support for scalar uniform buffer layouts. |
| 367 | bool khr_spirv_1_4{}; ///< Support for VK_KHR_spirv_1_4. | 373 | bool khr_spirv_1_4{}; ///< Support for VK_KHR_spirv_1_4. |
| 368 | bool khr_workgroup_memory_explicit_layout{}; ///< Support for explicit workgroup layouts. | 374 | bool khr_workgroup_memory_explicit_layout{}; ///< Support for explicit workgroup layouts. |