Explorar o código

shader: Implement SampleMask

ReinUsesLisp %!s(int64=5) %!d(string=hai) anos
pai
achega
80940b1706

+ 4 - 1
src/shader_recompiler/backend/spirv/emit_context.cpp

@@ -1179,7 +1179,10 @@ void EmitContext::DefineOutputs(const IR::Program& program) {
         if (info.stores_frag_depth) {
             frag_depth = DefineOutput(*this, F32[1], std::nullopt);
             Decorate(frag_depth, spv::Decoration::BuiltIn, spv::BuiltIn::FragDepth);
-            Name(frag_depth, "frag_depth");
+        }
+        if (info.stores_sample_mask) {
+            sample_mask = DefineOutput(*this, U32[1], std::nullopt);
+            Decorate(sample_mask, spv::Decoration::BuiltIn, spv::BuiltIn::SampleMask);
         }
         break;
     default:

+ 1 - 0
src/shader_recompiler/backend/spirv/emit_context.h

@@ -215,6 +215,7 @@ public:
     std::array<Id, 30> patches{};
 
     std::array<Id, 8> frag_color{};
+    Id sample_mask{};
     Id frag_depth{};
 
     std::vector<Id> interfaces;

+ 1 - 0
src/shader_recompiler/backend/spirv/emit_spirv.h

@@ -58,6 +58,7 @@ void EmitSetAttributeIndexed(EmitContext& ctx, Id offset, Id value, Id vertex);
 Id EmitGetPatch(EmitContext& ctx, IR::Patch patch);
 void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value);
 void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value);
+void EmitSetSampleMask(EmitContext& ctx, Id value);
 void EmitSetFragDepth(EmitContext& ctx, Id value);
 void EmitGetZFlag(EmitContext& ctx);
 void EmitGetSFlag(EmitContext& ctx);

+ 4 - 0
src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp

@@ -343,6 +343,10 @@ void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value) {
     ctx.OpStore(pointer, value);
 }
 
+void EmitSetSampleMask(EmitContext& ctx, Id value) {
+    ctx.OpStore(ctx.sample_mask, value);
+}
+
 void EmitSetFragDepth(EmitContext& ctx, Id value) {
     ctx.OpStore(ctx.frag_depth, value);
 }

+ 4 - 0
src/shader_recompiler/frontend/ir/ir_emitter.cpp

@@ -343,6 +343,10 @@ void IREmitter::SetFragColor(u32 index, u32 component, const F32& value) {
     Inst(Opcode::SetFragColor, Imm32(index), Imm32(component), value);
 }
 
+void IREmitter::SetSampleMask(const U32& value) {
+    Inst(Opcode::SetSampleMask, value);
+}
+
 void IREmitter::SetFragDepth(const F32& value) {
     Inst(Opcode::SetFragDepth, value);
 }

+ 1 - 0
src/shader_recompiler/frontend/ir/ir_emitter.h

@@ -88,6 +88,7 @@ public:
     void SetPatch(Patch patch, const F32& value);
 
     void SetFragColor(u32 index, u32 component, const F32& value);
+    void SetSampleMask(const U32& value);
     void SetFragDepth(const F32& value);
 
     [[nodiscard]] U32 WorkgroupIdX();

+ 1 - 0
src/shader_recompiler/frontend/ir/microinstruction.cpp

@@ -75,6 +75,7 @@ bool Inst::MayHaveSideEffects() const noexcept {
     case Opcode::SetAttributeIndexed:
     case Opcode::SetPatch:
     case Opcode::SetFragColor:
+    case Opcode::SetSampleMask:
     case Opcode::SetFragDepth:
     case Opcode::WriteGlobalU8:
     case Opcode::WriteGlobalS8:

+ 1 - 0
src/shader_recompiler/frontend/ir/opcodes.inc

@@ -51,6 +51,7 @@ OPCODE(SetAttributeIndexed,                                 Void,           U32,
 OPCODE(GetPatch,                                            F32,            Patch,                                                                          )
 OPCODE(SetPatch,                                            Void,           Patch,          F32,                                                            )
 OPCODE(SetFragColor,                                        Void,           U32,            U32,            F32,                                            )
+OPCODE(SetSampleMask,                                       Void,           U32,                                                                            )
 OPCODE(SetFragDepth,                                        Void,           F32,                                                                            )
 OPCODE(GetZFlag,                                            U1,             Void,                                                                           )
 OPCODE(GetSFlag,                                            U1,             Void,                                                                           )

+ 1 - 1
src/shader_recompiler/frontend/maxwell/translate/impl/exit_program.cpp

@@ -22,7 +22,7 @@ void ExitFragment(TranslatorVisitor& v) {
         }
     }
     if (sph.ps.omap.sample_mask != 0) {
-        throw NotImplementedException("Sample mask");
+        v.ir.SetSampleMask(v.X(src_reg));
     }
     if (sph.ps.omap.depth != 0) {
         v.ir.SetFragDepth(v.F(src_reg + 1));

+ 3 - 0
src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp

@@ -403,6 +403,9 @@ void VisitUsages(Info& info, IR::Inst& inst) {
     case IR::Opcode::SetFragColor:
         info.stores_frag_color[inst.Arg(0).U32()] = true;
         break;
+    case IR::Opcode::SetSampleMask:
+        info.stores_sample_mask = true;
+        break;
     case IR::Opcode::SetFragDepth:
         info.stores_frag_depth = true;
         break;

+ 1 - 0
src/shader_recompiler/shader_info.h

@@ -118,6 +118,7 @@ struct Info {
     bool loads_indexed_attributes{};
 
     std::array<bool, 8> stores_frag_color{};
+    bool stores_sample_mask{};
     bool stores_frag_depth{};
     std::array<bool, 32> stores_generics{};
     bool stores_position{};