summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2021-03-08 22:31:53 +0100
committerameerj <52414509+ameerj@users.noreply.github.com>2021-07-23 03:51:23 +0200
commitab463712474de5f99eec137a9c6233e55fe184f0 (patch)
tree30d79ac64dd03d5cfafd07c0c42c2baadc82de98 /src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
parentshader: Implement R2P (diff)
downloadyuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.gz
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.bz2
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.lz
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.xz
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.zst
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.zip
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
new file mode 100644
index 000000000..5f4783c95
--- /dev/null
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -0,0 +1,146 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <boost/container/static_vector.hpp>
+
+#include "shader_recompiler/backend/spirv/emit_spirv.h"
+#include "shader_recompiler/frontend/ir/modifiers.h"
+
+namespace Shader::Backend::SPIRV {
+namespace {
+class ImageOperands {
+public:
+ explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp,
+ Id lod, Id offset) {
+ if (has_bias) {
+ const Id bias{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod};
+ Add(spv::ImageOperandsMask::Bias, bias);
+ }
+ if (has_lod) {
+ const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod};
+ Add(spv::ImageOperandsMask::Lod, lod_value);
+ }
+ if (Sirit::ValidId(offset)) {
+ Add(spv::ImageOperandsMask::Offset, offset);
+ }
+ if (has_lod_clamp) {
+ const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod};
+ Add(spv::ImageOperandsMask::MinLod, lod_clamp);
+ }
+ }
+
+ void Add(spv::ImageOperandsMask new_mask, Id value) {
+ mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) |
+ static_cast<unsigned>(new_mask));
+ operands.push_back(value);
+ }
+
+ std::span<const Id> Span() const noexcept {
+ return std::span{operands.data(), operands.size()};
+ }
+
+ spv::ImageOperandsMask Mask() const noexcept {
+ return mask;
+ }
+
+private:
+ boost::container::static_vector<Id, 3> operands;
+ spv::ImageOperandsMask mask{};
+};
+
+Id Texture(EmitContext& ctx, const IR::Value& index) {
+ if (index.IsImmediate()) {
+ const TextureDefinition def{ctx.textures.at(index.U32())};
+ return ctx.OpLoad(def.type, def.id);
+ }
+ throw NotImplementedException("Indirect texture sample");
+}
+
+template <typename MethodPtrType, typename... Args>
+Id Emit(MethodPtrType sparse_ptr, MethodPtrType non_sparse_ptr, EmitContext& ctx, IR::Inst* inst,
+ Id result_type, Args&&... args) {
+ IR::Inst* const sparse{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)};
+ if (!sparse) {
+ return (ctx.*non_sparse_ptr)(result_type, std::forward<Args>(args)...);
+ }
+ const Id struct_type{ctx.TypeStruct(ctx.U32[1], result_type)};
+ const Id sample{(ctx.*sparse_ptr)(struct_type, std::forward<Args>(args)...)};
+ const Id resident_code{ctx.OpCompositeExtract(ctx.U32[1], sample, 0U)};
+ sparse->SetDefinition(ctx.OpImageSparseTexelsResident(ctx.U1, resident_code));
+ sparse->Invalidate();
+ return ctx.OpCompositeExtract(result_type, sample, 1U);
+}
+} // Anonymous namespace
+
+Id EmitBindlessImageSampleImplicitLod(EmitContext&) {
+ throw LogicError("Unreachable instruction");
+}
+
+Id EmitBindlessImageSampleExplicitLod(EmitContext&) {
+ throw LogicError("Unreachable instruction");
+}
+
+Id EmitBindlessImageSampleDrefImplicitLod(EmitContext&) {
+ throw LogicError("Unreachable instruction");
+}
+
+Id EmitBindlessImageSampleDrefExplicitLod(EmitContext&) {
+ throw LogicError("Unreachable instruction");
+}
+
+Id EmitBoundImageSampleImplicitLod(EmitContext&) {
+ throw LogicError("Unreachable instruction");
+}
+
+Id EmitBoundImageSampleExplicitLod(EmitContext&) {
+ throw LogicError("Unreachable instruction");
+}
+
+Id EmitBoundImageSampleDrefImplicitLod(EmitContext&) {
+ throw LogicError("Unreachable instruction");
+}
+
+Id EmitBoundImageSampleDrefExplicitLod(EmitContext&) {
+ throw LogicError("Unreachable instruction");
+}
+
+Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
+ Id bias_lc, Id offset) {
+ const auto info{inst->Flags<IR::TextureInstInfo>()};
+ const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc,
+ offset);
+ return Emit(&EmitContext::OpImageSparseSampleImplicitLod,
+ &EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index),
+ coords, operands.Mask(), operands.Span());
+}
+
+Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
+ Id lod_lc, Id offset) {
+ const auto info{inst->Flags<IR::TextureInstInfo>()};
+ const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset);
+ return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
+ &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index),
+ coords, operands.Mask(), operands.Span());
+}
+
+Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
+ Id coords, Id dref, Id bias_lc, Id offset) {
+ const auto info{inst->Flags<IR::TextureInstInfo>()};
+ const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc,
+ offset);
+ return Emit(&EmitContext::OpImageSparseSampleDrefImplicitLod,
+ &EmitContext::OpImageSampleDrefImplicitLod, ctx, inst, ctx.F32[1],
+ Texture(ctx, index), coords, dref, operands.Mask(), operands.Span());
+}
+
+Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
+ Id coords, Id dref, Id lod_lc, Id offset) {
+ const auto info{inst->Flags<IR::TextureInstInfo>()};
+ const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset);
+ return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod,
+ &EmitContext::OpImageSampleDrefExplicitLod, ctx, inst, ctx.F32[1],
+ Texture(ctx, index), coords, dref, operands.Mask(), operands.Span());
+}
+
+} // namespace Shader::Backend::SPIRV