diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 76 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | 2 |
2 files changed, 55 insertions, 23 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 800754554..64a4e0e55 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -12,6 +12,11 @@ namespace Shader::Backend::SPIRV { | |||
| 12 | namespace { | 12 | namespace { |
| 13 | class ImageOperands { | 13 | class ImageOperands { |
| 14 | public: | 14 | public: |
| 15 | [[maybe_unused]] static constexpr bool ImageSampleOffsetAllowed = false; | ||
| 16 | [[maybe_unused]] static constexpr bool ImageGatherOffsetAllowed = true; | ||
| 17 | [[maybe_unused]] static constexpr bool ImageFetchOffsetAllowed = false; | ||
| 18 | [[maybe_unused]] static constexpr bool ImageGradientOffsetAllowed = false; | ||
| 19 | |||
| 15 | explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp, | 20 | explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp, |
| 16 | Id lod, const IR::Value& offset) { | 21 | Id lod, const IR::Value& offset) { |
| 17 | if (has_bias) { | 22 | if (has_bias) { |
| @@ -22,7 +27,7 @@ public: | |||
| 22 | const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod}; | 27 | const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod}; |
| 23 | Add(spv::ImageOperandsMask::Lod, lod_value); | 28 | Add(spv::ImageOperandsMask::Lod, lod_value); |
| 24 | } | 29 | } |
| 25 | AddOffset(ctx, offset); | 30 | AddOffset(ctx, offset, ImageSampleOffsetAllowed); |
| 26 | if (has_lod_clamp) { | 31 | if (has_lod_clamp) { |
| 27 | const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod}; | 32 | const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod}; |
| 28 | Add(spv::ImageOperandsMask::MinLod, lod_clamp); | 33 | Add(spv::ImageOperandsMask::MinLod, lod_clamp); |
| @@ -55,20 +60,17 @@ public: | |||
| 55 | Add(spv::ImageOperandsMask::ConstOffsets, offsets); | 60 | Add(spv::ImageOperandsMask::ConstOffsets, offsets); |
| 56 | } | 61 | } |
| 57 | 62 | ||
| 58 | explicit ImageOperands(Id offset, Id lod, Id ms) { | 63 | explicit ImageOperands(Id lod, Id ms) { |
| 59 | if (Sirit::ValidId(lod)) { | 64 | if (Sirit::ValidId(lod)) { |
| 60 | Add(spv::ImageOperandsMask::Lod, lod); | 65 | Add(spv::ImageOperandsMask::Lod, lod); |
| 61 | } | 66 | } |
| 62 | if (Sirit::ValidId(offset)) { | ||
| 63 | Add(spv::ImageOperandsMask::Offset, offset); | ||
| 64 | } | ||
| 65 | if (Sirit::ValidId(ms)) { | 67 | if (Sirit::ValidId(ms)) { |
| 66 | Add(spv::ImageOperandsMask::Sample, ms); | 68 | Add(spv::ImageOperandsMask::Sample, ms); |
| 67 | } | 69 | } |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives, | 72 | explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives, |
| 71 | u32 num_derivatives, Id offset, Id lod_clamp) { | 73 | u32 num_derivatives, const IR::Value& offset, Id lod_clamp) { |
| 72 | if (!Sirit::ValidId(derivatives)) { | 74 | if (!Sirit::ValidId(derivatives)) { |
| 73 | throw LogicError("Derivatives must be present"); | 75 | throw LogicError("Derivatives must be present"); |
| 74 | } | 76 | } |
| @@ -83,16 +85,14 @@ public: | |||
| 83 | const Id derivatives_Y{ctx.OpCompositeConstruct( | 85 | const Id derivatives_Y{ctx.OpCompositeConstruct( |
| 84 | ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; | 86 | ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; |
| 85 | Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y); | 87 | Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y); |
| 86 | if (Sirit::ValidId(offset)) { | 88 | AddOffset(ctx, offset, ImageGradientOffsetAllowed); |
| 87 | Add(spv::ImageOperandsMask::Offset, offset); | ||
| 88 | } | ||
| 89 | if (has_lod_clamp) { | 89 | if (has_lod_clamp) { |
| 90 | Add(spv::ImageOperandsMask::MinLod, lod_clamp); | 90 | Add(spv::ImageOperandsMask::MinLod, lod_clamp); |
| 91 | } | 91 | } |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2, | 94 | explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2, |
| 95 | Id offset, Id lod_clamp) { | 95 | const IR::Value& offset, Id lod_clamp) { |
| 96 | if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) { | 96 | if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) { |
| 97 | throw LogicError("Derivatives must be present"); | 97 | throw LogicError("Derivatives must be present"); |
| 98 | } | 98 | } |
| @@ -111,9 +111,7 @@ public: | |||
| 111 | const Id derivatives_id2{ctx.OpCompositeConstruct( | 111 | const Id derivatives_id2{ctx.OpCompositeConstruct( |
| 112 | ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})}; | 112 | ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})}; |
| 113 | Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2); | 113 | Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2); |
| 114 | if (Sirit::ValidId(offset)) { | 114 | AddOffset(ctx, offset, ImageGradientOffsetAllowed); |
| 115 | Add(spv::ImageOperandsMask::Offset, offset); | ||
| 116 | } | ||
| 117 | if (has_lod_clamp) { | 115 | if (has_lod_clamp) { |
| 118 | Add(spv::ImageOperandsMask::MinLod, lod_clamp); | 116 | Add(spv::ImageOperandsMask::MinLod, lod_clamp); |
| 119 | } | 117 | } |
| @@ -132,7 +130,7 @@ public: | |||
| 132 | } | 130 | } |
| 133 | 131 | ||
| 134 | private: | 132 | private: |
| 135 | void AddOffset(EmitContext& ctx, const IR::Value& offset) { | 133 | void AddOffset(EmitContext& ctx, const IR::Value& offset, bool runtime_offset_allowed) { |
| 136 | if (offset.IsEmpty()) { | 134 | if (offset.IsEmpty()) { |
| 137 | return; | 135 | return; |
| 138 | } | 136 | } |
| @@ -165,7 +163,9 @@ private: | |||
| 165 | break; | 163 | break; |
| 166 | } | 164 | } |
| 167 | } | 165 | } |
| 168 | Add(spv::ImageOperandsMask::Offset, ctx.Def(offset)); | 166 | if (runtime_offset_allowed) { |
| 167 | Add(spv::ImageOperandsMask::Offset, ctx.Def(offset)); | ||
| 168 | } | ||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | void Add(spv::ImageOperandsMask new_mask, Id value) { | 171 | void Add(spv::ImageOperandsMask new_mask, Id value) { |
| @@ -311,6 +311,37 @@ Id ImageGatherSubpixelOffset(EmitContext& ctx, const IR::TextureInstInfo& info, | |||
| 311 | return coords; | 311 | return coords; |
| 312 | } | 312 | } |
| 313 | } | 313 | } |
| 314 | |||
| 315 | void AddOffsetToCoordinates(EmitContext& ctx, const IR::TextureInstInfo& info, Id& coords, | ||
| 316 | Id offset) { | ||
| 317 | if (!Sirit::ValidId(offset)) { | ||
| 318 | return; | ||
| 319 | } | ||
| 320 | |||
| 321 | Id result_type{}; | ||
| 322 | switch (info.type) { | ||
| 323 | case TextureType::Buffer: | ||
| 324 | case TextureType::Color1D: | ||
| 325 | case TextureType::ColorArray1D: { | ||
| 326 | result_type = ctx.U32[1]; | ||
| 327 | break; | ||
| 328 | } | ||
| 329 | case TextureType::Color2D: | ||
| 330 | case TextureType::Color2DRect: | ||
| 331 | case TextureType::ColorArray2D: { | ||
| 332 | result_type = ctx.U32[2]; | ||
| 333 | break; | ||
| 334 | } | ||
| 335 | case TextureType::Color3D: { | ||
| 336 | result_type = ctx.U32[3]; | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | case TextureType::ColorCube: | ||
| 340 | case TextureType::ColorArrayCube: | ||
| 341 | return; | ||
| 342 | } | ||
| 343 | coords = ctx.OpIAdd(result_type, coords, offset); | ||
| 344 | } | ||
| 314 | } // Anonymous namespace | 345 | } // Anonymous namespace |
| 315 | 346 | ||
| 316 | Id EmitBindlessImageSampleImplicitLod(EmitContext&) { | 347 | Id EmitBindlessImageSampleImplicitLod(EmitContext&) { |
| @@ -496,6 +527,7 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | |||
| 496 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, | 527 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, |
| 497 | Id lod, Id ms) { | 528 | Id lod, Id ms) { |
| 498 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 529 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 530 | AddOffsetToCoordinates(ctx, info, coords, offset); | ||
| 499 | if (info.type == TextureType::Buffer) { | 531 | if (info.type == TextureType::Buffer) { |
| 500 | lod = Id{}; | 532 | lod = Id{}; |
| 501 | } | 533 | } |
| @@ -503,7 +535,7 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c | |||
| 503 | // This image is multisampled, lod must be implicit | 535 | // This image is multisampled, lod must be implicit |
| 504 | lod = Id{}; | 536 | lod = Id{}; |
| 505 | } | 537 | } |
| 506 | const ImageOperands operands(offset, lod, ms); | 538 | const ImageOperands operands(lod, ms); |
| 507 | return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], | 539 | return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], |
| 508 | TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); | 540 | TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); |
| 509 | } | 541 | } |
| @@ -548,13 +580,13 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I | |||
| 548 | } | 580 | } |
| 549 | 581 | ||
| 550 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 582 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 551 | Id derivatives, Id offset, Id lod_clamp) { | 583 | Id derivatives, const IR::Value& offset, Id lod_clamp) { |
| 552 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 584 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 553 | const auto operands = | 585 | const auto operands = info.num_derivatives == 3 |
| 554 | info.num_derivatives == 3 | 586 | ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, |
| 555 | ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, offset, {}, lod_clamp) | 587 | ctx.Def(offset), {}, lod_clamp) |
| 556 | : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset, | 588 | : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, |
| 557 | lod_clamp); | 589 | info.num_derivatives, offset, lod_clamp); |
| 558 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, | 590 | return Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
| 559 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], | 591 | &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], |
| 560 | Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); | 592 | Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 7d34575c8..5c01b1012 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | |||
| @@ -543,7 +543,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 543 | const IR::Value& skip_mips); | 543 | const IR::Value& skip_mips); |
| 544 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | 544 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); |
| 545 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 545 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 546 | Id derivatives, Id offset, Id lod_clamp); | 546 | Id derivatives, const IR::Value& offset, Id lod_clamp); |
| 547 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | 547 | Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); |
| 548 | void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); | 548 | void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); |
| 549 | Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index); | 549 | Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index); |