summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
diff options
context:
space:
mode:
authorGravatar FernandoS272021-03-29 02:00:43 +0200
committerGravatar ameerj2021-07-22 21:51:25 -0400
commitd5bfc630886d98ed77959a9771c67293244aff0e (patch)
tree5816db6c236f9884c8900dd8a2c1e7ba9936b757 /src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
parentshader: Implement TMML partially (diff)
downloadyuzu-d5bfc630886d98ed77959a9771c67293244aff0e.tar.gz
yuzu-d5bfc630886d98ed77959a9771c67293244aff0e.tar.xz
yuzu-d5bfc630886d98ed77959a9771c67293244aff0e.zip
shader: Implement ImageGradient
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv_image.cpp')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 9f8fe2603..1eba9cc00 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -69,12 +69,44 @@ public:
69 } 69 }
70 } 70 }
71 71
72 explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivates, u32 num_derivates,
73 Id offset, Id lod_clamp) {
74 if (Sirit::ValidId(derivates)) {
75 boost::container::static_vector<Id, 3> deriv_x_accum;
76 boost::container::static_vector<Id, 3> deriv_y_accum;
77 for (size_t i = 0; i < num_derivates; i++) {
78 deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2));
79 deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2 + 1));
80 }
81 Id derivates_X = ctx.OpCompositeConstruct(
82 ctx.F32[num_derivates], std::span{deriv_x_accum.data(), deriv_x_accum.size()});
83 Id derivates_Y = ctx.OpCompositeConstruct(
84 ctx.F32[num_derivates], std::span{deriv_y_accum.data(), deriv_y_accum.size()});
85 Add(spv::ImageOperandsMask::Grad, derivates_X, derivates_Y);
86 } else {
87 throw LogicError("Derivates must be present");
88 }
89 if (Sirit::ValidId(offset)) {
90 Add(spv::ImageOperandsMask::Offset, offset);
91 }
92 if (has_lod_clamp) {
93 Add(spv::ImageOperandsMask::MinLod, lod_clamp);
94 }
95 }
96
72 void Add(spv::ImageOperandsMask new_mask, Id value) { 97 void Add(spv::ImageOperandsMask new_mask, Id value) {
73 mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) | 98 mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) |
74 static_cast<unsigned>(new_mask)); 99 static_cast<unsigned>(new_mask));
75 operands.push_back(value); 100 operands.push_back(value);
76 } 101 }
77 102
103 void Add(spv::ImageOperandsMask new_mask, Id value, Id value_2) {
104 mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) |
105 static_cast<unsigned>(new_mask));
106 operands.push_back(value);
107 operands.push_back(value_2);
108 }
109
78 std::span<const Id> Span() const noexcept { 110 std::span<const Id> Span() const noexcept {
79 return std::span{operands.data(), operands.size()}; 111 return std::span{operands.data(), operands.size()};
80 } 112 }
@@ -84,7 +116,7 @@ public:
84 } 116 }
85 117
86private: 118private:
87 boost::container::static_vector<Id, 3> operands; 119 boost::container::static_vector<Id, 4> operands;
88 spv::ImageOperandsMask mask{}; 120 spv::ImageOperandsMask mask{};
89}; 121};
90 122
@@ -165,6 +197,10 @@ Id EmitBindlessImageQueryLod(EmitContext&) {
165 throw LogicError("Unreachable instruction"); 197 throw LogicError("Unreachable instruction");
166} 198}
167 199
200Id EmitBindlessImageGradient(EmitContext&) {
201 throw LogicError("Unreachable instruction");
202}
203
168Id EmitBoundImageSampleImplicitLod(EmitContext&) { 204Id EmitBoundImageSampleImplicitLod(EmitContext&) {
169 throw LogicError("Unreachable instruction"); 205 throw LogicError("Unreachable instruction");
170} 206}
@@ -201,6 +237,10 @@ Id EmitBoundImageQueryLod(EmitContext&) {
201 throw LogicError("Unreachable instruction"); 237 throw LogicError("Unreachable instruction");
202} 238}
203 239
240Id EmitBoundImageGradient(EmitContext&) {
241 throw LogicError("Unreachable instruction");
242}
243
204Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 244Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
205 Id bias_lc, Id offset) { 245 Id bias_lc, Id offset) {
206 const auto info{inst->Flags<IR::TextureInstInfo>()}; 246 const auto info{inst->Flags<IR::TextureInstInfo>()};
@@ -302,4 +342,13 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst*, const IR::Value& index, Id coo
302 zero, zero); 342 zero, zero);
303} 343}
304 344
345Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
346 Id derivates, Id offset, Id lod_clamp) {
347 const auto info{inst->Flags<IR::TextureInstInfo>()};
348 const ImageOperands operands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates, offset, lod_clamp);
349 return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
350 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index),
351 coords, operands.Mask(), operands.Span());
352}
353
305} // namespace Shader::Backend::SPIRV 354} // namespace Shader::Backend::SPIRV