Browse Source
Merge pull request #9167 from vonchenplus/tess
video_core: Fix few issues in Tess stage
pull/15/merge
liamwhite
3 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with
63 additions and
6 deletions
-
src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
-
src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
-
src/shader_recompiler/backend/glasm/glasm_emit_context.cpp
-
src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
-
src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
-
src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
-
src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
-
src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
-
src/shader_recompiler/backend/spirv/spirv_emit_context.h
-
src/shader_recompiler/frontend/ir/ir_emitter.cpp
-
src/shader_recompiler/frontend/ir/ir_emitter.h
-
src/shader_recompiler/frontend/ir/opcodes.inc
-
src/shader_recompiler/frontend/ir/patch.h
-
src/shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp
-
src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp
-
src/shader_recompiler/shader_info.h
-
src/video_core/renderer_opengl/gl_shader_cache.cpp
-
src/video_core/renderer_vulkan/vk_pipeline_cache.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); |
|
|
|
} |
|
|
|
|
|
|
|
@ -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)) { |
|
|
|
|