diff options
| author | 2021-03-29 02:00:43 +0200 | |
|---|---|---|
| committer | 2021-07-22 21:51:25 -0400 | |
| commit | d5bfc630886d98ed77959a9771c67293244aff0e (patch) | |
| tree | 5816db6c236f9884c8900dd8a2c1e7ba9936b757 /src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |
| parent | shader: Implement TMML partially (diff) | |
| download | yuzu-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.cpp | 51 |
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 | ||
| 86 | private: | 118 | private: |
| 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 | ||
| 200 | Id EmitBindlessImageGradient(EmitContext&) { | ||
| 201 | throw LogicError("Unreachable instruction"); | ||
| 202 | } | ||
| 203 | |||
| 168 | Id EmitBoundImageSampleImplicitLod(EmitContext&) { | 204 | Id 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 | ||
| 240 | Id EmitBoundImageGradient(EmitContext&) { | ||
| 241 | throw LogicError("Unreachable instruction"); | ||
| 242 | } | ||
| 243 | |||
| 204 | Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 244 | Id 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 | ||
| 345 | Id 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 |