diff options
Diffstat (limited to 'src/shader_recompiler')
16 files changed, 176 insertions, 7 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp index f0bd84ab2..c7d7d5fef 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp @@ -137,6 +137,15 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal case IR::Attribute::VertexId: ctx.Add("MOV.F {}.x,{}.id;", inst, ctx.attrib_name); break; + case IR::Attribute::BaseInstance: + ctx.Add("MOV.F {}.x,{}.baseInstance;", inst, ctx.attrib_name); + break; + case IR::Attribute::BaseVertex: + ctx.Add("MOV.F {}.x,{}.baseVertex;", inst, ctx.attrib_name); + break; + case IR::Attribute::DrawID: + ctx.Add("MOV.F {}.x,{}.draw.id;", inst, ctx.attrib_name); + break; case IR::Attribute::FrontFace: ctx.Add("CMP.F {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name); break; @@ -156,6 +165,15 @@ void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, S case IR::Attribute::VertexId: ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name); break; + case IR::Attribute::BaseInstance: + ctx.Add("MOV.S {}.x,{}.baseInstance;", inst, ctx.attrib_name); + break; + case IR::Attribute::BaseVertex: + ctx.Add("MOV.S {}.x,{}.baseVertex;", inst, ctx.attrib_name); + break; + case IR::Attribute::DrawID: + ctx.Add("MOV.S {}.x,{}.draw.id;", inst, ctx.attrib_name); + break; default: throw NotImplementedException("Get U32 attribute {}", attr); } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp index e8a4390f6..d91e04446 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp @@ -219,7 +219,7 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo& runtime_info, IR EmitContext ctx{program, bindings, profile, runtime_info}; Precolor(program); EmitCode(ctx, program); - const std::string version{fmt::format("#version 450{}\n", GlslVersionSpecifier(ctx))}; + const std::string version{fmt::format("#version 460{}\n", GlslVersionSpecifier(ctx))}; ctx.header.insert(0, version); if (program.shared_memory_size > 0) { const auto requested_size{program.shared_memory_size}; diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index 39579cf5d..2e369ed72 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp @@ -234,6 +234,15 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, case IR::Attribute::FrontFace: ctx.AddF32("{}=itof(gl_FrontFacing?-1:0);", inst); break; + case IR::Attribute::BaseInstance: + ctx.AddF32("{}=itof(gl_BaseInstance);", inst); + break; + case IR::Attribute::BaseVertex: + ctx.AddF32("{}=itof(gl_BaseVertex);", inst); + break; + case IR::Attribute::DrawID: + ctx.AddF32("{}=itof(gl_DrawID);", inst); + break; default: throw NotImplementedException("Get attribute {}", attr); } @@ -250,6 +259,15 @@ void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, s case IR::Attribute::VertexId: ctx.AddU32("{}=uint(gl_VertexID);", inst); break; + case IR::Attribute::BaseInstance: + ctx.AddU32("{}=uint(gl_BaseInstance);", inst); + break; + case IR::Attribute::BaseVertex: + ctx.AddU32("{}=uint(gl_BaseVertex);", inst); + break; + case IR::Attribute::DrawID: + ctx.AddU32("{}=uint(gl_DrawID);", inst); + break; default: throw NotImplementedException("Get U32 attribute {}", attr); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 73b67f0af..db9c94ce8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -339,6 +339,12 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base)); } + case IR::Attribute::BaseInstance: + return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_instance)); + case IR::Attribute::BaseVertex: + return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_vertex)); + case IR::Attribute::DrawID: + return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.draw_index)); case IR::Attribute::FrontFace: return ctx.OpSelect(ctx.F32[1], ctx.OpLoad(ctx.U1, ctx.front_face), ctx.OpBitcast(ctx.F32[1], ctx.Const(std::numeric_limits<u32>::max())), @@ -380,6 +386,12 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id) { const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; return ctx.OpISub(ctx.U32[1], index, base); } + case IR::Attribute::BaseInstance: + return ctx.OpLoad(ctx.U32[1], ctx.base_instance); + case IR::Attribute::BaseVertex: + return ctx.OpLoad(ctx.U32[1], ctx.base_vertex); + case IR::Attribute::DrawID: + return ctx.OpLoad(ctx.U32[1], ctx.draw_index); default: throw NotImplementedException("Read U32 attribute {}", attr); } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 41dc6d031..ecb2db494 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -1379,18 +1379,31 @@ void EmitContext::DefineInputs(const IR::Program& program) { if (loads[IR::Attribute::InstanceId]) { if (profile.support_vertex_instance_id) { instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId); + if (loads[IR::Attribute::BaseInstance]) { + base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); + } } else { instance_index = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceIndex); base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance); } + } else if (loads[IR::Attribute::BaseInstance]) { + base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance); } if (loads[IR::Attribute::VertexId]) { if (profile.support_vertex_instance_id) { vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId); + if (loads[IR::Attribute::BaseVertex]) { + base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); + } } else { vertex_index = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexIndex); base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); } + } else if (loads[IR::Attribute::BaseVertex]) { + base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); + } + if (loads[IR::Attribute::DrawID]) { + draw_index = DefineInput(*this, U32[1], true, spv::BuiltIn::DrawIndex); } if (loads[IR::Attribute::FrontFace]) { front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index dde45b4bc..4414a5169 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -218,6 +218,7 @@ public: Id base_instance{}; Id vertex_id{}; Id vertex_index{}; + Id draw_index{}; Id base_vertex{}; Id front_face{}; Id point_coord{}; diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h index 402f2664f..26e8307c1 100644 --- a/src/shader_recompiler/environment.h +++ b/src/shader_recompiler/environment.h @@ -34,6 +34,11 @@ public: [[nodiscard]] virtual std::array<u32, 3> WorkgroupSize() const = 0; + [[nodiscard]] virtual bool HasHLEMacroState() const = 0; + + [[nodiscard]] virtual std::optional<ReplaceConstant> GetReplaceConstBuffer(u32 bank, + u32 offset) = 0; + virtual void Dump(u64 hash) = 0; [[nodiscard]] const ProgramHeader& SPH() const noexcept { @@ -52,11 +57,16 @@ public: return start_address; } + [[nodiscard]] bool IsPropietaryDriver() const noexcept { + return is_propietary_driver; + } + protected: ProgramHeader sph{}; std::array<u32, 8> gp_passthrough_mask{}; Stage stage{}; u32 start_address{}; + bool is_propietary_driver{}; }; } // namespace Shader diff --git a/src/shader_recompiler/frontend/ir/attribute.cpp b/src/shader_recompiler/frontend/ir/attribute.cpp index 7d3d882e4..1bf9db935 100644 --- a/src/shader_recompiler/frontend/ir/attribute.cpp +++ b/src/shader_recompiler/frontend/ir/attribute.cpp @@ -446,6 +446,12 @@ std::string NameOf(Attribute attribute) { return "ViewportMask"; case Attribute::FrontFace: return "FrontFace"; + case Attribute::BaseInstance: + return "BaseInstance"; + case Attribute::BaseVertex: + return "BaseVertex"; + case Attribute::DrawID: + return "DrawID"; } return fmt::format("<reserved attribute {}>", static_cast<int>(attribute)); } diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h index 6ee3947b1..5f039b6f6 100644 --- a/src/shader_recompiler/frontend/ir/attribute.h +++ b/src/shader_recompiler/frontend/ir/attribute.h @@ -219,6 +219,11 @@ enum class Attribute : u64 { FixedFncTexture9Q = 231, ViewportMask = 232, FrontFace = 255, + + // Implementation attributes + BaseInstance = 256, + BaseVertex = 257, + DrawID = 258, }; constexpr size_t NUM_GENERICS = 32; diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 0cdac0eff..eb2e49a68 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp @@ -294,6 +294,14 @@ F32 IREmitter::GetAttribute(IR::Attribute attribute, const U32& vertex) { return Inst<F32>(Opcode::GetAttribute, attribute, vertex); } +U32 IREmitter::GetAttributeU32(IR::Attribute attribute) { + return GetAttributeU32(attribute, Imm32(0)); +} + +U32 IREmitter::GetAttributeU32(IR::Attribute attribute, const U32& vertex) { + return Inst<U32>(Opcode::GetAttributeU32, attribute, vertex); +} + void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex) { Inst(Opcode::SetAttribute, attribute, value, vertex); } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 2df992feb..7aaaa4ab0 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h @@ -74,6 +74,8 @@ public: [[nodiscard]] F32 GetAttribute(IR::Attribute attribute); [[nodiscard]] F32 GetAttribute(IR::Attribute attribute, const U32& vertex); + [[nodiscard]] U32 GetAttributeU32(IR::Attribute attribute); + [[nodiscard]] U32 GetAttributeU32(IR::Attribute attribute, const U32& vertex); void SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex); [[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address); diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 3adbd2b16..ac159d24b 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -219,7 +219,7 @@ 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); diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index 826f9a54a..4d81e9336 100644 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp @@ -7,6 +7,7 @@ #include <type_traits> #include "common/bit_cast.h" +#include "shader_recompiler/environment.h" #include "shader_recompiler/exception.h" #include "shader_recompiler/frontend/ir/ir_emitter.h" #include "shader_recompiler/frontend/ir/value.h" @@ -515,6 +516,9 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) { case IR::Attribute::PrimitiveId: case IR::Attribute::InstanceId: case IR::Attribute::VertexId: + case IR::Attribute::BaseVertex: + case IR::Attribute::BaseInstance: + case IR::Attribute::DrawID: break; default: return; @@ -644,7 +648,63 @@ void FoldFSwizzleAdd(IR::Block& block, IR::Inst& inst) { } } -void ConstantPropagation(IR::Block& block, IR::Inst& inst) { +void FoldConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst) { + const IR::Value bank{inst.Arg(0)}; + const IR::Value offset{inst.Arg(1)}; + if (!bank.IsImmediate() || !offset.IsImmediate()) { + return; + } + const auto bank_value = bank.U32(); + const auto offset_value = offset.U32(); + auto replacement = env.GetReplaceConstBuffer(bank_value, offset_value); + if (!replacement) { + return; + } + const auto new_attribute = [replacement]() { + switch (*replacement) { + case ReplaceConstant::BaseInstance: + return IR::Attribute::BaseInstance; + case ReplaceConstant::BaseVertex: + return IR::Attribute::BaseVertex; + case ReplaceConstant::DrawID: + return IR::Attribute::DrawID; + default: + throw NotImplementedException("Not implemented replacement variable {}", *replacement); + } + }(); + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + if (inst.GetOpcode() == IR::Opcode::GetCbufU32) { + inst.ReplaceUsesWith(ir.GetAttributeU32(new_attribute)); + } else { + inst.ReplaceUsesWith(ir.GetAttribute(new_attribute)); + } +} + +void FoldDriverConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst, u32 which_bank, + u32 offset_start = 0, u32 offset_end = std::numeric_limits<u16>::max()) { + const IR::Value bank{inst.Arg(0)}; + const IR::Value offset{inst.Arg(1)}; + if (!bank.IsImmediate() || !offset.IsImmediate()) { + return; + } + const auto bank_value = bank.U32(); + if (bank_value != which_bank) { + return; + } + const auto offset_value = offset.U32(); + if (offset_value < offset_start || offset_value >= offset_end) { + return; + } + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + if (inst.GetOpcode() == IR::Opcode::GetCbufU32) { + inst.ReplaceUsesWith(IR::Value{env.ReadCbufValue(bank_value, offset_value)}); + } else { + inst.ReplaceUsesWith( + IR::Value{Common::BitCast<f32>(env.ReadCbufValue(bank_value, offset_value))}); + } +} + +void ConstantPropagation(Environment& env, IR::Block& block, IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::GetRegister: return FoldGetRegister(inst); @@ -789,18 +849,28 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { IR::Opcode::CompositeInsertF16x4); case IR::Opcode::FSwizzleAdd: return FoldFSwizzleAdd(block, inst); + case IR::Opcode::GetCbufF32: + case IR::Opcode::GetCbufU32: + if (env.HasHLEMacroState()) { + FoldConstBuffer(env, block, inst); + } + if (env.IsPropietaryDriver()) { + FoldDriverConstBuffer(env, block, inst, 1); + } + break; default: break; } } + } // Anonymous namespace -void ConstantPropagationPass(IR::Program& program) { +void ConstantPropagationPass(Environment& env, IR::Program& program) { const auto end{program.post_order_blocks.rend()}; for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) { IR::Block* const block{*it}; for (IR::Inst& inst : block->Instructions()) { - ConstantPropagation(*block, inst); + ConstantPropagation(env, *block, inst); } } } diff --git a/src/shader_recompiler/ir_opt/passes.h b/src/shader_recompiler/ir_opt/passes.h index 11bfe801a..1f8f2ba95 100644 --- a/src/shader_recompiler/ir_opt/passes.h +++ b/src/shader_recompiler/ir_opt/passes.h @@ -13,7 +13,7 @@ struct HostTranslateInfo; namespace Shader::Optimization { void CollectShaderInfoPass(Environment& env, IR::Program& program); -void ConstantPropagationPass(IR::Program& program); +void ConstantPropagationPass(Environment& env, IR::Program& program); void DeadCodeEliminationPass(IR::Program& program); void GlobalMemoryToStorageBufferPass(IR::Program& program); void IdentityRemovalPass(IR::Program& program); diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index d9c6e92db..44236b6b1 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -16,6 +16,12 @@ namespace Shader { +enum class ReplaceConstant : u32 { + BaseInstance, + BaseVertex, + DrawID, +}; + enum class TextureType : u32 { Color1D, ColorArray1D, diff --git a/src/shader_recompiler/varying_state.h b/src/shader_recompiler/varying_state.h index 7b28a285f..18a9aaf50 100644 --- a/src/shader_recompiler/varying_state.h +++ b/src/shader_recompiler/varying_state.h @@ -11,7 +11,7 @@ namespace Shader { struct VaryingState { - std::bitset<256> mask{}; + std::bitset<512> mask{}; void Set(IR::Attribute attribute, bool state = true) { mask[static_cast<size_t>(attribute)] = state; |