diff options
| author | FengChen <vonchenplus@gmail.com> | 2022-10-30 19:59:11 +0800 | 
|---|---|---|
| committer | Feng Chen <vonchenplus@gmail.com> | 2022-11-07 15:42:42 +0800 | 
| commit | a4472b55260ed1ccbad0d191d11abd2330145140 (patch) | |
| tree | ed58bca8f35b79497099c8c73675332be455c28e | |
| parent | df38c03a09ad56fdb299d78b39a3951d6ade83aa (diff) | |
video_core: Fix few issues in Tess stage
18 files changed, 63 insertions, 6 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 0a7d42dda..d6562c842 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 @@ -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);  } diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index d645fd532..eaaf9ba39 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/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); diff --git a/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp b/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp index 89603c1c4..333a91cc5 100644 --- a/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp +++ b/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]}};");      } 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 d7c845469..c1671c37b 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 @@ -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);  } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h index 96e683b5e..4151c89de 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h +++ b/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); 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 a4751b42d..5b3b5d1f3 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 @@ -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);  } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 7070c8fda..e31cdc5e8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/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); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index c26ad8f93..0bfc2dd89 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/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);      } diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index c86e50911..dde45b4bc 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/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{}; diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index d4425f06d..0cdac0eff 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/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);  } diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index f163c18d9..2df992feb 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/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(); diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 88aa077ee..1fe3749cc 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/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,                                                                                            ) diff --git a/src/shader_recompiler/frontend/ir/patch.h b/src/shader_recompiler/frontend/ir/patch.h index 1e37c8eb6..5077e56c2 100644 --- a/src/shader_recompiler/frontend/ir/patch.h +++ b/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; diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp index 52be12f9c..753c62098 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp +++ b/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)}, diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index 7cff8ecdc..5a4195217 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/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; diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index f31e1f821..ee6252bb5 100644 --- a/src/shader_recompiler/shader_info.h +++ b/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{}; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 977709518..e0709cb9c 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/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: diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index b42e5be1e..23b30253f 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/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)) { | 
