summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-03-08 18:31:53 -0300
committerGravatar ameerj2021-07-22 21:51:23 -0400
commitab463712474de5f99eec137a9c6233e55fe184f0 (patch)
tree30d79ac64dd03d5cfafd07c0c42c2baadc82de98 /src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
parentshader: Implement R2P (diff)
downloadyuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.gz
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.xz
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.zip
shader: Initial support for textures and TEX
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv_image.cpp')
-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 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <boost/container/static_vector.hpp>
6
7#include "shader_recompiler/backend/spirv/emit_spirv.h"
8#include "shader_recompiler/frontend/ir/modifiers.h"
9
10namespace Shader::Backend::SPIRV {
11namespace {
12class ImageOperands {
13public:
14 explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp,
15 Id lod, Id offset) {
16 if (has_bias) {
17 const Id bias{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod};
18 Add(spv::ImageOperandsMask::Bias, bias);
19 }
20 if (has_lod) {
21 const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod};
22 Add(spv::ImageOperandsMask::Lod, lod_value);
23 }
24 if (Sirit::ValidId(offset)) {
25 Add(spv::ImageOperandsMask::Offset, offset);
26 }
27 if (has_lod_clamp) {
28 const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod};
29 Add(spv::ImageOperandsMask::MinLod, lod_clamp);
30 }
31 }
32
33 void Add(spv::ImageOperandsMask new_mask, Id value) {
34 mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) |
35 static_cast<unsigned>(new_mask));
36 operands.push_back(value);
37 }
38
39 std::span<const Id> Span() const noexcept {
40 return std::span{operands.data(), operands.size()};
41 }
42
43 spv::ImageOperandsMask Mask() const noexcept {
44 return mask;
45 }
46
47private:
48 boost::container::static_vector<Id, 3> operands;
49 spv::ImageOperandsMask mask{};
50};
51
52Id Texture(EmitContext& ctx, const IR::Value& index) {
53 if (index.IsImmediate()) {
54 const TextureDefinition def{ctx.textures.at(index.U32())};
55 return ctx.OpLoad(def.type, def.id);
56 }
57 throw NotImplementedException("Indirect texture sample");
58}
59
60template <typename MethodPtrType, typename... Args>
61Id Emit(MethodPtrType sparse_ptr, MethodPtrType non_sparse_ptr, EmitContext& ctx, IR::Inst* inst,
62 Id result_type, Args&&... args) {
63 IR::Inst* const sparse{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)};
64 if (!sparse) {
65 return (ctx.*non_sparse_ptr)(result_type, std::forward<Args>(args)...);
66 }
67 const Id struct_type{ctx.TypeStruct(ctx.U32[1], result_type)};
68 const Id sample{(ctx.*sparse_ptr)(struct_type, std::forward<Args>(args)...)};
69 const Id resident_code{ctx.OpCompositeExtract(ctx.U32[1], sample, 0U)};
70 sparse->SetDefinition(ctx.OpImageSparseTexelsResident(ctx.U1, resident_code));
71 sparse->Invalidate();
72 return ctx.OpCompositeExtract(result_type, sample, 1U);
73}
74} // Anonymous namespace
75
76Id EmitBindlessImageSampleImplicitLod(EmitContext&) {
77 throw LogicError("Unreachable instruction");
78}
79
80Id EmitBindlessImageSampleExplicitLod(EmitContext&) {
81 throw LogicError("Unreachable instruction");
82}
83
84Id EmitBindlessImageSampleDrefImplicitLod(EmitContext&) {
85 throw LogicError("Unreachable instruction");
86}
87
88Id EmitBindlessImageSampleDrefExplicitLod(EmitContext&) {
89 throw LogicError("Unreachable instruction");
90}
91
92Id EmitBoundImageSampleImplicitLod(EmitContext&) {
93 throw LogicError("Unreachable instruction");
94}
95
96Id EmitBoundImageSampleExplicitLod(EmitContext&) {
97 throw LogicError("Unreachable instruction");
98}
99
100Id EmitBoundImageSampleDrefImplicitLod(EmitContext&) {
101 throw LogicError("Unreachable instruction");
102}
103
104Id EmitBoundImageSampleDrefExplicitLod(EmitContext&) {
105 throw LogicError("Unreachable instruction");
106}
107
108Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
109 Id bias_lc, Id offset) {
110 const auto info{inst->Flags<IR::TextureInstInfo>()};
111 const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc,
112 offset);
113 return Emit(&EmitContext::OpImageSparseSampleImplicitLod,
114 &EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index),
115 coords, operands.Mask(), operands.Span());
116}
117
118Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
119 Id lod_lc, Id offset) {
120 const auto info{inst->Flags<IR::TextureInstInfo>()};
121 const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset);
122 return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
123 &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index),
124 coords, operands.Mask(), operands.Span());
125}
126
127Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
128 Id coords, Id dref, Id bias_lc, Id offset) {
129 const auto info{inst->Flags<IR::TextureInstInfo>()};
130 const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc,
131 offset);
132 return Emit(&EmitContext::OpImageSparseSampleDrefImplicitLod,
133 &EmitContext::OpImageSampleDrefImplicitLod, ctx, inst, ctx.F32[1],
134 Texture(ctx, index), coords, dref, operands.Mask(), operands.Span());
135}
136
137Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
138 Id coords, Id dref, Id lod_lc, Id offset) {
139 const auto info{inst->Flags<IR::TextureInstInfo>()};
140 const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod_lc, offset);
141 return Emit(&EmitContext::OpImageSparseSampleDrefExplicitLod,
142 &EmitContext::OpImageSampleDrefExplicitLod, ctx, inst, ctx.F32[1],
143 Texture(ctx, index), coords, dref, operands.Mask(), operands.Span());
144}
145
146} // namespace Shader::Backend::SPIRV