mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Merge pull request #9167 from vonchenplus/tess
video_core: Fix few issues in Tess stage
This commit is contained in:
		@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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]}};");
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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{};
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -97,6 +97,7 @@ public:
 | 
			
		||||
    [[nodiscard]] U32 LocalInvocationIdZ();
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] U32 InvocationId();
 | 
			
		||||
    [[nodiscard]] U32 InvocationInfo();
 | 
			
		||||
    [[nodiscard]] U32 SampleId();
 | 
			
		||||
    [[nodiscard]] U1 IsHelperInvocation();
 | 
			
		||||
    [[nodiscard]] F32 YDirection();
 | 
			
		||||
 
 | 
			
		||||
@@ -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,                                                                                            )
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)},
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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{};
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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)) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user