diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/program.cpp | 19 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/dual_vertex_pass.cpp | 24 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/passes.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 26 |
4 files changed, 51 insertions, 19 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp index 900fc7ab1..8489f9a5f 100644 --- a/src/shader_recompiler/frontend/maxwell/program.cpp +++ b/src/shader_recompiler/frontend/maxwell/program.cpp | |||
| @@ -171,20 +171,29 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b | |||
| 171 | IR::Program result{}; | 171 | IR::Program result{}; |
| 172 | Optimization::VertexATransformPass(vertex_a); | 172 | Optimization::VertexATransformPass(vertex_a); |
| 173 | Optimization::VertexBTransformPass(vertex_b); | 173 | Optimization::VertexBTransformPass(vertex_b); |
| 174 | std::swap(result.blocks, vertex_a.blocks); | 174 | for (const auto& term : vertex_a.syntax_list) { |
| 175 | result.blocks.insert(result.blocks.end(), vertex_b.blocks.begin(), vertex_b.blocks.end()); | 175 | if (term.type == IR::AbstractSyntaxNode::Type::Return) { |
| 176 | continue; | ||
| 177 | } | ||
| 178 | result.syntax_list.push_back(term); | ||
| 179 | } | ||
| 180 | for (const auto& term : vertex_b.syntax_list) { | ||
| 181 | result.syntax_list.push_back(term); | ||
| 182 | } | ||
| 183 | result.blocks = GenerateBlocks(result.syntax_list); | ||
| 184 | result.post_order_blocks = vertex_b.post_order_blocks; | ||
| 185 | for (const auto& block : vertex_a.post_order_blocks) { | ||
| 186 | result.post_order_blocks.push_back(block); | ||
| 187 | } | ||
| 176 | result.stage = Stage::VertexB; | 188 | result.stage = Stage::VertexB; |
| 177 | result.info = vertex_a.info; | 189 | result.info = vertex_a.info; |
| 178 | result.local_memory_size = std::max(vertex_a.local_memory_size, vertex_b.local_memory_size); | 190 | result.local_memory_size = std::max(vertex_a.local_memory_size, vertex_b.local_memory_size); |
| 179 | |||
| 180 | for (size_t index = 0; index < 32; ++index) { | 191 | for (size_t index = 0; index < 32; ++index) { |
| 181 | result.info.input_generics[index].used |= vertex_b.info.input_generics[index].used; | 192 | result.info.input_generics[index].used |= vertex_b.info.input_generics[index].used; |
| 182 | result.info.stores_generics[index] |= vertex_b.info.stores_generics[index]; | 193 | result.info.stores_generics[index] |= vertex_b.info.stores_generics[index]; |
| 183 | } | 194 | } |
| 184 | Optimization::JoinTextureInfo(result.info, vertex_b.info); | 195 | Optimization::JoinTextureInfo(result.info, vertex_b.info); |
| 185 | Optimization::JoinStorageInfo(result.info, vertex_b.info); | 196 | Optimization::JoinStorageInfo(result.info, vertex_b.info); |
| 186 | Optimization::DualVertexJoinPass(result); | ||
| 187 | result.post_order_blocks = PostOrder(result.syntax_list.front()); | ||
| 188 | Optimization::DeadCodeEliminationPass(result); | 197 | Optimization::DeadCodeEliminationPass(result); |
| 189 | Optimization::VerificationPass(result); | 198 | Optimization::VerificationPass(result); |
| 190 | Optimization::CollectShaderInfoPass(env_vertex_b, result); | 199 | Optimization::CollectShaderInfoPass(env_vertex_b, result); |
diff --git a/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp b/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp index b0a9f5258..a926123f2 100644 --- a/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp +++ b/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp | |||
| @@ -13,16 +13,24 @@ | |||
| 13 | 13 | ||
| 14 | namespace Shader::Optimization { | 14 | namespace Shader::Optimization { |
| 15 | 15 | ||
| 16 | void VertexATransformPass(IR::Program&) { | 16 | void VertexATransformPass(IR::Program& program) { |
| 17 | throw NotImplementedException("VertexA pass"); | 17 | for (IR::Block* const block : program.blocks) { |
| 18 | for (IR::Inst& inst : block->Instructions()) { | ||
| 19 | if (inst.GetOpcode() == IR::Opcode::Epilogue) { | ||
| 20 | return inst.Invalidate(); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | } | ||
| 18 | } | 24 | } |
| 19 | 25 | ||
| 20 | void VertexBTransformPass(IR::Program&) { | 26 | void VertexBTransformPass(IR::Program& program) { |
| 21 | throw NotImplementedException("VertexA pass"); | 27 | for (IR::Block* const block : program.blocks) { |
| 22 | } | 28 | for (IR::Inst& inst : block->Instructions()) { |
| 23 | 29 | if (inst.GetOpcode() == IR::Opcode::Prologue) { | |
| 24 | void DualVertexJoinPass(IR::Program&) { | 30 | return inst.Invalidate(); |
| 25 | throw NotImplementedException("VertexA pass"); | 31 | } |
| 32 | } | ||
| 33 | } | ||
| 26 | } | 34 | } |
| 27 | 35 | ||
| 28 | } // namespace Shader::Optimization | 36 | } // namespace Shader::Optimization |
diff --git a/src/shader_recompiler/ir_opt/passes.h b/src/shader_recompiler/ir_opt/passes.h index e9cb8546a..5ebde49ea 100644 --- a/src/shader_recompiler/ir_opt/passes.h +++ b/src/shader_recompiler/ir_opt/passes.h | |||
| @@ -25,7 +25,6 @@ void VerificationPass(const IR::Program& program); | |||
| 25 | // Dual Vertex | 25 | // Dual Vertex |
| 26 | void VertexATransformPass(IR::Program& program); | 26 | void VertexATransformPass(IR::Program& program); |
| 27 | void VertexBTransformPass(IR::Program& program); | 27 | void VertexBTransformPass(IR::Program& program); |
| 28 | void DualVertexJoinPass(IR::Program& program); | ||
| 29 | void JoinTextureInfo(Info& base, Info& source); | 28 | void JoinTextureInfo(Info& base, Info& source); |
| 30 | void JoinStorageInfo(Info& base, Info& source); | 29 | void JoinStorageInfo(Info& base, Info& source); |
| 31 | 30 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index bdffac4b2..0e4904733 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -40,6 +40,7 @@ namespace OpenGL { | |||
| 40 | namespace { | 40 | namespace { |
| 41 | using Shader::Backend::GLASM::EmitGLASM; | 41 | using Shader::Backend::GLASM::EmitGLASM; |
| 42 | using Shader::Backend::SPIRV::EmitSPIRV; | 42 | using Shader::Backend::SPIRV::EmitSPIRV; |
| 43 | using Shader::Maxwell::MergeDualVertexPrograms; | ||
| 43 | using Shader::Maxwell::TranslateProgram; | 44 | using Shader::Maxwell::TranslateProgram; |
| 44 | using VideoCommon::ComputeEnvironment; | 45 | using VideoCommon::ComputeEnvironment; |
| 45 | using VideoCommon::FileEnvironment; | 46 | using VideoCommon::FileEnvironment; |
| @@ -446,6 +447,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 446 | size_t env_index{}; | 447 | size_t env_index{}; |
| 447 | u32 total_storage_buffers{}; | 448 | u32 total_storage_buffers{}; |
| 448 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; | 449 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; |
| 450 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; | ||
| 451 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; | ||
| 449 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 452 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| 450 | if (key.unique_hashes[index] == 0) { | 453 | if (key.unique_hashes[index] == 0) { |
| 451 | continue; | 454 | continue; |
| @@ -454,11 +457,22 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 454 | ++env_index; | 457 | ++env_index; |
| 455 | 458 | ||
| 456 | const u32 cfg_offset{static_cast<u32>(env.StartAddress() + sizeof(Shader::ProgramHeader))}; | 459 | const u32 cfg_offset{static_cast<u32>(env.StartAddress() + sizeof(Shader::ProgramHeader))}; |
| 457 | Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset); | 460 | Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0); |
| 458 | programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg); | 461 | if (!uses_vertex_a || index != 1) { |
| 462 | // Normal path | ||
| 463 | programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg); | ||
| 459 | 464 | ||
| 460 | for (const auto& desc : programs[index].info.storage_buffers_descriptors) { | 465 | for (const auto& desc : programs[index].info.storage_buffers_descriptors) { |
| 461 | total_storage_buffers += desc.count; | 466 | total_storage_buffers += desc.count; |
| 467 | } | ||
| 468 | } else { | ||
| 469 | // VertexB path when VertexA is present. | ||
| 470 | Shader::IR::Program& program_va{programs[0]}; | ||
| 471 | Shader::IR::Program program_vb{TranslateProgram(pools.inst, pools.block, env, cfg)}; | ||
| 472 | for (const auto& desc : program_vb.info.storage_buffers_descriptors) { | ||
| 473 | total_storage_buffers += desc.count; | ||
| 474 | } | ||
| 475 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); | ||
| 462 | } | 476 | } |
| 463 | } | 477 | } |
| 464 | const u32 glasm_storage_buffer_limit{device.GetMaxGLASMStorageBufferBlocks()}; | 478 | const u32 glasm_storage_buffer_limit{device.GetMaxGLASMStorageBufferBlocks()}; |
| @@ -472,7 +486,9 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 472 | if (!device.UseAssemblyShaders()) { | 486 | if (!device.UseAssemblyShaders()) { |
| 473 | source_program.handle = glCreateProgram(); | 487 | source_program.handle = glCreateProgram(); |
| 474 | } | 488 | } |
| 475 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 489 | |
| 490 | for (size_t index = uses_vertex_a && uses_vertex_b ? 1 : 0; index < Maxwell::MaxShaderProgram; | ||
| 491 | ++index) { | ||
| 476 | if (key.unique_hashes[index] == 0) { | 492 | if (key.unique_hashes[index] == 0) { |
| 477 | continue; | 493 | continue; |
| 478 | } | 494 | } |