summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ameerj2021-12-24 20:00:28 -0500
committerGravatar ameerj2021-12-29 19:03:49 -0500
commit14ac0c2923c41df9c6fc4833d2a8e46a6efe5b59 (patch)
tree6d9cb0ebd7d8d7b75d88a0d598c659b06d45004c
parentemit_glsl_floating_point: Fix FPNeg on newer Nvidia drivers (diff)
downloadyuzu-14ac0c2923c41df9c6fc4833d2a8e46a6efe5b59.tar.gz
yuzu-14ac0c2923c41df9c6fc4833d2a8e46a6efe5b59.tar.xz
yuzu-14ac0c2923c41df9c6fc4833d2a8e46a6efe5b59.zip
shader: Add integer attribute get optimization pass
Works around an nvidia driver bug, where casting the integer attributes to float and back to an integer always returned 0.
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp16
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_instructions.h1
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp16
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_instructions.h2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp25
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_instructions.h1
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc1
-rw-r--r--src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp1
-rw-r--r--src/shader_recompiler/ir_opt/constant_propagation_pass.cpp23
9 files changed, 86 insertions, 0 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 081b2c8e0..c0f5fc402 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
@@ -126,6 +126,22 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal
126 } 126 }
127} 127}
128 128
129void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32) {
130 switch (attr) {
131 case IR::Attribute::PrimitiveId:
132 ctx.Add("MOV.S {}.x,primitive.id;", inst);
133 break;
134 case IR::Attribute::InstanceId:
135 ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.attrib_name);
136 break;
137 case IR::Attribute::VertexId:
138 ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name);
139 break;
140 default:
141 throw NotImplementedException("Get U32 attribute {}", attr);
142 }
143}
144
129void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, 145void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value,
130 [[maybe_unused]] ScalarU32 vertex) { 146 [[maybe_unused]] ScalarU32 vertex) {
131 const u32 element{static_cast<u32>(attr) % 4}; 147 const u32 element{static_cast<u32>(attr) % 4};
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
index 1f343bff5..b48007856 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
@@ -50,6 +50,7 @@ void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
50void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); 50void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
51void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); 51void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
52void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex); 52void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex);
53void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex);
53void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex); 54void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex);
54void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex); 55void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex);
55void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex); 56void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex);
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 6477bd192..5ef46d634 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
@@ -221,6 +221,22 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
221 } 221 }
222} 222}
223 223
224void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, std::string_view) {
225 switch (attr) {
226 case IR::Attribute::PrimitiveId:
227 ctx.AddU32("{}=uint(gl_PrimitiveID);", inst);
228 break;
229 case IR::Attribute::InstanceId:
230 ctx.AddU32("{}=uint(gl_InstanceID);", inst);
231 break;
232 case IR::Attribute::VertexId:
233 ctx.AddU32("{}=uint(gl_VertexID);", inst);
234 break;
235 default:
236 throw NotImplementedException("Get U32 attribute {}", attr);
237 }
238}
239
224void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, 240void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
225 [[maybe_unused]] std::string_view vertex) { 241 [[maybe_unused]] std::string_view vertex) {
226 if (IR::IsGeneric(attr)) { 242 if (IR::IsGeneric(attr)) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index f86502e4c..6cabbc717 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -60,6 +60,8 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding
60 const IR::Value& offset); 60 const IR::Value& offset);
61void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, 61void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
62 std::string_view vertex); 62 std::string_view vertex);
63void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr,
64 std::string_view vertex);
63void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, 65void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value,
64 std::string_view vertex); 66 std::string_view vertex);
65void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, std::string_view offset, 67void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, std::string_view offset,
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 14f470812..8ea730c80 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
@@ -355,6 +355,31 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
355 } 355 }
356} 356}
357 357
358Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id) {
359 switch (attr) {
360 case IR::Attribute::PrimitiveId:
361 return ctx.OpLoad(ctx.U32[1], ctx.primitive_id);
362 case IR::Attribute::InstanceId:
363 if (ctx.profile.support_vertex_instance_id) {
364 return ctx.OpLoad(ctx.U32[1], ctx.instance_id);
365 } else {
366 const Id index{ctx.OpLoad(ctx.U32[1], ctx.instance_index)};
367 const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_instance)};
368 return ctx.OpISub(ctx.U32[1], index, base);
369 }
370 case IR::Attribute::VertexId:
371 if (ctx.profile.support_vertex_instance_id) {
372 return ctx.OpLoad(ctx.U32[1], ctx.vertex_id);
373 } else {
374 const Id index{ctx.OpLoad(ctx.U32[1], ctx.vertex_index)};
375 const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)};
376 return ctx.OpISub(ctx.U32[1], index, base);
377 }
378 default:
379 throw NotImplementedException("Read U32 attribute {}", attr);
380 }
381}
382
358void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, [[maybe_unused]] Id vertex) { 383void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, [[maybe_unused]] Id vertex) {
359 const std::optional<OutAttr> output{OutputAttrPointer(ctx, attr)}; 384 const std::optional<OutAttr> output{OutputAttrPointer(ctx, attr)};
360 if (!output) { 385 if (!output) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
index 6cd22dd3e..887112deb 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
@@ -53,6 +53,7 @@ Id EmitGetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& o
53Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); 53Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
54Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); 54Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
55Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex); 55Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex);
56Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id vertex);
56void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, Id vertex); 57void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, Id vertex);
57Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset, Id vertex); 58Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset, Id vertex);
58void EmitSetAttributeIndexed(EmitContext& ctx, Id offset, Id value, Id vertex); 59void EmitSetAttributeIndexed(EmitContext& ctx, Id offset, Id value, Id vertex);
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index 6929919df..b94ce7406 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -40,6 +40,7 @@ OPCODE(GetCbufU32, U32, U32,
40OPCODE(GetCbufF32, F32, U32, U32, ) 40OPCODE(GetCbufF32, F32, U32, U32, )
41OPCODE(GetCbufU32x2, U32x2, U32, U32, ) 41OPCODE(GetCbufU32x2, U32x2, U32, U32, )
42OPCODE(GetAttribute, F32, Attribute, U32, ) 42OPCODE(GetAttribute, F32, Attribute, U32, )
43OPCODE(GetAttributeU32, U32, Attribute, U32, )
43OPCODE(SetAttribute, Void, Attribute, F32, U32, ) 44OPCODE(SetAttribute, Void, Attribute, F32, U32, )
44OPCODE(GetAttributeIndexed, F32, U32, U32, ) 45OPCODE(GetAttributeIndexed, F32, U32, U32, )
45OPCODE(SetAttributeIndexed, Void, U32, F32, U32, ) 46OPCODE(SetAttributeIndexed, Void, U32, F32, U32, )
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 1e476d83d..a78c469be 100644
--- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp
+++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp
@@ -389,6 +389,7 @@ void VisitUsages(Info& info, IR::Inst& inst) {
389 info.uses_demote_to_helper_invocation = true; 389 info.uses_demote_to_helper_invocation = true;
390 break; 390 break;
391 case IR::Opcode::GetAttribute: 391 case IR::Opcode::GetAttribute:
392 case IR::Opcode::GetAttributeU32:
392 info.loads.mask[static_cast<size_t>(inst.Arg(0).Attribute())] = true; 393 info.loads.mask[static_cast<size_t>(inst.Arg(0).Attribute())] = true;
393 break; 394 break;
394 case IR::Opcode::SetAttribute: 395 case IR::Opcode::SetAttribute:
diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
index d089fdd12..c134a12bc 100644
--- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
+++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
@@ -505,6 +505,29 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) {
505 return; 505 return;
506 } 506 }
507 } 507 }
508 if constexpr (op == IR::Opcode::BitCastU32F32) {
509 // Workaround for new NVIDIA driver bug, where:
510 // uint attr = ftou(itof(gl_InstanceID));
511 // always returned 0.
512 // We can instead manually optimize this and work around the driver bug:
513 // uint attr = uint(gl_InstanceID);
514 if (arg_inst->GetOpcode() == IR::Opcode::GetAttribute) {
515 const IR::Attribute attr{arg_inst->Arg(0).Attribute()};
516 switch (attr) {
517 case IR::Attribute::PrimitiveId:
518 case IR::Attribute::InstanceId:
519 case IR::Attribute::VertexId:
520 break;
521 default:
522 return;
523 }
524 // Replace the bitcasts with an integer attribute get
525 inst.ReplaceOpcode(IR::Opcode::GetAttributeU32);
526 inst.SetArg(0, arg_inst->Arg(0));
527 inst.SetArg(1, arg_inst->Arg(1));
528 return;
529 }
530 }
508} 531}
509 532
510void FoldInverseFunc(IR::Inst& inst, IR::Opcode reverse) { 533void FoldInverseFunc(IR::Inst& inst, IR::Opcode reverse) {