diff options
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_context.h | 17 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv.h | 8 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 63 |
3 files changed, 67 insertions, 21 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 528dc33fe..9db2b0c94 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -97,6 +97,23 @@ public: | |||
| 97 | 97 | ||
| 98 | [[nodiscard]] Id Def(const IR::Value& value); | 98 | [[nodiscard]] Id Def(const IR::Value& value); |
| 99 | 99 | ||
| 100 | Id Const(u32 value) { | ||
| 101 | return Constant(U32[1], value); | ||
| 102 | } | ||
| 103 | |||
| 104 | Id Const(u32 element_1, u32 element_2) { | ||
| 105 | return ConstantComposite(U32[2], Const(element_1), Const(element_2)); | ||
| 106 | } | ||
| 107 | |||
| 108 | Id Const(u32 element_1, u32 element_2, u32 element_3) { | ||
| 109 | return ConstantComposite(U32[3], Const(element_1), Const(element_2), Const(element_3)); | ||
| 110 | } | ||
| 111 | |||
| 112 | Id Const(u32 element_1, u32 element_2, u32 element_3, u32 element_4) { | ||
| 113 | return ConstantComposite(U32[2], Const(element_1), Const(element_2), Const(element_3), | ||
| 114 | Const(element_4)); | ||
| 115 | } | ||
| 116 | |||
| 100 | const Profile& profile; | 117 | const Profile& profile; |
| 101 | Stage stage{}; | 118 | Stage stage{}; |
| 102 | 119 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 9f658a4bd..cf8d74f4e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -490,13 +490,13 @@ Id EmitBoundImageGradient(EmitContext&); | |||
| 490 | Id EmitBoundImageRead(EmitContext&); | 490 | Id EmitBoundImageRead(EmitContext&); |
| 491 | Id EmitBoundImageWrite(EmitContext&); | 491 | Id EmitBoundImageWrite(EmitContext&); |
| 492 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 492 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 493 | Id bias_lc, Id offset); | 493 | Id bias_lc, const IR::Value& offset); |
| 494 | Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 494 | Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 495 | Id lod_lc, Id offset); | 495 | Id lod_lc, const IR::Value& offset); |
| 496 | Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 496 | Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, |
| 497 | Id coords, Id dref, Id bias_lc, Id offset); | 497 | Id coords, Id dref, Id bias_lc, const IR::Value& offset); |
| 498 | Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 498 | Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, |
| 499 | Id coords, Id dref, Id lod_lc, Id offset); | 499 | Id coords, Id dref, Id lod_lc, const IR::Value& offset); |
| 500 | Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 500 | Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 501 | const IR::Value& offset, const IR::Value& offset2); | 501 | const IR::Value& offset, const IR::Value& offset2); |
| 502 | Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 502 | Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index c8d1d25b1..021933a8c 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -12,7 +12,7 @@ namespace { | |||
| 12 | class ImageOperands { | 12 | class ImageOperands { |
| 13 | public: | 13 | public: |
| 14 | explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp, | 14 | explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp, |
| 15 | Id lod, Id offset) { | 15 | Id lod, const IR::Value& offset) { |
| 16 | if (has_bias) { | 16 | if (has_bias) { |
| 17 | const Id bias{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod}; | 17 | const Id bias{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod}; |
| 18 | Add(spv::ImageOperandsMask::Bias, bias); | 18 | Add(spv::ImageOperandsMask::Bias, bias); |
| @@ -21,9 +21,7 @@ public: | |||
| 21 | const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod}; | 21 | const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod}; |
| 22 | Add(spv::ImageOperandsMask::Lod, lod_value); | 22 | Add(spv::ImageOperandsMask::Lod, lod_value); |
| 23 | } | 23 | } |
| 24 | if (Sirit::ValidId(offset)) { | 24 | AddOffset(ctx, offset); |
| 25 | Add(spv::ImageOperandsMask::Offset, offset); | ||
| 26 | } | ||
| 27 | if (has_lod_clamp) { | 25 | if (has_lod_clamp) { |
| 28 | const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod}; | 26 | const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod}; |
| 29 | Add(spv::ImageOperandsMask::MinLod, lod_clamp); | 27 | Add(spv::ImageOperandsMask::MinLod, lod_clamp); |
| @@ -96,6 +94,46 @@ public: | |||
| 96 | } | 94 | } |
| 97 | } | 95 | } |
| 98 | 96 | ||
| 97 | std::span<const Id> Span() const noexcept { | ||
| 98 | return std::span{operands.data(), operands.size()}; | ||
| 99 | } | ||
| 100 | |||
| 101 | spv::ImageOperandsMask Mask() const noexcept { | ||
| 102 | return mask; | ||
| 103 | } | ||
| 104 | |||
| 105 | private: | ||
| 106 | void AddOffset(EmitContext& ctx, const IR::Value& offset) { | ||
| 107 | if (offset.IsEmpty()) { | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | if (offset.IsImmediate()) { | ||
| 111 | Add(spv::ImageOperandsMask::ConstOffset, ctx.Constant(ctx.U32[1], offset.U32())); | ||
| 112 | return; | ||
| 113 | } | ||
| 114 | IR::Inst* const inst{offset.InstRecursive()}; | ||
| 115 | if (inst->AreAllArgsImmediates()) { | ||
| 116 | switch (inst->GetOpcode()) { | ||
| 117 | case IR::Opcode::CompositeConstructU32x2: | ||
| 118 | Add(spv::ImageOperandsMask::ConstOffset, | ||
| 119 | ctx.Const(inst->Arg(0).U32(), inst->Arg(1).U32())); | ||
| 120 | return; | ||
| 121 | case IR::Opcode::CompositeConstructU32x3: | ||
| 122 | Add(spv::ImageOperandsMask::ConstOffset, | ||
| 123 | ctx.Const(inst->Arg(0).U32(), inst->Arg(1).U32(), inst->Arg(2).U32())); | ||
| 124 | return; | ||
| 125 | case IR::Opcode::CompositeConstructU32x4: | ||
| 126 | Add(spv::ImageOperandsMask::ConstOffset, | ||
| 127 | ctx.Const(inst->Arg(0).U32(), inst->Arg(1).U32(), inst->Arg(2).U32(), | ||
| 128 | inst->Arg(3).U32())); | ||
| 129 | return; | ||
| 130 | default: | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | Add(spv::ImageOperandsMask::Offset, ctx.Def(offset)); | ||
| 135 | } | ||
| 136 | |||
| 99 | void Add(spv::ImageOperandsMask new_mask, Id value) { | 137 | void Add(spv::ImageOperandsMask new_mask, Id value) { |
| 100 | mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) | | 138 | mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) | |
| 101 | static_cast<unsigned>(new_mask)); | 139 | static_cast<unsigned>(new_mask)); |
| @@ -109,15 +147,6 @@ public: | |||
| 109 | operands.push_back(value_2); | 147 | operands.push_back(value_2); |
| 110 | } | 148 | } |
| 111 | 149 | ||
| 112 | std::span<const Id> Span() const noexcept { | ||
| 113 | return std::span{operands.data(), operands.size()}; | ||
| 114 | } | ||
| 115 | |||
| 116 | spv::ImageOperandsMask Mask() const noexcept { | ||
| 117 | return mask; | ||
| 118 | } | ||
| 119 | |||
| 120 | private: | ||
| 121 | boost::container::static_vector<Id, 4> operands; | 150 | boost::container::static_vector<Id, 4> operands; |
| 122 | spv::ImageOperandsMask mask{}; | 151 | spv::ImageOperandsMask mask{}; |
| 123 | }; | 152 | }; |
| @@ -279,7 +308,7 @@ Id EmitBoundImageWrite(EmitContext&) { | |||
| 279 | } | 308 | } |
| 280 | 309 | ||
| 281 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 310 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 282 | Id bias_lc, Id offset) { | 311 | Id bias_lc, const IR::Value& offset) { |
| 283 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 312 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 284 | const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc, | 313 | const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc, |
| 285 | offset); | 314 | offset); |
| @@ -289,7 +318,7 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& | |||
| 289 | } | 318 | } |
| 290 | 319 | ||
| 291 | Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 320 | Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 292 | Id lod_lc, Id offset) { | 321 | Id lod_lc, const IR::Value& offset) { |
| 293 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 322 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 294 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); | 323 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); |
| 295 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, | 324 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
| @@ -298,7 +327,7 @@ Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& | |||
| 298 | } | 327 | } |
| 299 | 328 | ||
| 300 | Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 329 | Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, |
| 301 | Id coords, Id dref, Id bias_lc, Id offset) { | 330 | Id coords, Id dref, Id bias_lc, const IR::Value& offset) { |
| 302 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 331 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 303 | const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc, | 332 | const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc, |
| 304 | offset); | 333 | offset); |
| @@ -308,7 +337,7 @@ Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va | |||
| 308 | } | 337 | } |
| 309 | 338 | ||
| 310 | Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 339 | Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, |
| 311 | Id coords, Id dref, Id lod_lc, Id offset) { | 340 | Id coords, Id dref, Id lod_lc, const IR::Value& offset) { |
| 312 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 341 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 313 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); | 342 | const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset); |
| 314 | return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod, | 343 | return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod, |