summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-04-09 01:45:39 -0300
committerGravatar ameerj2021-07-22 21:51:26 -0400
commit7cb2ab358517d95ebcd35c94c72b9e91762906c3 (patch)
tree3f75959e255026665a4dde406cb8c4cc34fb45a0 /src/shader_recompiler/backend/spirv
parentshader: Fix Windows build issues (diff)
downloadyuzu-7cb2ab358517d95ebcd35c94c72b9e91762906c3.tar.gz
yuzu-7cb2ab358517d95ebcd35c94c72b9e91762906c3.tar.xz
yuzu-7cb2ab358517d95ebcd35c94c72b9e91762906c3.zip
shader: Implement SULD and SUST
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp97
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h9
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h6
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp46
5 files changed, 130 insertions, 29 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 0c114402b..32f8c4508 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -18,41 +18,70 @@ namespace {
18Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { 18Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
19 const spv::ImageFormat format{spv::ImageFormat::Unknown}; 19 const spv::ImageFormat format{spv::ImageFormat::Unknown};
20 const Id type{ctx.F32[1]}; 20 const Id type{ctx.F32[1]};
21 const bool depth{desc.is_depth};
21 switch (desc.type) { 22 switch (desc.type) {
22 case TextureType::Color1D: 23 case TextureType::Color1D:
23 return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 1, format); 24 return ctx.TypeImage(type, spv::Dim::Dim1D, depth, false, false, 1, format);
24 case TextureType::ColorArray1D: 25 case TextureType::ColorArray1D:
25 return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 1, format); 26 return ctx.TypeImage(type, spv::Dim::Dim1D, depth, true, false, 1, format);
26 case TextureType::Color2D: 27 case TextureType::Color2D:
27 return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 1, format); 28 return ctx.TypeImage(type, spv::Dim::Dim2D, depth, false, false, 1, format);
28 case TextureType::ColorArray2D: 29 case TextureType::ColorArray2D:
29 return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 1, format); 30 return ctx.TypeImage(type, spv::Dim::Dim2D, depth, true, false, 1, format);
30 case TextureType::Color3D: 31 case TextureType::Color3D:
31 return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 1, format); 32 return ctx.TypeImage(type, spv::Dim::Dim3D, depth, false, false, 1, format);
32 case TextureType::ColorCube: 33 case TextureType::ColorCube:
33 return ctx.TypeImage(type, spv::Dim::Cube, false, false, false, 1, format); 34 return ctx.TypeImage(type, spv::Dim::Cube, depth, false, false, 1, format);
34 case TextureType::ColorArrayCube: 35 case TextureType::ColorArrayCube:
35 return ctx.TypeImage(type, spv::Dim::Cube, false, true, false, 1, format); 36 return ctx.TypeImage(type, spv::Dim::Cube, depth, true, false, 1, format);
36 case TextureType::Shadow1D:
37 return ctx.TypeImage(type, spv::Dim::Dim1D, true, false, false, 1, format);
38 case TextureType::ShadowArray1D:
39 return ctx.TypeImage(type, spv::Dim::Dim1D, true, true, false, 1, format);
40 case TextureType::Shadow2D:
41 return ctx.TypeImage(type, spv::Dim::Dim2D, true, false, false, 1, format);
42 case TextureType::ShadowArray2D:
43 return ctx.TypeImage(type, spv::Dim::Dim2D, true, true, false, 1, format);
44 case TextureType::Shadow3D:
45 return ctx.TypeImage(type, spv::Dim::Dim3D, true, false, false, 1, format);
46 case TextureType::ShadowCube:
47 return ctx.TypeImage(type, spv::Dim::Cube, true, false, false, 1, format);
48 case TextureType::ShadowArrayCube:
49 return ctx.TypeImage(type, spv::Dim::Cube, true, true, false, 1, format);
50 case TextureType::Buffer: 37 case TextureType::Buffer:
51 break; 38 break;
52 } 39 }
53 throw InvalidArgument("Invalid texture type {}", desc.type); 40 throw InvalidArgument("Invalid texture type {}", desc.type);
54} 41}
55 42
43Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) {
44 const spv::ImageFormat format{[&] {
45 switch (desc.format) {
46 case ImageFormat::Typeless:
47 return spv::ImageFormat::Unknown;
48 case ImageFormat::R8_UINT:
49 return spv::ImageFormat::R8ui;
50 case ImageFormat::R8_SINT:
51 return spv::ImageFormat::R8i;
52 case ImageFormat::R16_UINT:
53 return spv::ImageFormat::R16ui;
54 case ImageFormat::R16_SINT:
55 return spv::ImageFormat::R16i;
56 case ImageFormat::R32_UINT:
57 return spv::ImageFormat::R32ui;
58 case ImageFormat::R32G32_UINT:
59 return spv::ImageFormat::Rg32ui;
60 case ImageFormat::R32G32B32A32_UINT:
61 return spv::ImageFormat::Rgba32ui;
62 }
63 throw InvalidArgument("Invalid image format {}", desc.format);
64 }()};
65 const Id type{ctx.U32[1]};
66 switch (desc.type) {
67 case TextureType::Color1D:
68 return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 2, format);
69 case TextureType::ColorArray1D:
70 return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 2, format);
71 case TextureType::Color2D:
72 return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 2, format);
73 case TextureType::ColorArray2D:
74 return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 2, format);
75 case TextureType::Color3D:
76 return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 2, format);
77 case TextureType::Buffer:
78 throw NotImplementedException("Image buffer");
79 default:
80 break;
81 }
82 throw InvalidArgument("Invalid texture type {}", desc.type);
83}
84
56Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, 85Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin,
57 spv::StorageClass storage_class) { 86 spv::StorageClass storage_class) {
58 const Id pointer_type{ctx.TypePointer(storage_class, type)}; 87 const Id pointer_type{ctx.TypePointer(storage_class, type)};
@@ -134,6 +163,7 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin
134 DefineStorageBuffers(program.info, binding); 163 DefineStorageBuffers(program.info, binding);
135 DefineTextureBuffers(program.info, binding); 164 DefineTextureBuffers(program.info, binding);
136 DefineTextures(program.info, binding); 165 DefineTextures(program.info, binding);
166 DefineImages(program.info, binding);
137 DefineAttributeMemAccess(program.info); 167 DefineAttributeMemAccess(program.info);
138 DefineLabels(program); 168 DefineLabels(program);
139} 169}
@@ -572,6 +602,31 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) {
572 } 602 }
573} 603}
574 604
605void EmitContext::DefineImages(const Info& info, u32& binding) {
606 images.reserve(info.image_descriptors.size());
607 for (const ImageDescriptor& desc : info.image_descriptors) {
608 if (desc.count != 1) {
609 throw NotImplementedException("Array of textures");
610 }
611 const Id image_type{ImageType(*this, desc)};
612 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
613 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
614 Decorate(id, spv::Decoration::Binding, binding);
615 Decorate(id, spv::Decoration::DescriptorSet, 0U);
616 Name(id, fmt::format("img{}_{:02x}", desc.cbuf_index, desc.cbuf_offset));
617 for (u32 index = 0; index < desc.count; ++index) {
618 images.push_back(ImageDefinition{
619 .id{id},
620 .image_type{image_type},
621 });
622 }
623 if (profile.supported_spirv >= 0x00010400) {
624 interfaces.push_back(id);
625 }
626 binding += desc.count;
627 }
628}
629
575void EmitContext::DefineLabels(IR::Program& program) { 630void EmitContext::DefineLabels(IR::Program& program) {
576 for (IR::Block* const block : program.blocks) { 631 for (IR::Block* const block : program.blocks) {
577 block->SetDefinition(OpLabel()); 632 block->SetDefinition(OpLabel());
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index f1ac4430c..e70f3458c 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -35,6 +35,11 @@ struct TextureDefinition {
35 Id image_type; 35 Id image_type;
36}; 36};
37 37
38struct ImageDefinition {
39 Id id;
40 Id image_type;
41};
42
38struct UniformDefinitions { 43struct UniformDefinitions {
39 Id U8{}; 44 Id U8{};
40 Id S8{}; 45 Id S8{};
@@ -95,8 +100,9 @@ public:
95 100
96 std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; 101 std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{};
97 std::array<Id, Info::MAX_SSBOS> ssbos{}; 102 std::array<Id, Info::MAX_SSBOS> ssbos{};
98 std::vector<TextureDefinition> textures;
99 std::vector<Id> texture_buffers; 103 std::vector<Id> texture_buffers;
104 std::vector<TextureDefinition> textures;
105 std::vector<ImageDefinition> images;
100 106
101 Id workgroup_id{}; 107 Id workgroup_id{};
102 Id local_invocation_id{}; 108 Id local_invocation_id{};
@@ -156,6 +162,7 @@ private:
156 void DefineStorageBuffers(const Info& info, u32& binding); 162 void DefineStorageBuffers(const Info& info, u32& binding);
157 void DefineTextureBuffers(const Info& info, u32& binding); 163 void DefineTextureBuffers(const Info& info, u32& binding);
158 void DefineTextures(const Info& info, u32& binding); 164 void DefineTextures(const Info& info, u32& binding);
165 void DefineImages(const Info& info, u32& binding);
159 void DefineAttributeMemAccess(const Info& info); 166 void DefineAttributeMemAccess(const Info& info);
160 void DefineLabels(IR::Program& program); 167 void DefineLabels(IR::Program& program);
161 168
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index 355cf0ca8..ecd0fac5c 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -253,6 +253,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
253 ctx.AddCapability(spv::Capability::ImageGatherExtended); 253 ctx.AddCapability(spv::Capability::ImageGatherExtended);
254 ctx.AddCapability(spv::Capability::ImageQuery); 254 ctx.AddCapability(spv::Capability::ImageQuery);
255 ctx.AddCapability(spv::Capability::SampledBuffer); 255 ctx.AddCapability(spv::Capability::SampledBuffer);
256 ctx.AddCapability(spv::Capability::StorageImageReadWithoutFormat);
256} 257}
257 258
258Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { 259Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index 08460c94e..a39b16f1e 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -369,6 +369,8 @@ Id EmitBindlessImageFetch(EmitContext&);
369Id EmitBindlessImageQueryDimensions(EmitContext&); 369Id EmitBindlessImageQueryDimensions(EmitContext&);
370Id EmitBindlessImageQueryLod(EmitContext&); 370Id EmitBindlessImageQueryLod(EmitContext&);
371Id EmitBindlessImageGradient(EmitContext&); 371Id EmitBindlessImageGradient(EmitContext&);
372Id EmitBindlessImageRead(EmitContext&);
373Id EmitBindlessImageWrite(EmitContext&);
372Id EmitBoundImageSampleImplicitLod(EmitContext&); 374Id EmitBoundImageSampleImplicitLod(EmitContext&);
373Id EmitBoundImageSampleExplicitLod(EmitContext&); 375Id EmitBoundImageSampleExplicitLod(EmitContext&);
374Id EmitBoundImageSampleDrefImplicitLod(EmitContext&); 376Id EmitBoundImageSampleDrefImplicitLod(EmitContext&);
@@ -379,6 +381,8 @@ Id EmitBoundImageFetch(EmitContext&);
379Id EmitBoundImageQueryDimensions(EmitContext&); 381Id EmitBoundImageQueryDimensions(EmitContext&);
380Id EmitBoundImageQueryLod(EmitContext&); 382Id EmitBoundImageQueryLod(EmitContext&);
381Id EmitBoundImageGradient(EmitContext&); 383Id EmitBoundImageGradient(EmitContext&);
384Id EmitBoundImageRead(EmitContext&);
385Id EmitBoundImageWrite(EmitContext&);
382Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 386Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
383 Id bias_lc, Id offset); 387 Id bias_lc, Id offset);
384Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 388Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
@@ -397,6 +401,8 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
397Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); 401Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
398Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 402Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
399 Id derivates, Id offset, Id lod_clamp); 403 Id derivates, Id offset, Id lod_clamp);
404Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
405void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color);
400Id EmitVoteAll(EmitContext& ctx, Id pred); 406Id EmitVoteAll(EmitContext& ctx, Id pred);
401Id EmitVoteAny(EmitContext& ctx, Id pred); 407Id EmitVoteAny(EmitContext& ctx, Id pred);
402Id EmitVoteEqual(EmitContext& ctx, Id pred); 408Id EmitVoteEqual(EmitContext& ctx, Id pred);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 6a89c0f79..dd261fd47 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -144,6 +144,18 @@ Id TextureImage(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo in
144 } 144 }
145} 145}
146 146
147Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
148 if (!index.IsImmediate()) {
149 throw NotImplementedException("Indirect image indexing");
150 }
151 if (info.type == TextureType::Buffer) {
152 throw NotImplementedException("Image buffer");
153 } else {
154 const ImageDefinition def{ctx.images.at(index.U32())};
155 return ctx.OpLoad(def.image_type, def.id);
156 }
157}
158
147Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { 159Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) {
148 const auto info{inst->Flags<IR::TextureInstInfo>()}; 160 const auto info{inst->Flags<IR::TextureInstInfo>()};
149 if (info.relaxed_precision != 0) { 161 if (info.relaxed_precision != 0) {
@@ -209,6 +221,14 @@ Id EmitBindlessImageGradient(EmitContext&) {
209 throw LogicError("Unreachable instruction"); 221 throw LogicError("Unreachable instruction");
210} 222}
211 223
224Id EmitBindlessImageRead(EmitContext&) {
225 throw LogicError("Unreachable instruction");
226}
227
228Id EmitBindlessImageWrite(EmitContext&) {
229 throw LogicError("Unreachable instruction");
230}
231
212Id EmitBoundImageSampleImplicitLod(EmitContext&) { 232Id EmitBoundImageSampleImplicitLod(EmitContext&) {
213 throw LogicError("Unreachable instruction"); 233 throw LogicError("Unreachable instruction");
214} 234}
@@ -249,6 +269,14 @@ Id EmitBoundImageGradient(EmitContext&) {
249 throw LogicError("Unreachable instruction"); 269 throw LogicError("Unreachable instruction");
250} 270}
251 271
272Id EmitBoundImageRead(EmitContext&) {
273 throw LogicError("Unreachable instruction");
274}
275
276Id EmitBoundImageWrite(EmitContext&) {
277 throw LogicError("Unreachable instruction");
278}
279
252Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 280Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
253 Id bias_lc, Id offset) { 281 Id bias_lc, Id offset) {
254 const auto info{inst->Flags<IR::TextureInstInfo>()}; 282 const auto info{inst->Flags<IR::TextureInstInfo>()};
@@ -322,23 +350,16 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
322 const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; 350 const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }};
323 switch (info.type) { 351 switch (info.type) {
324 case TextureType::Color1D: 352 case TextureType::Color1D:
325 case TextureType::Shadow1D:
326 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), 353 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod),
327 zero, zero, mips()); 354 zero, zero, mips());
328 case TextureType::ColorArray1D: 355 case TextureType::ColorArray1D:
329 case TextureType::Color2D: 356 case TextureType::Color2D:
330 case TextureType::ColorCube: 357 case TextureType::ColorCube:
331 case TextureType::ShadowArray1D:
332 case TextureType::Shadow2D:
333 case TextureType::ShadowCube:
334 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod), 358 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod),
335 zero, mips()); 359 zero, mips());
336 case TextureType::ColorArray2D: 360 case TextureType::ColorArray2D:
337 case TextureType::Color3D: 361 case TextureType::Color3D:
338 case TextureType::ColorArrayCube: 362 case TextureType::ColorArrayCube:
339 case TextureType::ShadowArray2D:
340 case TextureType::Shadow3D:
341 case TextureType::ShadowArrayCube:
342 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), 363 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod),
343 mips()); 364 mips());
344 case TextureType::Buffer: 365 case TextureType::Buffer:
@@ -365,4 +386,15 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I
365 coords, operands.Mask(), operands.Span()); 386 coords, operands.Mask(), operands.Span());
366} 387}
367 388
389Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) {
390 const auto info{inst->Flags<IR::TextureInstInfo>()};
391 return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4],
392 Image(ctx, index, info), coords, std::nullopt, std::span<const Id>{});
393}
394
395void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) {
396 const auto info{inst->Flags<IR::TextureInstInfo>()};
397 ctx.OpImageWrite(Image(ctx, index, info), coords, color);
398}
399
368} // namespace Shader::Backend::SPIRV 400} // namespace Shader::Backend::SPIRV