summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp76
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_instructions.h2
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 {
12namespace { 12namespace {
13class ImageOperands { 13class ImageOperands {
14public: 14public:
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
134private: 132private:
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
315void 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
316Id EmitBindlessImageSampleImplicitLod(EmitContext&) { 347Id EmitBindlessImageSampleImplicitLod(EmitContext&) {
@@ -496,6 +527,7 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
496Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, 527Id 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
550Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 582Id 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);
544Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); 544Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
545Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 545Id 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);
547Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); 547Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
548void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); 548void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color);
549Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index); 549Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index);