diff options
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
-rw-r--r-- | src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp | 8 | ||||
-rw-r--r-- | src/shader_recompiler/frontend/maxwell/translate_program.cpp | 118 |
2 files changed, 80 insertions, 46 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp index f8cfd4ab6..39af62559 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp @@ -15,11 +15,13 @@ enum class Mode : u64 { SamplePos = 5, }; -IR::Value Query(TranslatorVisitor& v, const IR::U32& handle, Mode mode, IR::Reg src_reg) { +IR::Value Query(TranslatorVisitor& v, const IR::U32& handle, Mode mode, IR::Reg src_reg, u64 mask) { switch (mode) { case Mode::Dimension: { + const bool needs_num_mips{((mask >> 3) & 1) != 0}; + const IR::U1 skip_mips{v.ir.Imm1(!needs_num_mips)}; const IR::U32 lod{v.X(src_reg)}; - return v.ir.ImageQueryDimension(handle, lod); + return v.ir.ImageQueryDimension(handle, lod, skip_mips); } case Mode::TextureType: case Mode::SamplePos: @@ -46,7 +48,7 @@ void Impl(TranslatorVisitor& v, u64 insn, std::optional<u32> cbuf_offset) { handle = v.X(src_reg); ++src_reg; } - const IR::Value query{Query(v, handle, txq.mode, src_reg)}; + const IR::Value query{Query(v, handle, txq.mode, src_reg, txq.mask)}; IR::Reg dest_reg{txq.dest_reg}; for (int element = 0; element < 4; ++element) { if (((txq.mask >> element) & 1) == 0) { diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 3adbd2b16..a42453e90 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -171,6 +171,70 @@ std::map<IR::Attribute, IR::Attribute> GenerateLegacyToGenericMappings( } return mapping; } + +void EmitGeometryPassthrough(IR::IREmitter& ir, const IR::Program& program, + const Shader::VaryingState& passthrough_mask, + bool passthrough_position, + std::optional<IR::Attribute> 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)) { + continue; + } + + const IR::Attribute attr = IR::Attribute::Generic0X + (j * 4); + ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0)); + ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0)); + ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0)); + ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0)); + } + + if (passthrough_position) { + // Assign position from input + const IR::Attribute attr = IR::Attribute::PositionX; + ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0)); + ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0)); + ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0)); + ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0)); + } + + if (passthrough_layer_attr) { + // Assign layer + ir.SetAttribute(IR::Attribute::Layer, ir.GetAttribute(*passthrough_layer_attr), + ir.Imm32(0)); + } + + // Emit vertex + ir.EmitVertex(ir.Imm32(0)); + } + ir.EndPrimitive(ir.Imm32(0)); +} + +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), {}); + } + } + } +} + } // Anonymous namespace IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Block>& block_pool, @@ -195,9 +259,14 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo program.is_geometry_passthrough = sph.common0.geometry_passthrough != 0; if (program.is_geometry_passthrough) { const auto& mask{env.GpPassthroughMask()}; - for (size_t i = 0; i < program.info.passthrough.mask.size(); ++i) { + for (size_t i = 0; i < mask.size() * 32; ++i) { program.info.passthrough.mask[i] = ((mask[i / 32] >> (i % 32)) & 1) == 0; } + + if (!host_info.support_geometry_shader_passthrough) { + program.output_vertices = GetOutputTopologyVertices(program.output_topology); + LowerGeometryPassthrough(program, host_info); + } } break; } @@ -219,11 +288,11 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo } Optimization::SsaRewritePass(program); - Optimization::ConstantPropagationPass(program); + Optimization::ConstantPropagationPass(env, program); Optimization::PositionPass(env, program); - Optimization::GlobalMemoryToStorageBufferPass(program); + Optimization::GlobalMemoryToStorageBufferPass(program, host_info); Optimization::TexturePass(env, program, host_info); if (Settings::values.resolution_info.active) { @@ -342,17 +411,7 @@ IR::Program GenerateGeometryPassthrough(ObjectPool<IR::Inst>& inst_pool, IR::Program program; program.stage = Stage::Geometry; program.output_topology = output_topology; - switch (output_topology) { - case OutputTopology::PointList: - program.output_vertices = 1; - break; - case OutputTopology::LineStrip: - program.output_vertices = 2; - break; - default: - program.output_vertices = 3; - break; - } + program.output_vertices = GetOutputTopologyVertices(output_topology); program.is_geometry_passthrough = false; program.info.loads.mask = source_program.info.stores.mask; @@ -366,35 +425,8 @@ IR::Program GenerateGeometryPassthrough(ObjectPool<IR::Inst>& inst_pool, node.data.block = current_block; IR::IREmitter ir{*current_block}; - for (u32 i = 0; i < program.output_vertices; i++) { - // Assign generics from input - for (u32 j = 0; j < 32; j++) { - if (!program.info.stores.Generic(j)) { - continue; - } - - const IR::Attribute attr = IR::Attribute::Generic0X + (j * 4); - ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0)); - ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0)); - ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0)); - ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0)); - } - - // Assign position from input - const IR::Attribute attr = IR::Attribute::PositionX; - ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0)); - ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0)); - ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0)); - ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0)); - - // Assign layer - ir.SetAttribute(IR::Attribute::Layer, ir.GetAttribute(source_program.info.emulated_layer), - ir.Imm32(0)); - - // Emit vertex - ir.EmitVertex(ir.Imm32(0)); - } - ir.EndPrimitive(ir.Imm32(0)); + EmitGeometryPassthrough(ir, program, program.info.stores, true, + source_program.info.emulated_layer); IR::Block* return_block{block_pool.Create(inst_pool)}; IR::IREmitter{*return_block}.Epilogue(); |