diff options
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 | ||
| 129 | void 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 | |||
| 129 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, | 145 | void 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, | |||
| 50 | void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); | 50 | void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); |
| 51 | void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); | 51 | void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); |
| 52 | void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex); | 52 | void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex); |
| 53 | void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex); | ||
| 53 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex); | 54 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex); |
| 54 | void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex); | 55 | void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex); |
| 55 | void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex); | 56 | void 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 | ||
| 224 | void 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 | |||
| 224 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, | 240 | void 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); |
| 61 | void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | 61 | void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, |
| 62 | std::string_view vertex); | 62 | std::string_view vertex); |
| 63 | void EmitGetAttributeU32(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | ||
| 64 | std::string_view vertex); | ||
| 63 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, | 65 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, |
| 64 | std::string_view vertex); | 66 | std::string_view vertex); |
| 65 | void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, std::string_view offset, | 67 | void 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 | ||
| 358 | Id 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 | |||
| 358 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, [[maybe_unused]] Id vertex) { | 383 | void 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 | |||
| 53 | Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | 53 | Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); |
| 54 | Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | 54 | Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); |
| 55 | Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex); | 55 | Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex); |
| 56 | Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id vertex); | ||
| 56 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, Id vertex); | 57 | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, Id vertex); |
| 57 | Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset, Id vertex); | 58 | Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset, Id vertex); |
| 58 | void EmitSetAttributeIndexed(EmitContext& ctx, Id offset, Id value, Id vertex); | 59 | void 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, | |||
| 40 | OPCODE(GetCbufF32, F32, U32, U32, ) | 40 | OPCODE(GetCbufF32, F32, U32, U32, ) |
| 41 | OPCODE(GetCbufU32x2, U32x2, U32, U32, ) | 41 | OPCODE(GetCbufU32x2, U32x2, U32, U32, ) |
| 42 | OPCODE(GetAttribute, F32, Attribute, U32, ) | 42 | OPCODE(GetAttribute, F32, Attribute, U32, ) |
| 43 | OPCODE(GetAttributeU32, U32, Attribute, U32, ) | ||
| 43 | OPCODE(SetAttribute, Void, Attribute, F32, U32, ) | 44 | OPCODE(SetAttribute, Void, Attribute, F32, U32, ) |
| 44 | OPCODE(GetAttributeIndexed, F32, U32, U32, ) | 45 | OPCODE(GetAttributeIndexed, F32, U32, U32, ) |
| 45 | OPCODE(SetAttributeIndexed, Void, U32, F32, U32, ) | 46 | OPCODE(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 | ||
| 510 | void FoldInverseFunc(IR::Inst& inst, IR::Opcode reverse) { | 533 | void FoldInverseFunc(IR::Inst& inst, IR::Opcode reverse) { |