From 73b11f390e3dabf42d22af78670c8aa6d8f52cee Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Wed, 1 Sep 2021 00:07:25 +0800 Subject: [PATCH 01/10] Add colorfront and txtcoord support --- .../backend/spirv/emit_context.cpp | 14 ++++++++++ .../backend/spirv/emit_context.h | 4 +++ .../spirv/emit_spirv_context_get_set.cpp | 26 +++++++++++++++++++ .../frontend/ir/attribute.cpp | 8 ++++++ src/shader_recompiler/frontend/ir/attribute.h | 5 ++++ 5 files changed, 57 insertions(+) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 2d29d8c14..89c75c52d 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -1201,6 +1201,12 @@ void EmitContext::DefineInputs(const IR::Program& program) { } } } + if (loads.AllComponents(IR::Attribute::ColorFrontDiffuseR)) { + input_front_color = DefineInput(*this, F32[4], true); + } + if (loads.AllComponents(IR::Attribute::FixedFncTexture0S)) { + input_txt_coord = DefineInput(*this, F32[4], true); + } if (loads[IR::Attribute::InstanceId]) { if (profile.support_vertex_instance_id) { instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId); @@ -1282,6 +1288,9 @@ void EmitContext::DefineOutputs(const IR::Program& program) { if (info.stores.AnyComponent(IR::Attribute::PositionX) || stage == Stage::VertexB) { output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position); } + if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR) || stage == Stage::VertexB) { + output_front_color = DefineOutput(*this, F32[4], invocations); + } if (info.stores[IR::Attribute::PointSize] || runtime_info.fixed_state_point_size) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing PointSize in fragment stage"); @@ -1313,6 +1322,11 @@ void EmitContext::DefineOutputs(const IR::Program& program) { viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt, spv::BuiltIn::ViewportMaskNV); } + + if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S)) { + output_txt_coord = DefineOutput(*this, F32[4], invocations); + } + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { if (info.stores.Generic(index)) { DefineGenericOutput(*this, index, invocations); diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index e277bc358..1023d0ee4 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h @@ -268,10 +268,14 @@ public: Id write_global_func_u32x4{}; Id input_position{}; + Id input_front_color{}; + Id input_txt_coord{}; std::array input_generics{}; Id output_point_size{}; Id output_position{}; + Id output_front_color{}; + Id output_txt_coord; std::array, 32> output_generics{}; Id output_tess_level_outer{}; 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 14c77f162..0444bbf8f 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 @@ -74,6 +74,12 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id); } } + if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { + const u32 index{IR::TxtCoordAttributeIndex(attr)}; + const u32 element{IR::TxtCoordAttributeElement(attr)}; + const Id element_id{ctx.Const(element)}; + return OutputAccessChain(ctx, ctx.output_f32, ctx.output_txt_coord, element_id); + } switch (attr) { case IR::Attribute::PointSize: return ctx.output_point_size; @@ -85,6 +91,14 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { const Id element_id{ctx.Const(element)}; return OutputAccessChain(ctx, ctx.output_f32, ctx.output_position, element_id); } + case IR::Attribute::ColorFrontDiffuseR: + case IR::Attribute::ColorFrontDiffuseG: + case IR::Attribute::ColorFrontDiffuseB: + case IR::Attribute::ColorFrontDiffuseA: { + const u32 element{static_cast(attr) % 4}; + const Id element_id{ctx.Const(element)}; + return OutputAccessChain(ctx, ctx.output_f32, ctx.output_front_color, element_id); + } case IR::Attribute::ClipDistance0: case IR::Attribute::ClipDistance1: case IR::Attribute::ClipDistance2: @@ -307,6 +321,11 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { const Id value{ctx.OpLoad(type->id, pointer)}; return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value; } + if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { + const u32 index{IR::TxtCoordAttributeIndex(attr)}; + return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_txt_coord, + ctx.Const(element))); + } switch (attr) { case IR::Attribute::PrimitiveId: return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.primitive_id)); @@ -316,6 +335,13 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { case IR::Attribute::PositionW: return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position, ctx.Const(element))); + case IR::Attribute::ColorFrontDiffuseR: + case IR::Attribute::ColorFrontDiffuseG: + case IR::Attribute::ColorFrontDiffuseB: + case IR::Attribute::ColorFrontDiffuseA: { + return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_front_color, + ctx.Const(element))); + } case IR::Attribute::InstanceId: if (ctx.profile.support_vertex_instance_id) { return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_id)); diff --git a/src/shader_recompiler/frontend/ir/attribute.cpp b/src/shader_recompiler/frontend/ir/attribute.cpp index 4d0b8b8e5..dc2bec06d 100644 --- a/src/shader_recompiler/frontend/ir/attribute.cpp +++ b/src/shader_recompiler/frontend/ir/attribute.cpp @@ -9,6 +9,14 @@ namespace Shader::IR { +u32 TxtCoordAttributeIndex(Attribute attribute) { + return (static_cast(attribute) - static_cast(Attribute::FixedFncTexture0S)) / 4u; +} + +u32 TxtCoordAttributeElement(Attribute attribute) { + return static_cast(attribute) % 4; +} + bool IsGeneric(Attribute attribute) noexcept { return attribute >= Attribute::Generic0X && attribute <= Attribute::Generic31X; } diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h index ca1199494..6957fb43b 100644 --- a/src/shader_recompiler/frontend/ir/attribute.h +++ b/src/shader_recompiler/frontend/ir/attribute.h @@ -222,8 +222,13 @@ enum class Attribute : u64 { FrontFace = 255, }; +constexpr size_t NUM_TXT_COORD = 10; constexpr size_t NUM_GENERICS = 32; +[[nodiscard]] u32 TxtCoordAttributeIndex(Attribute attribute); + +[[nodiscard]] u32 TxtCoordAttributeElement(Attribute attribute); + [[nodiscard]] bool IsGeneric(Attribute attribute) noexcept; [[nodiscard]] u32 GenericAttributeIndex(Attribute attribute); From 1e2a89d3061bbee3c73cd55fb8d580b56aabacec Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Thu, 2 Sep 2021 23:34:51 +0800 Subject: [PATCH 02/10] Add input/output location --- .../backend/spirv/emit_context.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 89c75c52d..ff0501b76 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -1202,10 +1202,14 @@ void EmitContext::DefineInputs(const IR::Program& program) { } } if (loads.AllComponents(IR::Attribute::ColorFrontDiffuseR)) { - input_front_color = DefineInput(*this, F32[4], true); + const Id id{DefineInput(*this, F32[4], true)}; + Decorate(id, spv::Decoration::Location, static_cast(55)); + input_front_color = id; } - if (loads.AllComponents(IR::Attribute::FixedFncTexture0S)) { - input_txt_coord = DefineInput(*this, F32[4], true); + if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S)) { + const Id id{DefineInput(*this, F32[4], true)}; + Decorate(id, spv::Decoration::Location, static_cast(56)); + input_txt_coord = id; } if (loads[IR::Attribute::InstanceId]) { if (profile.support_vertex_instance_id) { @@ -1289,7 +1293,9 @@ void EmitContext::DefineOutputs(const IR::Program& program) { output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position); } if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR) || stage == Stage::VertexB) { - output_front_color = DefineOutput(*this, F32[4], invocations); + const Id id{DefineOutput(*this, F32[4], invocations)}; + Decorate(id, spv::Decoration::Location, static_cast(55)); + output_front_color = id; } if (info.stores[IR::Attribute::PointSize] || runtime_info.fixed_state_point_size) { if (stage == Stage::Fragment) { @@ -1324,7 +1330,9 @@ void EmitContext::DefineOutputs(const IR::Program& program) { } if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S)) { - output_txt_coord = DefineOutput(*this, F32[4], invocations); + const Id id{DefineOutput(*this, F32[4], invocations)}; + Decorate(id, spv::Decoration::Location, static_cast(56)); + output_txt_coord = id; } for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { From cf26f375ff2bfc84445270cf1077504ab4cc41f6 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Fri, 3 Sep 2021 22:55:53 +0800 Subject: [PATCH 03/10] Fix create GraphicsPipelines crash --- src/shader_recompiler/backend/spirv/emit_context.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index ff0501b76..78ca97d91 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -1201,14 +1201,14 @@ void EmitContext::DefineInputs(const IR::Program& program) { } } } - if (loads.AllComponents(IR::Attribute::ColorFrontDiffuseR)) { + if (loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { const Id id{DefineInput(*this, F32[4], true)}; - Decorate(id, spv::Decoration::Location, static_cast(55)); + Decorate(id, spv::Decoration::Location, static_cast(11)); input_front_color = id; } if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S)) { const Id id{DefineInput(*this, F32[4], true)}; - Decorate(id, spv::Decoration::Location, static_cast(56)); + Decorate(id, spv::Decoration::Location, static_cast(12)); input_txt_coord = id; } if (loads[IR::Attribute::InstanceId]) { @@ -1294,7 +1294,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { } if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR) || stage == Stage::VertexB) { const Id id{DefineOutput(*this, F32[4], invocations)}; - Decorate(id, spv::Decoration::Location, static_cast(55)); + Decorate(id, spv::Decoration::Location, static_cast(11)); output_front_color = id; } if (info.stores[IR::Attribute::PointSize] || runtime_info.fixed_state_point_size) { @@ -1331,7 +1331,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S)) { const Id id{DefineOutput(*this, F32[4], invocations)}; - Decorate(id, spv::Decoration::Location, static_cast(56)); + Decorate(id, spv::Decoration::Location, static_cast(12)); output_txt_coord = id; } From a7bbaa489755c9847416c8c96f0eefb9e78a50a0 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Fri, 3 Sep 2021 23:52:20 +0800 Subject: [PATCH 04/10] Rename parameters --- .../backend/spirv/emit_context.cpp | 4 ++-- src/shader_recompiler/backend/spirv/emit_context.h | 4 ++-- .../backend/spirv/emit_spirv_context_get_set.cpp | 10 +++++----- src/shader_recompiler/frontend/ir/attribute.cpp | 14 ++++++++++++-- src/shader_recompiler/frontend/ir/attribute.h | 6 +++--- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 78ca97d91..3ec5a4570 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -1209,7 +1209,7 @@ void EmitContext::DefineInputs(const IR::Program& program) { if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S)) { const Id id{DefineInput(*this, F32[4], true)}; Decorate(id, spv::Decoration::Location, static_cast(12)); - input_txt_coord = id; + input_fixed_fnc_texture = id; } if (loads[IR::Attribute::InstanceId]) { if (profile.support_vertex_instance_id) { @@ -1332,7 +1332,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S)) { const Id id{DefineOutput(*this, F32[4], invocations)}; Decorate(id, spv::Decoration::Location, static_cast(12)); - output_txt_coord = id; + output_fixed_fnc_texture = id; } for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 1023d0ee4..9a76e1ca9 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h @@ -269,13 +269,13 @@ public: Id input_position{}; Id input_front_color{}; - Id input_txt_coord{}; + Id input_fixed_fnc_texture{}; std::array input_generics{}; Id output_point_size{}; Id output_position{}; Id output_front_color{}; - Id output_txt_coord; + Id output_fixed_fnc_texture; std::array, 32> output_generics{}; Id output_tess_level_outer{}; 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 0444bbf8f..a546d06a5 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 @@ -75,10 +75,10 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { } } if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { - const u32 index{IR::TxtCoordAttributeIndex(attr)}; - const u32 element{IR::TxtCoordAttributeElement(attr)}; + const u32 index{IR::FixedFncTextureAttributeIndex(attr)}; + const u32 element{IR::FixedFncTextureAttributeElement(attr)}; const Id element_id{ctx.Const(element)}; - return OutputAccessChain(ctx, ctx.output_f32, ctx.output_txt_coord, element_id); + return OutputAccessChain(ctx, ctx.output_f32, ctx.output_fixed_fnc_texture, element_id); } switch (attr) { case IR::Attribute::PointSize: @@ -322,8 +322,8 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value; } if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { - const u32 index{IR::TxtCoordAttributeIndex(attr)}; - return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_txt_coord, + const u32 index{IR::FixedFncTextureAttributeIndex(attr)}; + return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_fixed_fnc_texture, ctx.Const(element))); } switch (attr) { diff --git a/src/shader_recompiler/frontend/ir/attribute.cpp b/src/shader_recompiler/frontend/ir/attribute.cpp index dc2bec06d..5b3694f65 100644 --- a/src/shader_recompiler/frontend/ir/attribute.cpp +++ b/src/shader_recompiler/frontend/ir/attribute.cpp @@ -9,11 +9,21 @@ namespace Shader::IR { -u32 TxtCoordAttributeIndex(Attribute attribute) { +bool IsFixedFncTexture(Attribute attribute) { + return attribute >= Attribute::FixedFncTexture0S && attribute <= Attribute::FixedFncTexture9Q; +} + +u32 FixedFncTextureAttributeIndex(Attribute attribute) { + if (!IsFixedFncTexture(attribute)) { + throw InvalidArgument("Attribute is not fixedfnctexture {}", attribute); + } return (static_cast(attribute) - static_cast(Attribute::FixedFncTexture0S)) / 4u; } -u32 TxtCoordAttributeElement(Attribute attribute) { +u32 FixedFncTextureAttributeElement(Attribute attribute) { + if (!IsFixedFncTexture(attribute)) { + throw InvalidArgument("Attribute is not fixedfnctexture {}", attribute); + } return static_cast(attribute) % 4; } diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h index 6957fb43b..3f07fd7ac 100644 --- a/src/shader_recompiler/frontend/ir/attribute.h +++ b/src/shader_recompiler/frontend/ir/attribute.h @@ -222,12 +222,12 @@ enum class Attribute : u64 { FrontFace = 255, }; -constexpr size_t NUM_TXT_COORD = 10; +constexpr size_t NUM_FIXEDFNCTEXTURE = 10; constexpr size_t NUM_GENERICS = 32; -[[nodiscard]] u32 TxtCoordAttributeIndex(Attribute attribute); +[[nodiscard]] u32 FixedFncTextureAttributeIndex(Attribute attribute); -[[nodiscard]] u32 TxtCoordAttributeElement(Attribute attribute); +[[nodiscard]] u32 FixedFncTextureAttributeElement(Attribute attribute); [[nodiscard]] bool IsGeneric(Attribute attribute) noexcept; From d994466a08efaa2c06237e6ac840bc0e9000d433 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Sat, 4 Sep 2021 00:12:06 +0800 Subject: [PATCH 05/10] Implement intput and output fixed fnc textures --- .../backend/spirv/emit_context.cpp | 30 ++++++++++--------- .../backend/spirv/emit_context.h | 4 +-- .../spirv/emit_spirv_context_get_set.cpp | 8 +++-- src/shader_recompiler/frontend/ir/attribute.h | 2 ++ 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 3ec5a4570..81c79e1ed 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -1206,10 +1206,12 @@ void EmitContext::DefineInputs(const IR::Program& program) { Decorate(id, spv::Decoration::Location, static_cast(11)); input_front_color = id; } - if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S)) { - const Id id{DefineInput(*this, F32[4], true)}; - Decorate(id, spv::Decoration::Location, static_cast(12)); - input_fixed_fnc_texture = id; + for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) { + if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { + const Id id{DefineInput(*this, F32[4], true)}; + Decorate(id, spv::Decoration::Location, static_cast(12)); + input_fixed_fnc_textures[index] = id; + } } if (loads[IR::Attribute::InstanceId]) { if (profile.support_vertex_instance_id) { @@ -1292,11 +1294,6 @@ void EmitContext::DefineOutputs(const IR::Program& program) { if (info.stores.AnyComponent(IR::Attribute::PositionX) || stage == Stage::VertexB) { output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position); } - if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR) || stage == Stage::VertexB) { - const Id id{DefineOutput(*this, F32[4], invocations)}; - Decorate(id, spv::Decoration::Location, static_cast(11)); - output_front_color = id; - } if (info.stores[IR::Attribute::PointSize] || runtime_info.fixed_state_point_size) { if (stage == Stage::Fragment) { throw NotImplementedException("Storing PointSize in fragment stage"); @@ -1328,13 +1325,18 @@ void EmitContext::DefineOutputs(const IR::Program& program) { viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt, spv::BuiltIn::ViewportMaskNV); } - - if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S)) { + if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR) || stage == Stage::VertexB) { const Id id{DefineOutput(*this, F32[4], invocations)}; - Decorate(id, spv::Decoration::Location, static_cast(12)); - output_fixed_fnc_texture = id; + Decorate(id, spv::Decoration::Location, static_cast(11)); + output_front_color = id; + } + for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) { + if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { + const Id id{DefineOutput(*this, F32[4], invocations)}; + Decorate(id, spv::Decoration::Location, static_cast(12)); + output_fixed_fnc_textures[index] = id; + } } - for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { if (info.stores.Generic(index)) { DefineGenericOutput(*this, index, invocations); diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 9a76e1ca9..847d0c0e6 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h @@ -269,13 +269,13 @@ public: Id input_position{}; Id input_front_color{}; - Id input_fixed_fnc_texture{}; + std::array input_fixed_fnc_textures{}; std::array input_generics{}; Id output_point_size{}; Id output_position{}; Id output_front_color{}; - Id output_fixed_fnc_texture; + std::array output_fixed_fnc_textures{}; std::array, 32> output_generics{}; Id output_tess_level_outer{}; 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 a546d06a5..c3ebd3e6a 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 @@ -78,7 +78,8 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { const u32 index{IR::FixedFncTextureAttributeIndex(attr)}; const u32 element{IR::FixedFncTextureAttributeElement(attr)}; const Id element_id{ctx.Const(element)}; - return OutputAccessChain(ctx, ctx.output_f32, ctx.output_fixed_fnc_texture, element_id); + return OutputAccessChain(ctx, ctx.output_f32, ctx.output_fixed_fnc_textures[index], + element_id); } switch (attr) { case IR::Attribute::PointSize: @@ -323,8 +324,9 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { } if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { const u32 index{IR::FixedFncTextureAttributeIndex(attr)}; - return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_fixed_fnc_texture, - ctx.Const(element))); + return ctx.OpLoad(ctx.F32[1], + AttrPointer(ctx, ctx.input_f32, vertex, + ctx.input_fixed_fnc_textures[index], ctx.Const(element))); } switch (attr) { case IR::Attribute::PrimitiveId: diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h index 3f07fd7ac..9ca4dd76e 100644 --- a/src/shader_recompiler/frontend/ir/attribute.h +++ b/src/shader_recompiler/frontend/ir/attribute.h @@ -225,6 +225,8 @@ enum class Attribute : u64 { constexpr size_t NUM_FIXEDFNCTEXTURE = 10; constexpr size_t NUM_GENERICS = 32; +[[nodiscard]] bool IsFixedFncTexture(Attribute attribute); + [[nodiscard]] u32 FixedFncTextureAttributeIndex(Attribute attribute); [[nodiscard]] u32 FixedFncTextureAttributeElement(Attribute attribute); From 1de9e4e121a6648521debc21a46ef145156697c0 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Mon, 6 Sep 2021 10:46:03 +0800 Subject: [PATCH 06/10] Dynamic get unused location --- .../backend/spirv/emit_context.cpp | 76 ++++++++++++------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 81c79e1ed..2809f9281 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -1201,18 +1202,6 @@ void EmitContext::DefineInputs(const IR::Program& program) { } } } - if (loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { - const Id id{DefineInput(*this, F32[4], true)}; - Decorate(id, spv::Decoration::Location, static_cast(11)); - input_front_color = id; - } - for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) { - if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { - const Id id{DefineInput(*this, F32[4], true)}; - Decorate(id, spv::Decoration::Location, static_cast(12)); - input_fixed_fnc_textures[index] = id; - } - } if (loads[IR::Attribute::InstanceId]) { if (profile.support_vertex_instance_id) { instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId); @@ -1239,17 +1228,15 @@ void EmitContext::DefineInputs(const IR::Program& program) { loads[IR::Attribute::TessellationEvaluationPointV]) { tess_coord = DefineInput(*this, F32[3], false, spv::BuiltIn::TessCoord); } + std::queue ununsed_location; for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { const AttributeType input_type{runtime_info.generic_input_types[index]}; - if (!runtime_info.previous_stage_stores.Generic(index)) { - continue; - } - if (!loads.Generic(index)) { - continue; - } - if (input_type == AttributeType::Disabled) { + if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) || + input_type == AttributeType::Disabled) { + ununsed_location.push(static_cast(index)); continue; } + const Id type{GetAttributeType(*this, input_type)}; const Id id{DefineInput(*this, type, true)}; Decorate(id, spv::Decoration::Location, static_cast(index)); @@ -1275,6 +1262,28 @@ void EmitContext::DefineInputs(const IR::Program& program) { break; } } + if (loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { + if (ununsed_location.empty()) { + throw RuntimeError("Unable to get an unused location"); + } + u32 location = ununsed_location.front(); + ununsed_location.pop(); + const Id id{DefineInput(*this, F32[4], true)}; + Decorate(id, spv::Decoration::Location, location); + input_front_color = id; + } + for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) { + if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { + if (ununsed_location.empty()) { + throw RuntimeError("Unable to get an unused location"); + } + u32 location = ununsed_location.front(); + ununsed_location.pop(); + const Id id{DefineInput(*this, F32[4], true)}; + Decorate(id, spv::Decoration::Location, location); + input_fixed_fnc_textures[index] = id; + } + } if (stage == Stage::TessellationEval) { for (size_t index = 0; index < info.uses_patches.size(); ++index) { if (!info.uses_patches[index]) { @@ -1325,23 +1334,36 @@ void EmitContext::DefineOutputs(const IR::Program& program) { viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt, spv::BuiltIn::ViewportMaskNV); } - if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR) || stage == Stage::VertexB) { + std::queue ununsed_location; + for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { + if (info.stores.Generic(index)) { + DefineGenericOutput(*this, index, invocations); + } else { + ununsed_location.push(static_cast(index)); + } + } + if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { + if (ununsed_location.empty()) { + throw RuntimeError("Unable to get an unused location"); + } + u32 location = ununsed_location.front(); + ununsed_location.pop(); const Id id{DefineOutput(*this, F32[4], invocations)}; - Decorate(id, spv::Decoration::Location, static_cast(11)); + Decorate(id, spv::Decoration::Location, location); output_front_color = id; } for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) { if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { + if (ununsed_location.empty()) { + throw RuntimeError("Unable to get an unused location"); + } + u32 location = ununsed_location.front(); + ununsed_location.pop(); const Id id{DefineOutput(*this, F32[4], invocations)}; - Decorate(id, spv::Decoration::Location, static_cast(12)); + Decorate(id, spv::Decoration::Location, location); output_fixed_fnc_textures[index] = id; } } - for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { - if (info.stores.Generic(index)) { - DefineGenericOutput(*this, index, invocations); - } - } switch (stage) { case Stage::TessellationControl: if (info.stores_tess_level_outer) { From 9cdf2383e99fac2110d788da070f16b2b5c678e7 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Tue, 7 Sep 2021 12:34:35 +0800 Subject: [PATCH 07/10] Move attribute related definitions to spirv anonymous namespace --- .../backend/spirv/emit_context.cpp | 6 +++-- .../spirv/emit_spirv_context_get_set.cpp | 25 ++++++++++++++++--- .../frontend/ir/attribute.cpp | 18 ------------- src/shader_recompiler/frontend/ir/attribute.h | 7 ------ 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 2809f9281..f048174cb 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -428,6 +428,8 @@ Id DescType(EmitContext& ctx, Id sampled_type, Id pointer_type, u32 count) { return pointer_type; } } + +constexpr size_t NUM_FIXEDFNCTEXTURE = 10; } // Anonymous namespace void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { @@ -1272,7 +1274,7 @@ void EmitContext::DefineInputs(const IR::Program& program) { Decorate(id, spv::Decoration::Location, location); input_front_color = id; } - for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) { + for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) { if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { if (ununsed_location.empty()) { throw RuntimeError("Unable to get an unused location"); @@ -1352,7 +1354,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { Decorate(id, spv::Decoration::Location, location); output_front_color = id; } - for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) { + for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) { if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { if (ununsed_location.empty()) { throw RuntimeError("Unable to get an unused location"); 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 c3ebd3e6a..dd0d01b2a 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 @@ -43,6 +43,25 @@ Id AttrPointer(EmitContext& ctx, Id pointer_type, Id vertex, Id base, Args&&... } } +bool IsFixedFncTexture(IR::Attribute attribute) { + return attribute >= IR::Attribute::FixedFncTexture0S && + attribute <= IR::Attribute::FixedFncTexture9Q; +} + +u32 FixedFncTextureAttributeIndex(IR::Attribute attribute) { + if (!IsFixedFncTexture(attribute)) { + throw InvalidArgument("Attribute is not fixedfnctexture {}", attribute); + } + return (static_cast(attribute) - static_cast(IR::Attribute::FixedFncTexture0S)) / 4u; +} + +u32 FixedFncTextureAttributeElement(IR::Attribute attribute) { + if (!IsFixedFncTexture(attribute)) { + throw InvalidArgument("Attribute is not fixedfnctexture {}", attribute); + } + return static_cast(attribute) % 4; +} + template Id OutputAccessChain(EmitContext& ctx, Id result_type, Id base, Args&&... args) { if (ctx.stage == Stage::TessellationControl) { @@ -75,8 +94,8 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { } } if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { - const u32 index{IR::FixedFncTextureAttributeIndex(attr)}; - const u32 element{IR::FixedFncTextureAttributeElement(attr)}; + const u32 index{FixedFncTextureAttributeIndex(attr)}; + const u32 element{FixedFncTextureAttributeElement(attr)}; const Id element_id{ctx.Const(element)}; return OutputAccessChain(ctx, ctx.output_f32, ctx.output_fixed_fnc_textures[index], element_id); @@ -323,7 +342,7 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value; } if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { - const u32 index{IR::FixedFncTextureAttributeIndex(attr)}; + const u32 index{FixedFncTextureAttributeIndex(attr)}; return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_fixed_fnc_textures[index], ctx.Const(element))); diff --git a/src/shader_recompiler/frontend/ir/attribute.cpp b/src/shader_recompiler/frontend/ir/attribute.cpp index 5b3694f65..4d0b8b8e5 100644 --- a/src/shader_recompiler/frontend/ir/attribute.cpp +++ b/src/shader_recompiler/frontend/ir/attribute.cpp @@ -9,24 +9,6 @@ namespace Shader::IR { -bool IsFixedFncTexture(Attribute attribute) { - return attribute >= Attribute::FixedFncTexture0S && attribute <= Attribute::FixedFncTexture9Q; -} - -u32 FixedFncTextureAttributeIndex(Attribute attribute) { - if (!IsFixedFncTexture(attribute)) { - throw InvalidArgument("Attribute is not fixedfnctexture {}", attribute); - } - return (static_cast(attribute) - static_cast(Attribute::FixedFncTexture0S)) / 4u; -} - -u32 FixedFncTextureAttributeElement(Attribute attribute) { - if (!IsFixedFncTexture(attribute)) { - throw InvalidArgument("Attribute is not fixedfnctexture {}", attribute); - } - return static_cast(attribute) % 4; -} - bool IsGeneric(Attribute attribute) noexcept { return attribute >= Attribute::Generic0X && attribute <= Attribute::Generic31X; } diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h index 9ca4dd76e..ca1199494 100644 --- a/src/shader_recompiler/frontend/ir/attribute.h +++ b/src/shader_recompiler/frontend/ir/attribute.h @@ -222,15 +222,8 @@ enum class Attribute : u64 { FrontFace = 255, }; -constexpr size_t NUM_FIXEDFNCTEXTURE = 10; constexpr size_t NUM_GENERICS = 32; -[[nodiscard]] bool IsFixedFncTexture(Attribute attribute); - -[[nodiscard]] u32 FixedFncTextureAttributeIndex(Attribute attribute); - -[[nodiscard]] u32 FixedFncTextureAttributeElement(Attribute attribute); - [[nodiscard]] bool IsGeneric(Attribute attribute) noexcept; [[nodiscard]] u32 GenericAttributeIndex(Attribute attribute); From e5ca733722865daa43eca8679f3c55826f0b88e6 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Tue, 7 Sep 2021 13:21:17 +0800 Subject: [PATCH 08/10] Re-implement get unused location --- .../backend/spirv/emit_context.cpp | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index f048174cb..b9fa5098c 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include @@ -430,6 +429,16 @@ Id DescType(EmitContext& ctx, Id sampled_type, Id pointer_type, u32 count) { } constexpr size_t NUM_FIXEDFNCTEXTURE = 10; + +size_t FindFistUnUsedLocation(const auto& used_location) { + if (used_location.all()) { + throw RuntimeError("Unable to get an unused location"); + } + size_t location = 0; + while (location < used_location.size() && used_location.test(location)) + ++location; + return location; +} } // Anonymous namespace void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { @@ -1230,15 +1239,19 @@ void EmitContext::DefineInputs(const IR::Program& program) { loads[IR::Attribute::TessellationEvaluationPointV]) { tess_coord = DefineInput(*this, F32[3], false, spv::BuiltIn::TessCoord); } - std::queue ununsed_location; + std::bitset used_location; for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { const AttributeType input_type{runtime_info.generic_input_types[index]}; - if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) || - input_type == AttributeType::Disabled) { - ununsed_location.push(static_cast(index)); + if (!runtime_info.previous_stage_stores.Generic(index)) { continue; } - + if (!loads.Generic(index)) { + continue; + } + if (input_type == AttributeType::Disabled) { + continue; + } + used_location.set(index); const Id type{GetAttributeType(*this, input_type)}; const Id id{DefineInput(*this, type, true)}; Decorate(id, spv::Decoration::Location, static_cast(index)); @@ -1265,22 +1278,16 @@ void EmitContext::DefineInputs(const IR::Program& program) { } } if (loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { - if (ununsed_location.empty()) { - throw RuntimeError("Unable to get an unused location"); - } - u32 location = ununsed_location.front(); - ununsed_location.pop(); + size_t location = FindFistUnUsedLocation(used_location); + used_location.set(location); const Id id{DefineInput(*this, F32[4], true)}; Decorate(id, spv::Decoration::Location, location); input_front_color = id; } for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) { if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { - if (ununsed_location.empty()) { - throw RuntimeError("Unable to get an unused location"); - } - u32 location = ununsed_location.front(); - ununsed_location.pop(); + size_t location = FindFistUnUsedLocation(used_location); + used_location.set(location); const Id id{DefineInput(*this, F32[4], true)}; Decorate(id, spv::Decoration::Location, location); input_fixed_fnc_textures[index] = id; @@ -1336,31 +1343,24 @@ void EmitContext::DefineOutputs(const IR::Program& program) { viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt, spv::BuiltIn::ViewportMaskNV); } - std::queue ununsed_location; + std::bitset used_location; for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { if (info.stores.Generic(index)) { DefineGenericOutput(*this, index, invocations); - } else { - ununsed_location.push(static_cast(index)); + used_location.set(index); } } if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { - if (ununsed_location.empty()) { - throw RuntimeError("Unable to get an unused location"); - } - u32 location = ununsed_location.front(); - ununsed_location.pop(); + size_t location = FindFistUnUsedLocation(used_location); + used_location.set(location); const Id id{DefineOutput(*this, F32[4], invocations)}; - Decorate(id, spv::Decoration::Location, location); + Decorate(id, spv::Decoration::Location, static_cast(location)); output_front_color = id; } for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) { if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { - if (ununsed_location.empty()) { - throw RuntimeError("Unable to get an unused location"); - } - u32 location = ununsed_location.front(); - ununsed_location.pop(); + size_t location = FindFistUnUsedLocation(used_location); + used_location.set(location); const Id id{DefineOutput(*this, F32[4], invocations)}; Decorate(id, spv::Decoration::Location, location); output_fixed_fnc_textures[index] = id; From bbc1800c1b22097c56ecb799c0e475aaf8502038 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Wed, 8 Sep 2021 09:53:10 +0800 Subject: [PATCH 09/10] Detail adjustment --- .../backend/spirv/emit_context.cpp | 47 +++++++++++-------- .../spirv/emit_spirv_context_get_set.cpp | 16 +++---- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index b9fa5098c..118a80165 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -15,6 +15,8 @@ namespace Shader::Backend::SPIRV { namespace { +constexpr size_t NUM_FIXEDFNCTEXTURE = 10; + enum class Operation { Increment, Decrement, @@ -428,15 +430,14 @@ Id DescType(EmitContext& ctx, Id sampled_type, Id pointer_type, u32 count) { } } -constexpr size_t NUM_FIXEDFNCTEXTURE = 10; - -size_t FindFistUnUsedLocation(const auto& used_location) { - if (used_location.all()) { - throw RuntimeError("Unable to get an unused location"); - } - size_t location = 0; - while (location < used_location.size() && used_location.test(location)) +size_t FindFistUnUsedLocation(const std::bitset& used_locations, + size_t previous_unused_location) { + size_t location = previous_unused_location + 1; + while (location < used_locations.size() && used_locations.test(location)) ++location; + if (location == used_locations.size()) { + throw RuntimeError("Unable to get an unused location for legacy attribute"); + } return location; } } // Anonymous namespace @@ -1239,7 +1240,7 @@ void EmitContext::DefineInputs(const IR::Program& program) { loads[IR::Attribute::TessellationEvaluationPointV]) { tess_coord = DefineInput(*this, F32[3], false, spv::BuiltIn::TessCoord); } - std::bitset used_location; + std::bitset used_locations{}; for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { const AttributeType input_type{runtime_info.generic_input_types[index]}; if (!runtime_info.previous_stage_stores.Generic(index)) { @@ -1251,7 +1252,7 @@ void EmitContext::DefineInputs(const IR::Program& program) { if (input_type == AttributeType::Disabled) { continue; } - used_location.set(index); + used_locations.set(index); const Id type{GetAttributeType(*this, input_type)}; const Id id{DefineInput(*this, type, true)}; Decorate(id, spv::Decoration::Location, static_cast(index)); @@ -1277,17 +1278,20 @@ void EmitContext::DefineInputs(const IR::Program& program) { break; } } + size_t previous_unused_location = 0; if (loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { - size_t location = FindFistUnUsedLocation(used_location); - used_location.set(location); + size_t location = FindFistUnUsedLocation(used_locations, previous_unused_location); + previous_unused_location = location; + used_locations.set(location); const Id id{DefineInput(*this, F32[4], true)}; Decorate(id, spv::Decoration::Location, location); input_front_color = id; } for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) { if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { - size_t location = FindFistUnUsedLocation(used_location); - used_location.set(location); + size_t location = FindFistUnUsedLocation(used_locations, previous_unused_location); + previous_unused_location = location; + used_locations.set(location); const Id id{DefineInput(*this, F32[4], true)}; Decorate(id, spv::Decoration::Location, location); input_fixed_fnc_textures[index] = id; @@ -1343,24 +1347,27 @@ void EmitContext::DefineOutputs(const IR::Program& program) { viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt, spv::BuiltIn::ViewportMaskNV); } - std::bitset used_location; + std::bitset used_locations{}; for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { if (info.stores.Generic(index)) { DefineGenericOutput(*this, index, invocations); - used_location.set(index); + used_locations.set(index); } } + size_t previous_unused_location = 0; if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { - size_t location = FindFistUnUsedLocation(used_location); - used_location.set(location); + size_t location = FindFistUnUsedLocation(used_locations, previous_unused_location); + previous_unused_location = location; + used_locations.set(location); const Id id{DefineOutput(*this, F32[4], invocations)}; Decorate(id, spv::Decoration::Location, static_cast(location)); output_front_color = id; } for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) { if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { - size_t location = FindFistUnUsedLocation(used_location); - used_location.set(location); + size_t location = FindFistUnUsedLocation(used_locations, previous_unused_location); + previous_unused_location = location; + used_locations.set(location); const Id id{DefineOutput(*this, F32[4], invocations)}; Decorate(id, spv::Decoration::Location, location); output_fixed_fnc_textures[index] = id; 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 dd0d01b2a..67df46499 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 @@ -50,16 +50,16 @@ bool IsFixedFncTexture(IR::Attribute attribute) { u32 FixedFncTextureAttributeIndex(IR::Attribute attribute) { if (!IsFixedFncTexture(attribute)) { - throw InvalidArgument("Attribute is not fixedfnctexture {}", attribute); + throw InvalidArgument("Attribute {} is not a FixedFncTexture", attribute); } return (static_cast(attribute) - static_cast(IR::Attribute::FixedFncTexture0S)) / 4u; } u32 FixedFncTextureAttributeElement(IR::Attribute attribute) { if (!IsFixedFncTexture(attribute)) { - throw InvalidArgument("Attribute is not fixedfnctexture {}", attribute); + throw InvalidArgument("Attribute {} is not a FixedFncTexture", attribute); } - return static_cast(attribute) % 4; + return static_cast(attribute) % 4u; } template @@ -93,7 +93,7 @@ std::optional OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id); } } - if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { + if (IsFixedFncTexture(attr)) { const u32 index{FixedFncTextureAttributeIndex(attr)}; const u32 element{FixedFncTextureAttributeElement(attr)}; const Id element_id{ctx.Const(element)}; @@ -341,11 +341,11 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { const Id value{ctx.OpLoad(type->id, pointer)}; return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value; } - if (attr >= IR::Attribute::FixedFncTexture0S && attr <= IR::Attribute::FixedFncTexture9Q) { + if (IsFixedFncTexture(attr)) { const u32 index{FixedFncTextureAttributeIndex(attr)}; - return ctx.OpLoad(ctx.F32[1], - AttrPointer(ctx, ctx.input_f32, vertex, - ctx.input_fixed_fnc_textures[index], ctx.Const(element))); + const Id attr_id{ctx.input_fixed_fnc_textures[index]}; + const Id attr_ptr{AttrPointer(ctx, ctx.input_f32, vertex, attr_id, ctx.Const(element))}; + return ctx.OpLoad(ctx.F32[1], attr_ptr); } switch (attr) { case IR::Attribute::PrimitiveId: From b1e655f89824bb1c43fc5160cd879b60bb60dbad Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Wed, 8 Sep 2021 10:28:09 +0800 Subject: [PATCH 10/10] Detail adjustment --- .../backend/spirv/emit_context.cpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 118a80165..2885e6799 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -430,15 +430,14 @@ Id DescType(EmitContext& ctx, Id sampled_type, Id pointer_type, u32 count) { } } -size_t FindFistUnUsedLocation(const std::bitset& used_locations, - size_t previous_unused_location) { - size_t location = previous_unused_location + 1; - while (location < used_locations.size() && used_locations.test(location)) - ++location; - if (location == used_locations.size()) { - throw RuntimeError("Unable to get an unused location for legacy attribute"); +size_t FindNextUnusedLocation(const std::bitset& used_locations, + size_t start_offset) { + for (size_t location = start_offset; location < used_locations.size(); ++location) { + if (!used_locations.test(location)) { + return location; + } } - return location; + throw RuntimeError("Unable to get an unused location for legacy attribute"); } } // Anonymous namespace @@ -1280,7 +1279,7 @@ void EmitContext::DefineInputs(const IR::Program& program) { } size_t previous_unused_location = 0; if (loads.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { - size_t location = FindFistUnUsedLocation(used_locations, previous_unused_location); + const size_t location = FindNextUnusedLocation(used_locations, previous_unused_location); previous_unused_location = location; used_locations.set(location); const Id id{DefineInput(*this, F32[4], true)}; @@ -1289,7 +1288,8 @@ void EmitContext::DefineInputs(const IR::Program& program) { } for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) { if (loads.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { - size_t location = FindFistUnUsedLocation(used_locations, previous_unused_location); + const size_t location = + FindNextUnusedLocation(used_locations, previous_unused_location); previous_unused_location = location; used_locations.set(location); const Id id{DefineInput(*this, F32[4], true)}; @@ -1356,7 +1356,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { } size_t previous_unused_location = 0; if (info.stores.AnyComponent(IR::Attribute::ColorFrontDiffuseR)) { - size_t location = FindFistUnUsedLocation(used_locations, previous_unused_location); + const size_t location = FindNextUnusedLocation(used_locations, previous_unused_location); previous_unused_location = location; used_locations.set(location); const Id id{DefineOutput(*this, F32[4], invocations)}; @@ -1365,7 +1365,8 @@ void EmitContext::DefineOutputs(const IR::Program& program) { } for (size_t index = 0; index < NUM_FIXEDFNCTEXTURE; ++index) { if (info.stores.AnyComponent(IR::Attribute::FixedFncTexture0S + index * 4)) { - size_t location = FindFistUnUsedLocation(used_locations, previous_unused_location); + const size_t location = + FindNextUnusedLocation(used_locations, previous_unused_location); previous_unused_location = location; used_locations.set(location); const Id id{DefineOutput(*this, F32[4], invocations)};