Parcourir la source

Merge pull request #9167 from vonchenplus/tess

video_core: Fix few issues in Tess stage
liamwhite il y a 3 ans
Parent
commit
c973029374

+ 12 - 0
src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp

@@ -379,6 +379,18 @@ void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) {
     ctx.Add("MOV.S {}.x,primitive_invocation.x;", inst);
 }
 
+void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst) {
+    switch (ctx.stage) {
+    case Stage::TessellationControl:
+    case Stage::TessellationEval:
+        ctx.Add("SHL.U {}.x,primitive.vertexcount,16;", inst);
+        break;
+    default:
+        LOG_WARNING(Shader, "(STUBBED) called");
+        ctx.Add("MOV.S {}.x,0x00ff0000;", inst);
+    }
+}
+
 void EmitSampleId(EmitContext& ctx, IR::Inst& inst) {
     ctx.Add("MOV.S {}.x,fragment.sampleid.x;", inst);
 }

+ 1 - 0
src/shader_recompiler/backend/glasm/emit_glasm_instructions.h

@@ -69,6 +69,7 @@ void EmitSetOFlag(EmitContext& ctx);
 void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst);
 void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst);
 void EmitInvocationId(EmitContext& ctx, IR::Inst& inst);
+void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst);
 void EmitSampleId(EmitContext& ctx, IR::Inst& inst);
 void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst);
 void EmitYDirection(EmitContext& ctx, IR::Inst& inst);

+ 4 - 0
src/shader_recompiler/backend/glasm/glasm_emit_context.cpp

@@ -95,6 +95,10 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
     if (info.uses_invocation_id) {
         Add("ATTRIB primitive_invocation=primitive.invocation;");
     }
+    if (info.uses_invocation_info &&
+        (stage == Stage::TessellationControl || stage == Stage::TessellationEval)) {
+        Add("ATTRIB primitive_vertexcount = primitive.vertexcount;");
+    }
     if (info.stores_tess_level_outer) {
         Add("OUTPUT result_patch_tessouter[]={{result.patch.tessouter[0..3]}};");
     }

+ 12 - 0
src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp

@@ -399,6 +399,18 @@ void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) {
     ctx.AddU32("{}=uint(gl_InvocationID);", inst);
 }
 
+void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst) {
+    switch (ctx.stage) {
+    case Stage::TessellationControl:
+    case Stage::TessellationEval:
+        ctx.AddU32("{}=uint(gl_PatchVerticesIn)<<16;", inst);
+        break;
+    default:
+        LOG_WARNING(Shader, "(STUBBED) called");
+        ctx.AddU32("{}=uint(0x00ff0000);", inst);
+    }
+}
+
 void EmitSampleId(EmitContext& ctx, IR::Inst& inst) {
     ctx.AddU32("{}=uint(gl_SampleID);", inst);
 }

+ 1 - 0
src/shader_recompiler/backend/glsl/emit_glsl_instructions.h

@@ -83,6 +83,7 @@ void EmitSetOFlag(EmitContext& ctx);
 void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst);
 void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst);
 void EmitInvocationId(EmitContext& ctx, IR::Inst& inst);
+void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst);
 void EmitSampleId(EmitContext& ctx, IR::Inst& inst);
 void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst);
 void EmitYDirection(EmitContext& ctx, IR::Inst& inst);

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

@@ -512,6 +512,18 @@ Id EmitInvocationId(EmitContext& ctx) {
     return ctx.OpLoad(ctx.U32[1], ctx.invocation_id);
 }
 
+Id EmitInvocationInfo(EmitContext& ctx) {
+    switch (ctx.stage) {
+    case Stage::TessellationControl:
+    case Stage::TessellationEval:
+        return ctx.OpShiftLeftLogical(ctx.U32[1], ctx.OpLoad(ctx.U32[1], ctx.patch_vertices_in),
+                                      ctx.Const(16u));
+    default:
+        LOG_WARNING(Shader, "(STUBBED) called");
+        return ctx.Const(0x00ff0000u);
+    }
+}
+
 Id EmitSampleId(EmitContext& ctx) {
     return ctx.OpLoad(ctx.U32[1], ctx.sample_id);
 }

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

@@ -72,6 +72,7 @@ void EmitSetOFlag(EmitContext& ctx);
 Id EmitWorkgroupId(EmitContext& ctx);
 Id EmitLocalInvocationId(EmitContext& ctx);
 Id EmitInvocationId(EmitContext& ctx);
+Id EmitInvocationInfo(EmitContext& ctx);
 Id EmitSampleId(EmitContext& ctx);
 Id EmitIsHelperInvocation(EmitContext& ctx);
 Id EmitYDirection(EmitContext& ctx);

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

@@ -1325,6 +1325,10 @@ void EmitContext::DefineInputs(const IR::Program& program) {
     if (info.uses_invocation_id) {
         invocation_id = DefineInput(*this, U32[1], false, spv::BuiltIn::InvocationId);
     }
+    if (info.uses_invocation_info &&
+        (stage == Shader::Stage::TessellationControl || stage == Shader::Stage::TessellationEval)) {
+        patch_vertices_in = DefineInput(*this, U32[1], false, spv::BuiltIn::PatchVertices);
+    }
     if (info.uses_sample_id) {
         sample_id = DefineInput(*this, U32[1], false, spv::BuiltIn::SampleId);
     }

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

@@ -204,6 +204,7 @@ public:
     Id workgroup_id{};
     Id local_invocation_id{};
     Id invocation_id{};
+    Id patch_vertices_in{};
     Id sample_id{};
     Id is_helper_invocation{};
     Id subgroup_local_invocation_id{};

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

@@ -362,6 +362,10 @@ U32 IREmitter::InvocationId() {
     return Inst<U32>(Opcode::InvocationId);
 }
 
+U32 IREmitter::InvocationInfo() {
+    return Inst<U32>(Opcode::InvocationInfo);
+}
+
 U32 IREmitter::SampleId() {
     return Inst<U32>(Opcode::SampleId);
 }

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

@@ -97,6 +97,7 @@ public:
     [[nodiscard]] U32 LocalInvocationIdZ();
 
     [[nodiscard]] U32 InvocationId();
+    [[nodiscard]] U32 InvocationInfo();
     [[nodiscard]] U32 SampleId();
     [[nodiscard]] U1 IsHelperInvocation();
     [[nodiscard]] F32 YDirection();

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

@@ -59,6 +59,7 @@ OPCODE(SetOFlag,                                            Void,           U1,
 OPCODE(WorkgroupId,                                         U32x3,                                                                                          )
 OPCODE(LocalInvocationId,                                   U32x3,                                                                                          )
 OPCODE(InvocationId,                                        U32,                                                                                            )
+OPCODE(InvocationInfo,                                      U32,                                                                                            )
 OPCODE(SampleId,                                            U32,                                                                                            )
 OPCODE(IsHelperInvocation,                                  U1,                                                                                             )
 OPCODE(YDirection,                                          F32,                                                                                            )

+ 1 - 3
src/shader_recompiler/frontend/ir/patch.h

@@ -14,8 +14,6 @@ enum class Patch : u64 {
     TessellationLodBottom,
     TessellationLodInteriorU,
     TessellationLodInteriorV,
-    ComponentPadding0,
-    ComponentPadding1,
     Component0,
     Component1,
     Component2,
@@ -137,7 +135,7 @@ enum class Patch : u64 {
     Component118,
     Component119,
 };
-static_assert(static_cast<u64>(Patch::Component119) == 127);
+static_assert(static_cast<u64>(Patch::Component119) == 125);
 
 [[nodiscard]] bool IsGeneric(Patch patch) noexcept;
 

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

@@ -117,8 +117,7 @@ enum class SpecialRegister : u64 {
     case SpecialRegister::SR_THREAD_KILL:
         return IR::U32{ir.Select(ir.IsHelperInvocation(), ir.Imm32(-1), ir.Imm32(0))};
     case SpecialRegister::SR_INVOCATION_INFO:
-        LOG_WARNING(Shader, "(STUBBED) SR_INVOCATION_INFO");
-        return ir.Imm32(0x00ff'0000);
+        return ir.InvocationInfo();
     case SpecialRegister::SR_TID: {
         const IR::Value tid{ir.LocalInvocationId()};
         return ir.BitFieldInsert(ir.BitFieldInsert(IR::U32{ir.CompositeExtract(tid, 0)},

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

@@ -468,6 +468,9 @@ void VisitUsages(Info& info, IR::Inst& inst) {
     case IR::Opcode::InvocationId:
         info.uses_invocation_id = true;
         break;
+    case IR::Opcode::InvocationInfo:
+        info.uses_invocation_info = true;
+        break;
     case IR::Opcode::SampleId:
         info.uses_sample_id = true;
         break;

+ 1 - 0
src/shader_recompiler/shader_info.h

@@ -127,6 +127,7 @@ struct Info {
     bool uses_workgroup_id{};
     bool uses_local_invocation_id{};
     bool uses_invocation_id{};
+    bool uses_invocation_info{};
     bool uses_sample_id{};
     bool uses_is_helper_invocation{};
     bool uses_subgroup_invocation_id{};

+ 2 - 1
src/video_core/renderer_opengl/gl_shader_cache.cpp

@@ -76,7 +76,8 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
         }
         break;
     case Shader::Stage::TessellationEval:
-        info.tess_clockwise = key.tessellation_clockwise != 0;
+        // Flip the face, as OpenGL's drawing is flipped.
+        info.tess_clockwise = key.tessellation_clockwise == 0;
         info.tess_primitive = [&key] {
             switch (key.tessellation_primitive) {
             case Maxwell::Tessellation::DomainType::Isolines:

+ 1 - 0
src/video_core/renderer_vulkan/vk_pipeline_cache.cpp

@@ -166,6 +166,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
         }
         break;
     case Shader::Stage::TessellationEval:
+        info.tess_clockwise = key.state.tessellation_clockwise != 0;
         info.tess_primitive = [&key] {
             const u32 raw{key.state.tessellation_primitive.Value()};
             switch (static_cast<Maxwell::Tessellation::DomainType>(raw)) {