diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 37 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 33 |
2 files changed, 65 insertions, 5 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 3fe04a115..a38060100 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -39,6 +39,7 @@ using Shader::Backend::GLASM::EmitGLASM; | |||
| 39 | using Shader::Backend::GLSL::EmitGLSL; | 39 | using Shader::Backend::GLSL::EmitGLSL; |
| 40 | using Shader::Backend::SPIRV::EmitSPIRV; | 40 | using Shader::Backend::SPIRV::EmitSPIRV; |
| 41 | using Shader::Maxwell::ConvertLegacyToGeneric; | 41 | using Shader::Maxwell::ConvertLegacyToGeneric; |
| 42 | using Shader::Maxwell::GenerateGeometryPassthrough; | ||
| 42 | using Shader::Maxwell::MergeDualVertexPrograms; | 43 | using Shader::Maxwell::MergeDualVertexPrograms; |
| 43 | using Shader::Maxwell::TranslateProgram; | 44 | using Shader::Maxwell::TranslateProgram; |
| 44 | using VideoCommon::ComputeEnvironment; | 45 | using VideoCommon::ComputeEnvironment; |
| @@ -56,6 +57,17 @@ auto MakeSpan(Container& container) { | |||
| 56 | return std::span(container.data(), container.size()); | 57 | return std::span(container.data(), container.size()); |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 60 | Shader::OutputTopology MaxwellToOutputTopology(Maxwell::PrimitiveTopology topology) { | ||
| 61 | switch (topology) { | ||
| 62 | case Maxwell::PrimitiveTopology::Points: | ||
| 63 | return Shader::OutputTopology::PointList; | ||
| 64 | case Maxwell::PrimitiveTopology::LineStrip: | ||
| 65 | return Shader::OutputTopology::LineStrip; | ||
| 66 | default: | ||
| 67 | return Shader::OutputTopology::TriangleStrip; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 59 | Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, | 71 | Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, |
| 60 | const Shader::IR::Program& program, | 72 | const Shader::IR::Program& program, |
| 61 | const Shader::IR::Program* previous_program, | 73 | const Shader::IR::Program* previous_program, |
| @@ -220,6 +232,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo | |||
| 220 | .support_int64 = device.HasShaderInt64(), | 232 | .support_int64 = device.HasShaderInt64(), |
| 221 | .needs_demote_reorder = device.IsAmd(), | 233 | .needs_demote_reorder = device.IsAmd(), |
| 222 | .support_snorm_render_buffer = false, | 234 | .support_snorm_render_buffer = false, |
| 235 | .support_viewport_index_layer = device.HasVertexViewportLayer(), | ||
| 223 | } { | 236 | } { |
| 224 | if (use_asynchronous_shaders) { | 237 | if (use_asynchronous_shaders) { |
| 225 | workers = CreateWorkers(); | 238 | workers = CreateWorkers(); |
| @@ -314,9 +327,7 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | |||
| 314 | const auto& regs{maxwell3d->regs}; | 327 | const auto& regs{maxwell3d->regs}; |
| 315 | graphics_key.raw = 0; | 328 | graphics_key.raw = 0; |
| 316 | graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0); | 329 | graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0); |
| 317 | graphics_key.gs_input_topology.Assign(graphics_key.unique_hashes[4] != 0 | 330 | graphics_key.gs_input_topology.Assign(regs.draw.topology.Value()); |
| 318 | ? regs.draw.topology.Value() | ||
| 319 | : Maxwell::PrimitiveTopology{}); | ||
| 320 | graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value()); | 331 | graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value()); |
| 321 | graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value()); | 332 | graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value()); |
| 322 | graphics_key.tessellation_clockwise.Assign( | 333 | graphics_key.tessellation_clockwise.Assign( |
| @@ -415,7 +426,19 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 415 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; | 426 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; |
| 416 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; | 427 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; |
| 417 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; | 428 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; |
| 429 | |||
| 430 | // Layer passthrough generation for devices without GL_ARB_shader_viewport_layer_array | ||
| 431 | Shader::IR::Program* layer_source_program{}; | ||
| 432 | |||
| 418 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 433 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| 434 | const bool is_emulated_stage = layer_source_program != nullptr && | ||
| 435 | index == static_cast<u32>(Maxwell::ShaderType::Geometry); | ||
| 436 | if (key.unique_hashes[index] == 0 && is_emulated_stage) { | ||
| 437 | auto topology = MaxwellToOutputTopology(key.gs_input_topology); | ||
| 438 | programs[index] = GenerateGeometryPassthrough(pools.inst, pools.block, host_info, | ||
| 439 | *layer_source_program, topology); | ||
| 440 | continue; | ||
| 441 | } | ||
| 419 | if (key.unique_hashes[index] == 0) { | 442 | if (key.unique_hashes[index] == 0) { |
| 420 | continue; | 443 | continue; |
| 421 | } | 444 | } |
| @@ -443,6 +466,10 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 443 | Shader::NumDescriptors(program_vb.info.storage_buffers_descriptors); | 466 | Shader::NumDescriptors(program_vb.info.storage_buffers_descriptors); |
| 444 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); | 467 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); |
| 445 | } | 468 | } |
| 469 | |||
| 470 | if (programs[index].info.requires_layer_emulation) { | ||
| 471 | layer_source_program = &programs[index]; | ||
| 472 | } | ||
| 446 | } | 473 | } |
| 447 | const u32 glasm_storage_buffer_limit{device.GetMaxGLASMStorageBufferBlocks()}; | 474 | const u32 glasm_storage_buffer_limit{device.GetMaxGLASMStorageBufferBlocks()}; |
| 448 | const bool glasm_use_storage_buffers{total_storage_buffers <= glasm_storage_buffer_limit}; | 475 | const bool glasm_use_storage_buffers{total_storage_buffers <= glasm_storage_buffer_limit}; |
| @@ -456,7 +483,9 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 456 | const bool use_glasm{device.UseAssemblyShaders()}; | 483 | const bool use_glasm{device.UseAssemblyShaders()}; |
| 457 | const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0; | 484 | const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0; |
| 458 | for (size_t index = first_index; index < Maxwell::MaxShaderProgram; ++index) { | 485 | for (size_t index = first_index; index < Maxwell::MaxShaderProgram; ++index) { |
| 459 | if (key.unique_hashes[index] == 0) { | 486 | const bool is_emulated_stage = layer_source_program != nullptr && |
| 487 | index == static_cast<u32>(Maxwell::ShaderType::Geometry); | ||
| 488 | if (key.unique_hashes[index] == 0 && !is_emulated_stage) { | ||
| 460 | continue; | 489 | continue; |
| 461 | } | 490 | } |
| 462 | UNIMPLEMENTED_IF(index == 0); | 491 | UNIMPLEMENTED_IF(index == 0); |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index d4b0a542a..150413b04 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -46,6 +46,7 @@ MICROPROFILE_DECLARE(Vulkan_PipelineCache); | |||
| 46 | namespace { | 46 | namespace { |
| 47 | using Shader::Backend::SPIRV::EmitSPIRV; | 47 | using Shader::Backend::SPIRV::EmitSPIRV; |
| 48 | using Shader::Maxwell::ConvertLegacyToGeneric; | 48 | using Shader::Maxwell::ConvertLegacyToGeneric; |
| 49 | using Shader::Maxwell::GenerateGeometryPassthrough; | ||
| 49 | using Shader::Maxwell::MergeDualVertexPrograms; | 50 | using Shader::Maxwell::MergeDualVertexPrograms; |
| 50 | using Shader::Maxwell::TranslateProgram; | 51 | using Shader::Maxwell::TranslateProgram; |
| 51 | using VideoCommon::ComputeEnvironment; | 52 | using VideoCommon::ComputeEnvironment; |
| @@ -60,6 +61,17 @@ auto MakeSpan(Container& container) { | |||
| 60 | return std::span(container.data(), container.size()); | 61 | return std::span(container.data(), container.size()); |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 64 | Shader::OutputTopology MaxwellToOutputTopology(Maxwell::PrimitiveTopology topology) { | ||
| 65 | switch (topology) { | ||
| 66 | case Maxwell::PrimitiveTopology::Points: | ||
| 67 | return Shader::OutputTopology::PointList; | ||
| 68 | case Maxwell::PrimitiveTopology::LineStrip: | ||
| 69 | return Shader::OutputTopology::LineStrip; | ||
| 70 | default: | ||
| 71 | return Shader::OutputTopology::TriangleStrip; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 63 | Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) { | 75 | Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) { |
| 64 | switch (comparison) { | 76 | switch (comparison) { |
| 65 | case Maxwell::ComparisonOp::Never_D3D: | 77 | case Maxwell::ComparisonOp::Never_D3D: |
| @@ -327,6 +339,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 327 | .needs_demote_reorder = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY_KHR || | 339 | .needs_demote_reorder = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY_KHR || |
| 328 | driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR, | 340 | driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR, |
| 329 | .support_snorm_render_buffer = true, | 341 | .support_snorm_render_buffer = true, |
| 342 | .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(), | ||
| 330 | }; | 343 | }; |
| 331 | } | 344 | } |
| 332 | 345 | ||
| @@ -509,7 +522,19 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 509 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; | 522 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; |
| 510 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; | 523 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; |
| 511 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; | 524 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; |
| 525 | |||
| 526 | // Layer passthrough generation for devices without VK_EXT_shader_viewport_index_layer | ||
| 527 | Shader::IR::Program* layer_source_program{}; | ||
| 528 | |||
| 512 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 529 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| 530 | const bool is_emulated_stage = layer_source_program != nullptr && | ||
| 531 | index == static_cast<u32>(Maxwell::ShaderType::Geometry); | ||
| 532 | if (key.unique_hashes[index] == 0 && is_emulated_stage) { | ||
| 533 | auto topology = MaxwellToOutputTopology(key.state.topology); | ||
| 534 | programs[index] = GenerateGeometryPassthrough(pools.inst, pools.block, host_info, | ||
| 535 | *layer_source_program, topology); | ||
| 536 | continue; | ||
| 537 | } | ||
| 513 | if (key.unique_hashes[index] == 0) { | 538 | if (key.unique_hashes[index] == 0) { |
| 514 | continue; | 539 | continue; |
| 515 | } | 540 | } |
| @@ -530,6 +555,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 530 | auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; | 555 | auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; |
| 531 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); | 556 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); |
| 532 | } | 557 | } |
| 558 | |||
| 559 | if (programs[index].info.requires_layer_emulation) { | ||
| 560 | layer_source_program = &programs[index]; | ||
| 561 | } | ||
| 533 | } | 562 | } |
| 534 | std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{}; | 563 | std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{}; |
| 535 | std::array<vk::ShaderModule, Maxwell::MaxShaderStage> modules; | 564 | std::array<vk::ShaderModule, Maxwell::MaxShaderStage> modules; |
| @@ -538,7 +567,9 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 538 | Shader::Backend::Bindings binding; | 567 | Shader::Backend::Bindings binding; |
| 539 | for (size_t index = uses_vertex_a && uses_vertex_b ? 1 : 0; index < Maxwell::MaxShaderProgram; | 568 | for (size_t index = uses_vertex_a && uses_vertex_b ? 1 : 0; index < Maxwell::MaxShaderProgram; |
| 540 | ++index) { | 569 | ++index) { |
| 541 | if (key.unique_hashes[index] == 0) { | 570 | const bool is_emulated_stage = layer_source_program != nullptr && |
| 571 | index == static_cast<u32>(Maxwell::ShaderType::Geometry); | ||
| 572 | if (key.unique_hashes[index] == 0 && !is_emulated_stage) { | ||
| 542 | continue; | 573 | continue; |
| 543 | } | 574 | } |
| 544 | UNIMPLEMENTED_IF(index == 0); | 575 | UNIMPLEMENTED_IF(index == 0); |