diff options
| author | 2022-11-09 17:58:10 +0100 | |
|---|---|---|
| committer | 2023-01-01 16:43:57 -0500 | |
| commit | aad0cbf024fb8077a9b375a093c60a7e2ab1db3d (patch) | |
| tree | 8c6a86c92ed8cedbafb5f34dd9f72283eaaf4342 /src/shader_recompiler | |
| parent | MacroHLE: Add Index Buffer size estimation. (diff) | |
| download | yuzu-aad0cbf024fb8077a9b375a093c60a7e2ab1db3d.tar.gz yuzu-aad0cbf024fb8077a9b375a093c60a7e2ab1db3d.tar.xz yuzu-aad0cbf024fb8077a9b375a093c60a7e2ab1db3d.zip | |
MacroHLE: Add HLE replacement for base vertex and base instance.
Diffstat (limited to 'src/shader_recompiler')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | 8 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | 10 | ||||
| -rw-r--r-- | src/shader_recompiler/environment.h | 5 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/attribute.cpp | 4 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/attribute.h | 4 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.cpp | 8 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.h | 2 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/translate_program.cpp | 2 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/constant_propagation_pass.cpp | 45 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/passes.h | 2 | ||||
| -rw-r--r-- | src/shader_recompiler/shader_info.h | 5 | ||||
| -rw-r--r-- | src/shader_recompiler/varying_state.h | 2 |
12 files changed, 91 insertions, 6 deletions
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 73b67f0af..e4802bf9e 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 | |||
| @@ -339,6 +339,10 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { | |||
| 339 | const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; | 339 | const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; |
| 340 | return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base)); | 340 | return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base)); |
| 341 | } | 341 | } |
| 342 | case IR::Attribute::BaseInstance: | ||
| 343 | return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_instance)); | ||
| 344 | case IR::Attribute::BaseVertex: | ||
| 345 | return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_vertex)); | ||
| 342 | case IR::Attribute::FrontFace: | 346 | case IR::Attribute::FrontFace: |
| 343 | return ctx.OpSelect(ctx.F32[1], ctx.OpLoad(ctx.U1, ctx.front_face), | 347 | return ctx.OpSelect(ctx.F32[1], ctx.OpLoad(ctx.U1, ctx.front_face), |
| 344 | ctx.OpBitcast(ctx.F32[1], ctx.Const(std::numeric_limits<u32>::max())), | 348 | ctx.OpBitcast(ctx.F32[1], ctx.Const(std::numeric_limits<u32>::max())), |
| @@ -380,6 +384,10 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id) { | |||
| 380 | const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; | 384 | const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; |
| 381 | return ctx.OpISub(ctx.U32[1], index, base); | 385 | return ctx.OpISub(ctx.U32[1], index, base); |
| 382 | } | 386 | } |
| 387 | case IR::Attribute::BaseInstance: | ||
| 388 | return ctx.OpLoad(ctx.U32[1], ctx.base_instance); | ||
| 389 | case IR::Attribute::BaseVertex: | ||
| 390 | return ctx.OpLoad(ctx.U32[1], ctx.base_vertex); | ||
| 383 | default: | 391 | default: |
| 384 | throw NotImplementedException("Read U32 attribute {}", attr); | 392 | throw NotImplementedException("Read U32 attribute {}", attr); |
| 385 | } | 393 | } |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 41dc6d031..563a5fc49 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -1379,18 +1379,28 @@ void EmitContext::DefineInputs(const IR::Program& program) { | |||
| 1379 | if (loads[IR::Attribute::InstanceId]) { | 1379 | if (loads[IR::Attribute::InstanceId]) { |
| 1380 | if (profile.support_vertex_instance_id) { | 1380 | if (profile.support_vertex_instance_id) { |
| 1381 | instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId); | 1381 | instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId); |
| 1382 | if (loads[IR::Attribute::BaseInstance]) { | ||
| 1383 | base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); | ||
| 1384 | } | ||
| 1382 | } else { | 1385 | } else { |
| 1383 | instance_index = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceIndex); | 1386 | instance_index = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceIndex); |
| 1384 | base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance); | 1387 | base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance); |
| 1385 | } | 1388 | } |
| 1389 | } else if (loads[IR::Attribute::BaseInstance]) { | ||
| 1390 | base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance); | ||
| 1386 | } | 1391 | } |
| 1387 | if (loads[IR::Attribute::VertexId]) { | 1392 | if (loads[IR::Attribute::VertexId]) { |
| 1388 | if (profile.support_vertex_instance_id) { | 1393 | if (profile.support_vertex_instance_id) { |
| 1389 | vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId); | 1394 | vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId); |
| 1395 | if (loads[IR::Attribute::BaseVertex]) { | ||
| 1396 | base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); | ||
| 1397 | } | ||
| 1390 | } else { | 1398 | } else { |
| 1391 | vertex_index = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexIndex); | 1399 | vertex_index = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexIndex); |
| 1392 | base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); | 1400 | base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); |
| 1393 | } | 1401 | } |
| 1402 | } else if (loads[IR::Attribute::BaseVertex]) { | ||
| 1403 | base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); | ||
| 1394 | } | 1404 | } |
| 1395 | if (loads[IR::Attribute::FrontFace]) { | 1405 | if (loads[IR::Attribute::FrontFace]) { |
| 1396 | front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing); | 1406 | front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing); |
diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h index 402f2664f..b9b4455f6 100644 --- a/src/shader_recompiler/environment.h +++ b/src/shader_recompiler/environment.h | |||
| @@ -34,6 +34,11 @@ public: | |||
| 34 | 34 | ||
| 35 | [[nodiscard]] virtual std::array<u32, 3> WorkgroupSize() const = 0; | 35 | [[nodiscard]] virtual std::array<u32, 3> WorkgroupSize() const = 0; |
| 36 | 36 | ||
| 37 | [[nodiscard]] virtual bool HasHLEMacroState() const = 0; | ||
| 38 | |||
| 39 | [[nodiscard]] virtual std::optional<ReplaceConstant> GetReplaceConstBuffer( | ||
| 40 | u32 bank, u32 offset) = 0; | ||
| 41 | |||
| 37 | virtual void Dump(u64 hash) = 0; | 42 | virtual void Dump(u64 hash) = 0; |
| 38 | 43 | ||
| 39 | [[nodiscard]] const ProgramHeader& SPH() const noexcept { | 44 | [[nodiscard]] const ProgramHeader& SPH() const noexcept { |
diff --git a/src/shader_recompiler/frontend/ir/attribute.cpp b/src/shader_recompiler/frontend/ir/attribute.cpp index 7d3d882e4..73e189a89 100644 --- a/src/shader_recompiler/frontend/ir/attribute.cpp +++ b/src/shader_recompiler/frontend/ir/attribute.cpp | |||
| @@ -446,6 +446,10 @@ std::string NameOf(Attribute attribute) { | |||
| 446 | return "ViewportMask"; | 446 | return "ViewportMask"; |
| 447 | case Attribute::FrontFace: | 447 | case Attribute::FrontFace: |
| 448 | return "FrontFace"; | 448 | return "FrontFace"; |
| 449 | case Attribute::BaseInstance: | ||
| 450 | return "BaseInstance"; | ||
| 451 | case Attribute::BaseVertex: | ||
| 452 | return "BaseVertex"; | ||
| 449 | } | 453 | } |
| 450 | return fmt::format("<reserved attribute {}>", static_cast<int>(attribute)); | 454 | return fmt::format("<reserved attribute {}>", static_cast<int>(attribute)); |
| 451 | } | 455 | } |
diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h index 6ee3947b1..364d8a912 100644 --- a/src/shader_recompiler/frontend/ir/attribute.h +++ b/src/shader_recompiler/frontend/ir/attribute.h | |||
| @@ -219,6 +219,10 @@ enum class Attribute : u64 { | |||
| 219 | FixedFncTexture9Q = 231, | 219 | FixedFncTexture9Q = 231, |
| 220 | ViewportMask = 232, | 220 | ViewportMask = 232, |
| 221 | FrontFace = 255, | 221 | FrontFace = 255, |
| 222 | |||
| 223 | // Implementation attributes | ||
| 224 | BaseInstance = 256, | ||
| 225 | BaseVertex = 257, | ||
| 222 | }; | 226 | }; |
| 223 | 227 | ||
| 224 | constexpr size_t NUM_GENERICS = 32; | 228 | constexpr size_t NUM_GENERICS = 32; |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 0cdac0eff..eb2e49a68 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -294,6 +294,14 @@ F32 IREmitter::GetAttribute(IR::Attribute attribute, const U32& vertex) { | |||
| 294 | return Inst<F32>(Opcode::GetAttribute, attribute, vertex); | 294 | return Inst<F32>(Opcode::GetAttribute, attribute, vertex); |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | U32 IREmitter::GetAttributeU32(IR::Attribute attribute) { | ||
| 298 | return GetAttributeU32(attribute, Imm32(0)); | ||
| 299 | } | ||
| 300 | |||
| 301 | U32 IREmitter::GetAttributeU32(IR::Attribute attribute, const U32& vertex) { | ||
| 302 | return Inst<U32>(Opcode::GetAttributeU32, attribute, vertex); | ||
| 303 | } | ||
| 304 | |||
| 297 | void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex) { | 305 | void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex) { |
| 298 | Inst(Opcode::SetAttribute, attribute, value, vertex); | 306 | Inst(Opcode::SetAttribute, attribute, value, vertex); |
| 299 | } | 307 | } |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 2df992feb..7aaaa4ab0 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -74,6 +74,8 @@ public: | |||
| 74 | 74 | ||
| 75 | [[nodiscard]] F32 GetAttribute(IR::Attribute attribute); | 75 | [[nodiscard]] F32 GetAttribute(IR::Attribute attribute); |
| 76 | [[nodiscard]] F32 GetAttribute(IR::Attribute attribute, const U32& vertex); | 76 | [[nodiscard]] F32 GetAttribute(IR::Attribute attribute, const U32& vertex); |
| 77 | [[nodiscard]] U32 GetAttributeU32(IR::Attribute attribute); | ||
| 78 | [[nodiscard]] U32 GetAttributeU32(IR::Attribute attribute, const U32& vertex); | ||
| 77 | void SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex); | 79 | void SetAttribute(IR::Attribute attribute, const F32& value, const U32& vertex); |
| 78 | 80 | ||
| 79 | [[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address); | 81 | [[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 3adbd2b16..ac159d24b 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp | |||
| @@ -219,7 +219,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo | |||
| 219 | } | 219 | } |
| 220 | Optimization::SsaRewritePass(program); | 220 | Optimization::SsaRewritePass(program); |
| 221 | 221 | ||
| 222 | Optimization::ConstantPropagationPass(program); | 222 | Optimization::ConstantPropagationPass(env, program); |
| 223 | 223 | ||
| 224 | Optimization::PositionPass(env, program); | 224 | Optimization::PositionPass(env, program); |
| 225 | 225 | ||
diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index 826f9a54a..ac10405f3 100644 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <type_traits> | 7 | #include <type_traits> |
| 8 | 8 | ||
| 9 | #include "common/bit_cast.h" | 9 | #include "common/bit_cast.h" |
| 10 | #include "shader_recompiler/environment.h" | ||
| 10 | #include "shader_recompiler/exception.h" | 11 | #include "shader_recompiler/exception.h" |
| 11 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | 12 | #include "shader_recompiler/frontend/ir/ir_emitter.h" |
| 12 | #include "shader_recompiler/frontend/ir/value.h" | 13 | #include "shader_recompiler/frontend/ir/value.h" |
| @@ -515,6 +516,8 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) { | |||
| 515 | case IR::Attribute::PrimitiveId: | 516 | case IR::Attribute::PrimitiveId: |
| 516 | case IR::Attribute::InstanceId: | 517 | case IR::Attribute::InstanceId: |
| 517 | case IR::Attribute::VertexId: | 518 | case IR::Attribute::VertexId: |
| 519 | case IR::Attribute::BaseVertex: | ||
| 520 | case IR::Attribute::BaseInstance: | ||
| 518 | break; | 521 | break; |
| 519 | default: | 522 | default: |
| 520 | return; | 523 | return; |
| @@ -644,7 +647,37 @@ void FoldFSwizzleAdd(IR::Block& block, IR::Inst& inst) { | |||
| 644 | } | 647 | } |
| 645 | } | 648 | } |
| 646 | 649 | ||
| 647 | void ConstantPropagation(IR::Block& block, IR::Inst& inst) { | 650 | void FoldConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst) { |
| 651 | const IR::Value bank{inst.Arg(0)}; | ||
| 652 | const IR::Value offset{inst.Arg(1)}; | ||
| 653 | if (!bank.IsImmediate() || !offset.IsImmediate()) { | ||
| 654 | return; | ||
| 655 | } | ||
| 656 | const auto bank_value = bank.U32(); | ||
| 657 | const auto offset_value = offset.U32(); | ||
| 658 | auto replacement = env.GetReplaceConstBuffer(bank_value, offset_value); | ||
| 659 | if (!replacement) { | ||
| 660 | return; | ||
| 661 | } | ||
| 662 | const auto new_attribute = [replacement]() { | ||
| 663 | switch (*replacement) { | ||
| 664 | case ReplaceConstant::BaseInstance: | ||
| 665 | return IR::Attribute::BaseInstance; | ||
| 666 | case ReplaceConstant::BaseVertex: | ||
| 667 | return IR::Attribute::BaseVertex; | ||
| 668 | default: | ||
| 669 | throw NotImplementedException("Not implemented replacement variable {}", *replacement); | ||
| 670 | } | ||
| 671 | }(); | ||
| 672 | IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; | ||
| 673 | if (inst.GetOpcode() == IR::Opcode::GetCbufU32) { | ||
| 674 | inst.ReplaceUsesWith(ir.GetAttributeU32(new_attribute)); | ||
| 675 | } else { | ||
| 676 | inst.ReplaceUsesWith(ir.GetAttribute(new_attribute)); | ||
| 677 | } | ||
| 678 | } | ||
| 679 | |||
| 680 | void ConstantPropagation(Environment& env, IR::Block& block, IR::Inst& inst) { | ||
| 648 | switch (inst.GetOpcode()) { | 681 | switch (inst.GetOpcode()) { |
| 649 | case IR::Opcode::GetRegister: | 682 | case IR::Opcode::GetRegister: |
| 650 | return FoldGetRegister(inst); | 683 | return FoldGetRegister(inst); |
| @@ -789,18 +822,24 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { | |||
| 789 | IR::Opcode::CompositeInsertF16x4); | 822 | IR::Opcode::CompositeInsertF16x4); |
| 790 | case IR::Opcode::FSwizzleAdd: | 823 | case IR::Opcode::FSwizzleAdd: |
| 791 | return FoldFSwizzleAdd(block, inst); | 824 | return FoldFSwizzleAdd(block, inst); |
| 825 | case IR::Opcode::GetCbufF32: | ||
| 826 | case IR::Opcode::GetCbufU32: | ||
| 827 | if (env.HasHLEMacroState()) { | ||
| 828 | return FoldConstBuffer(env, block, inst); | ||
| 829 | } | ||
| 830 | break; | ||
| 792 | default: | 831 | default: |
| 793 | break; | 832 | break; |
| 794 | } | 833 | } |
| 795 | } | 834 | } |
| 796 | } // Anonymous namespace | 835 | } // Anonymous namespace |
| 797 | 836 | ||
| 798 | void ConstantPropagationPass(IR::Program& program) { | 837 | void ConstantPropagationPass(Environment& env, IR::Program& program) { |
| 799 | const auto end{program.post_order_blocks.rend()}; | 838 | const auto end{program.post_order_blocks.rend()}; |
| 800 | for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) { | 839 | for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) { |
| 801 | IR::Block* const block{*it}; | 840 | IR::Block* const block{*it}; |
| 802 | for (IR::Inst& inst : block->Instructions()) { | 841 | for (IR::Inst& inst : block->Instructions()) { |
| 803 | ConstantPropagation(*block, inst); | 842 | ConstantPropagation(env, *block, inst); |
| 804 | } | 843 | } |
| 805 | } | 844 | } |
| 806 | } | 845 | } |
diff --git a/src/shader_recompiler/ir_opt/passes.h b/src/shader_recompiler/ir_opt/passes.h index 11bfe801a..1f8f2ba95 100644 --- a/src/shader_recompiler/ir_opt/passes.h +++ b/src/shader_recompiler/ir_opt/passes.h | |||
| @@ -13,7 +13,7 @@ struct HostTranslateInfo; | |||
| 13 | namespace Shader::Optimization { | 13 | namespace Shader::Optimization { |
| 14 | 14 | ||
| 15 | void CollectShaderInfoPass(Environment& env, IR::Program& program); | 15 | void CollectShaderInfoPass(Environment& env, IR::Program& program); |
| 16 | void ConstantPropagationPass(IR::Program& program); | 16 | void ConstantPropagationPass(Environment& env, IR::Program& program); |
| 17 | void DeadCodeEliminationPass(IR::Program& program); | 17 | void DeadCodeEliminationPass(IR::Program& program); |
| 18 | void GlobalMemoryToStorageBufferPass(IR::Program& program); | 18 | void GlobalMemoryToStorageBufferPass(IR::Program& program); |
| 19 | void IdentityRemovalPass(IR::Program& program); | 19 | void IdentityRemovalPass(IR::Program& program); |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index d9c6e92db..ea0f48344 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -16,6 +16,11 @@ | |||
| 16 | 16 | ||
| 17 | namespace Shader { | 17 | namespace Shader { |
| 18 | 18 | ||
| 19 | enum class ReplaceConstant : u32 { | ||
| 20 | BaseInstance, | ||
| 21 | BaseVertex, | ||
| 22 | }; | ||
| 23 | |||
| 19 | enum class TextureType : u32 { | 24 | enum class TextureType : u32 { |
| 20 | Color1D, | 25 | Color1D, |
| 21 | ColorArray1D, | 26 | ColorArray1D, |
diff --git a/src/shader_recompiler/varying_state.h b/src/shader_recompiler/varying_state.h index 7b28a285f..18a9aaf50 100644 --- a/src/shader_recompiler/varying_state.h +++ b/src/shader_recompiler/varying_state.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | namespace Shader { | 11 | namespace Shader { |
| 12 | 12 | ||
| 13 | struct VaryingState { | 13 | struct VaryingState { |
| 14 | std::bitset<256> mask{}; | 14 | std::bitset<512> mask{}; |
| 15 | 15 | ||
| 16 | void Set(IR::Attribute attribute, bool state = true) { | 16 | void Set(IR::Attribute attribute, bool state = true) { |
| 17 | mask[static_cast<size_t>(attribute)] = state; | 17 | mask[static_cast<size_t>(attribute)] = state; |