diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 728d405674..ebc5a825dd 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -169,36 +169,11 @@ std::map GenerateLegacyToGenericMappings( return mapping; } -struct PassthroughVertices { - u32 count; - u32 first; - u32 stride; -}; - -PassthroughVertices GetPassthroughVertices(InputTopology input_topology) { - switch (input_topology) { - case InputTopology::Points: - return {1, 0, 1}; - case InputTopology::Lines: - return {2, 0, 1}; - case InputTopology::LinesAdjacency: - return {2, 1, 1}; - case InputTopology::Triangles: - return {3, 0, 1}; - case InputTopology::TrianglesAdjacency: - return {3, 0, 2}; - } - return {3, 0, 1}; -} - void EmitGeometryPassthrough(IR::IREmitter& ir, const IR::Program& program, const Shader::VaryingState& passthrough_mask, bool passthrough_position, - std::optional passthrough_layer_attr, - InputTopology input_topology) { - const PassthroughVertices vertices{GetPassthroughVertices(input_topology)}; - for (u32 vertex = 0; vertex < vertices.count; vertex++) { - const u32 i = vertices.first + vertex * vertices.stride; + std::optional passthrough_layer_attr) { + for (u32 i = 0; i < program.output_vertices; i++) { // Assign generics from input for (u32 j = 0; j < 32; j++) { if (!passthrough_mask.Generic(j)) { @@ -233,16 +208,25 @@ void EmitGeometryPassthrough(IR::IREmitter& ir, const IR::Program& program, ir.EndPrimitive(ir.Imm32(0)); } -void LowerGeometryPassthrough(const IR::Program& program, const HostTranslateInfo& host_info, - InputTopology input_topology) { +u32 GetOutputTopologyVertices(OutputTopology output_topology) { + switch (output_topology) { + case OutputTopology::PointList: + return 1; + case OutputTopology::LineStrip: + return 2; + default: + return 3; + } +} + +void LowerGeometryPassthrough(const IR::Program& program, const HostTranslateInfo& host_info) { for (IR::Block* const block : program.blocks) { for (IR::Inst& inst : block->Instructions()) { if (inst.GetOpcode() == IR::Opcode::Epilogue) { IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)}; EmitGeometryPassthrough( ir, program, program.info.passthrough, - program.info.passthrough.AnyComponent(IR::Attribute::PositionX), {}, - input_topology); + program.info.passthrough.AnyComponent(IR::Attribute::PositionX), {}); } } } @@ -251,8 +235,7 @@ void LowerGeometryPassthrough(const IR::Program& program, const HostTranslateInf } // Anonymous namespace IR::Program TranslateProgram(ObjectPool& inst_pool, ObjectPool& block_pool, - Environment& env, Flow::CFG& cfg, const HostTranslateInfo& host_info, - InputTopology input_topology) { + Environment& env, Flow::CFG& cfg, const HostTranslateInfo& host_info) { HostTranslateInfo normalized_host_info{host_info}; normalized_host_info.ApplyDescriptorLimitPolicy(); @@ -281,9 +264,8 @@ IR::Program TranslateProgram(ObjectPool& inst_pool, ObjectPool& inst_pool, ObjectPool& block_pool, const HostTranslateInfo& host_info, IR::Program& source_program, - Shader::OutputTopology output_topology, - InputTopology input_topology) { + Shader::OutputTopology output_topology) { IR::Program program; program.stage = Stage::Geometry; program.output_topology = output_topology; - program.output_vertices = GetPassthroughVertices(input_topology).count; + program.output_vertices = GetOutputTopologyVertices(output_topology); program.is_geometry_passthrough = false; program.info.loads.mask = source_program.info.stores.mask; @@ -452,7 +433,7 @@ IR::Program GenerateGeometryPassthrough(ObjectPool& inst_pool, IR::IREmitter ir{*current_block}; EmitGeometryPassthrough(ir, program, program.info.stores, true, - source_program.info.emulated_layer, input_topology); + source_program.info.emulated_layer); IR::Block* return_block{block_pool.Create(inst_pool)}; IR::IREmitter{*return_block}.Epilogue(); diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.h b/src/shader_recompiler/frontend/maxwell/translate_program.h index 23c7ba1bbf..fa870258b3 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.h +++ b/src/shader_recompiler/frontend/maxwell/translate_program.h @@ -21,8 +21,7 @@ namespace Shader::Maxwell { [[nodiscard]] IR::Program TranslateProgram(ObjectPool& inst_pool, ObjectPool& block_pool, Environment& env, - Flow::CFG& cfg, const HostTranslateInfo& host_info, - InputTopology input_topology); + Flow::CFG& cfg, const HostTranslateInfo& host_info); [[nodiscard]] IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b, Environment& env_vertex_b); @@ -36,7 +35,6 @@ void ConvertLegacyToGeneric(IR::Program& program, const RuntimeInfo& runtime_inf ObjectPool& block_pool, const HostTranslateInfo& host_info, IR::Program& source_program, - Shader::OutputTopology output_topology, - InputTopology input_topology); + Shader::OutputTopology output_topology); } // namespace Shader::Maxwell diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 1218c8580c..cde03d5822 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -72,25 +72,6 @@ Shader::OutputTopology MaxwellToOutputTopology(Maxwell::PrimitiveTopology topolo } } -Shader::InputTopology MaxwellToInputTopology(Maxwell::PrimitiveTopology topology) { - switch (topology) { - case Maxwell::PrimitiveTopology::Points: - return Shader::InputTopology::Points; - case Maxwell::PrimitiveTopology::Lines: - case Maxwell::PrimitiveTopology::LineLoop: - case Maxwell::PrimitiveTopology::LineStrip: - return Shader::InputTopology::Lines; - case Maxwell::PrimitiveTopology::LinesAdjacency: - case Maxwell::PrimitiveTopology::LineStripAdjacency: - return Shader::InputTopology::LinesAdjacency; - case Maxwell::PrimitiveTopology::TrianglesAdjacency: - case Maxwell::PrimitiveTopology::TriangleStripAdjacency: - return Shader::InputTopology::TrianglesAdjacency; - default: - return Shader::InputTopology::Triangles; - } -} - Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, const Shader::IR::Program& program, const Shader::IR::Program* previous_program, @@ -146,7 +127,33 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, default: break; } - info.input_topology = MaxwellToInputTopology(key.gs_input_topology); + switch (key.gs_input_topology) { + case Maxwell::PrimitiveTopology::Points: + info.input_topology = Shader::InputTopology::Points; + break; + case Maxwell::PrimitiveTopology::Lines: + case Maxwell::PrimitiveTopology::LineLoop: + case Maxwell::PrimitiveTopology::LineStrip: + info.input_topology = Shader::InputTopology::Lines; + break; + case Maxwell::PrimitiveTopology::Triangles: + case Maxwell::PrimitiveTopology::TriangleStrip: + case Maxwell::PrimitiveTopology::TriangleFan: + case Maxwell::PrimitiveTopology::Quads: + case Maxwell::PrimitiveTopology::QuadStrip: + case Maxwell::PrimitiveTopology::Polygon: + case Maxwell::PrimitiveTopology::Patches: + info.input_topology = Shader::InputTopology::Triangles; + break; + case Maxwell::PrimitiveTopology::LinesAdjacency: + case Maxwell::PrimitiveTopology::LineStripAdjacency: + info.input_topology = Shader::InputTopology::LinesAdjacency; + break; + case Maxwell::PrimitiveTopology::TrianglesAdjacency: + case Maxwell::PrimitiveTopology::TriangleStripAdjacency: + info.input_topology = Shader::InputTopology::TrianglesAdjacency; + break; + } info.glasm_use_storage_buffers = glasm_use_storage_buffers; return info; } @@ -476,10 +483,8 @@ std::unique_ptr ShaderCache::CreateGraphicsPipeline( && index == u32(Maxwell::ShaderType::Geometry); if (key.unique_hashes[index] == 0 && is_emulated_stage) { auto topology = MaxwellToOutputTopology(key.gs_input_topology); - programs[index] = - GenerateGeometryPassthrough(pools.inst, pools.block, host_info, - *layer_source_program, topology, - MaxwellToInputTopology(key.gs_input_topology)); + programs[index] = GenerateGeometryPassthrough(pools.inst, pools.block, host_info, + *layer_source_program, topology); continue; } if (key.unique_hashes[index] == 0) { @@ -497,15 +502,13 @@ std::unique_ptr ShaderCache::CreateGraphicsPipeline( if (!uses_vertex_a || index != 1) { // Normal path - programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info, - MaxwellToInputTopology(key.gs_input_topology)); + programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info); total_storage_buffers += Shader::NumDescriptors(programs[index].info.storage_buffers_descriptors); } else { // VertexB path when VertexA is present. auto& program_va{programs[0]}; - auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info, - MaxwellToInputTopology(key.gs_input_topology))}; + auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; total_storage_buffers += Shader::NumDescriptors(program_vb.info.storage_buffers_descriptors); programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); } @@ -594,8 +597,7 @@ std::unique_ptr ShaderCache::CreateComputePipeline( env.Dump(hash, key.unique_hash); } - auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info, - Shader::InputTopology::Points)}; + auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; const u32 num_storage_buffers{Shader::NumDescriptors(program.info.storage_buffers_descriptors)}; Shader::RuntimeInfo info; info.glasm_use_storage_buffers = num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks(); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 697540981d..acb4219213 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -152,25 +152,6 @@ Shader::AttributeType AttributeType(const FixedPipelineState& state, size_t inde return Shader::AttributeType::Disabled; } -Shader::InputTopology MaxwellToInputTopology(Maxwell::PrimitiveTopology topology) { - switch (topology) { - case Maxwell::PrimitiveTopology::Points: - return Shader::InputTopology::Points; - case Maxwell::PrimitiveTopology::Lines: - case Maxwell::PrimitiveTopology::LineLoop: - case Maxwell::PrimitiveTopology::LineStrip: - return Shader::InputTopology::Lines; - case Maxwell::PrimitiveTopology::LinesAdjacency: - case Maxwell::PrimitiveTopology::LineStripAdjacency: - return Shader::InputTopology::LinesAdjacency; - case Maxwell::PrimitiveTopology::TrianglesAdjacency: - case Maxwell::PrimitiveTopology::TriangleStripAdjacency: - return Shader::InputTopology::TrianglesAdjacency; - default: - return Shader::InputTopology::Triangles; - } -} - Shader::RuntimeInfo MakeRuntimeInfo(std::span programs, const GraphicsPipelineCacheKey& key, const Shader::IR::Program& program, @@ -289,7 +270,33 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span program default: break; } - info.input_topology = MaxwellToInputTopology(key.state.topology); + switch (key.state.topology) { + case Maxwell::PrimitiveTopology::Points: + info.input_topology = Shader::InputTopology::Points; + break; + case Maxwell::PrimitiveTopology::Lines: + case Maxwell::PrimitiveTopology::LineLoop: + case Maxwell::PrimitiveTopology::LineStrip: + info.input_topology = Shader::InputTopology::Lines; + break; + case Maxwell::PrimitiveTopology::Triangles: + case Maxwell::PrimitiveTopology::TriangleStrip: + case Maxwell::PrimitiveTopology::TriangleFan: + case Maxwell::PrimitiveTopology::Quads: + case Maxwell::PrimitiveTopology::QuadStrip: + case Maxwell::PrimitiveTopology::Polygon: + case Maxwell::PrimitiveTopology::Patches: + info.input_topology = Shader::InputTopology::Triangles; + break; + case Maxwell::PrimitiveTopology::LinesAdjacency: + case Maxwell::PrimitiveTopology::LineStripAdjacency: + info.input_topology = Shader::InputTopology::LinesAdjacency; + break; + case Maxwell::PrimitiveTopology::TrianglesAdjacency: + case Maxwell::PrimitiveTopology::TriangleStripAdjacency: + info.input_topology = Shader::InputTopology::TrianglesAdjacency; + break; + } info.force_early_z = key.state.early_z != 0; info.y_negate = key.state.y_negate != 0; return info; @@ -786,10 +793,8 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline( index == static_cast(Maxwell::ShaderType::Geometry); if (key.unique_hashes[index] == 0 && is_emulated_stage) { auto topology = MaxwellToOutputTopology(key.state.topology); - programs[index] = - GenerateGeometryPassthrough(pools.inst, pools.block, host_info, - *layer_source_program, topology, - MaxwellToInputTopology(key.state.topology)); + programs[index] = GenerateGeometryPassthrough(pools.inst, pools.block, host_info, + *layer_source_program, topology); continue; } if (key.unique_hashes[index] == 0) { @@ -802,13 +807,11 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline( Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0); if (!uses_vertex_a || index != 1) { // Normal path - programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info, - MaxwellToInputTopology(key.state.topology)); + programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info); } else { // VertexB path when VertexA is present. auto& program_va{programs[0]}; - auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info, - MaxwellToInputTopology(key.state.topology))}; + auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); } @@ -954,8 +957,7 @@ std::unique_ptr PipelineCache::CreateComputePipeline( env.Dump(hash, key.unique_hash); } - auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info, - Shader::InputTopology::Points)}; + auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; const VkDriverIdKHR driver_id = device.GetDriverID(); const bool needs_shared_mem_clamp = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||