summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/engines/shader_bytecode.h66
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp70
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp7
-rw-r--r--src/video_core/shader/decode.cpp1
-rw-r--r--src/video_core/shader/decode/image.cpp89
-rw-r--r--src/video_core/shader/node.h42
-rw-r--r--src/video_core/shader/shader_ir.h9
9 files changed, 283 insertions, 3 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 198b3fe07..8ae05137b 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -44,6 +44,7 @@ add_custom_command(OUTPUT scm_rev.cpp
44 "${VIDEO_CORE}/shader/decode/half_set.cpp" 44 "${VIDEO_CORE}/shader/decode/half_set.cpp"
45 "${VIDEO_CORE}/shader/decode/half_set_predicate.cpp" 45 "${VIDEO_CORE}/shader/decode/half_set_predicate.cpp"
46 "${VIDEO_CORE}/shader/decode/hfma2.cpp" 46 "${VIDEO_CORE}/shader/decode/hfma2.cpp"
47 "${VIDEO_CORE}/shader/decode/image.cpp"
47 "${VIDEO_CORE}/shader/decode/integer_set.cpp" 48 "${VIDEO_CORE}/shader/decode/integer_set.cpp"
48 "${VIDEO_CORE}/shader/decode/integer_set_predicate.cpp" 49 "${VIDEO_CORE}/shader/decode/integer_set_predicate.cpp"
49 "${VIDEO_CORE}/shader/decode/memory.cpp" 50 "${VIDEO_CORE}/shader/decode/memory.cpp"
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 9d43f03d2..6839abe71 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -90,6 +90,7 @@ add_library(video_core STATIC
90 shader/decode/conversion.cpp 90 shader/decode/conversion.cpp
91 shader/decode/memory.cpp 91 shader/decode/memory.cpp
92 shader/decode/texture.cpp 92 shader/decode/texture.cpp
93 shader/decode/image.cpp
93 shader/decode/float_set_predicate.cpp 94 shader/decode/float_set_predicate.cpp
94 shader/decode/integer_set_predicate.cpp 95 shader/decode/integer_set_predicate.cpp
95 shader/decode/half_set_predicate.cpp 96 shader/decode/half_set_predicate.cpp
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 5b32e1249..54a1a04f9 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -126,6 +126,15 @@ union Sampler {
126 u64 value{}; 126 u64 value{};
127}; 127};
128 128
129union Image {
130 Image() = default;
131
132 constexpr explicit Image(u64 value) : value{value} {}
133
134 BitField<36, 13, u64> index;
135 u64 value;
136};
137
129} // namespace Tegra::Shader 138} // namespace Tegra::Shader
130 139
131namespace std { 140namespace std {
@@ -344,6 +353,26 @@ enum class TextureMiscMode : u64 {
344 PTP, 353 PTP,
345}; 354};
346 355
356enum class SurfaceDataMode : u64 {
357 P = 0,
358 D_BA = 1,
359};
360
361enum class OutOfBoundsStore : u64 {
362 Ignore = 0,
363 Clamp = 1,
364 Trap = 2,
365};
366
367enum class ImageType : u64 {
368 Texture1D = 0,
369 TextureBuffer = 1,
370 Texture1DArray = 2,
371 Texture2D = 3,
372 Texture2DArray = 4,
373 Texture3D = 5,
374};
375
347enum class IsberdMode : u64 { 376enum class IsberdMode : u64 {
348 None = 0, 377 None = 0,
349 Patch = 1, 378 Patch = 1,
@@ -398,7 +427,7 @@ enum class LmemLoadCacheManagement : u64 {
398 CV = 3, 427 CV = 3,
399}; 428};
400 429
401enum class LmemStoreCacheManagement : u64 { 430enum class StoreCacheManagement : u64 {
402 Default = 0, 431 Default = 0,
403 CG = 1, 432 CG = 1,
404 CS = 2, 433 CS = 2,
@@ -811,7 +840,7 @@ union Instruction {
811 } ld_l; 840 } ld_l;
812 841
813 union { 842 union {
814 BitField<44, 2, LmemStoreCacheManagement> cache_management; 843 BitField<44, 2, StoreCacheManagement> cache_management;
815 } st_l; 844 } st_l;
816 845
817 union { 846 union {
@@ -1295,6 +1324,35 @@ union Instruction {
1295 } tlds; 1324 } tlds;
1296 1325
1297 union { 1326 union {
1327 BitField<24, 2, StoreCacheManagement> cache_management;
1328 BitField<33, 3, ImageType> image_type;
1329 BitField<49, 2, OutOfBoundsStore> out_of_bounds_store;
1330 BitField<51, 1, u64> is_immediate;
1331 BitField<52, 1, SurfaceDataMode> mode;
1332
1333 BitField<20, 3, StoreType> store_data_layout;
1334 BitField<20, 4, u64> component_mask_selector;
1335
1336 bool IsComponentEnabled(std::size_t component) const {
1337 ASSERT(mode == SurfaceDataMode::P);
1338 constexpr u8 R = 0b0001;
1339 constexpr u8 G = 0b0010;
1340 constexpr u8 B = 0b0100;
1341 constexpr u8 A = 0b1000;
1342 constexpr std::array<u8, 16> mask = {
1343 0, (R), (G), (R | G), (B), (R | B),
1344 (G | B), (R | G | B), (A), (R | A), (G | A), (R | G | A),
1345 (B | A), (R | B | A), (G | B | A), (R | G | B | A)};
1346 return std::bitset<4>{mask.at(component_mask_selector)}.test(component);
1347 }
1348
1349 StoreType GetStoreDataLayout() const {
1350 ASSERT(mode == SurfaceDataMode::D_BA);
1351 return store_data_layout;
1352 }
1353 } sust;
1354
1355 union {
1298 BitField<20, 24, u64> target; 1356 BitField<20, 24, u64> target;
1299 BitField<5, 1, u64> constant_buffer; 1357 BitField<5, 1, u64> constant_buffer;
1300 1358
@@ -1385,6 +1443,7 @@ union Instruction {
1385 1443
1386 Attribute attribute; 1444 Attribute attribute;
1387 Sampler sampler; 1445 Sampler sampler;
1446 Image image;
1388 1447
1389 u64 value; 1448 u64 value;
1390}; 1449};
@@ -1428,6 +1487,7 @@ public:
1428 TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations 1487 TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations
1429 TMML_B, // Texture Mip Map Level 1488 TMML_B, // Texture Mip Map Level
1430 TMML, // Texture Mip Map Level 1489 TMML, // Texture Mip Map Level
1490 SUST, // Surface Store
1431 EXIT, 1491 EXIT,
1432 IPA, 1492 IPA,
1433 OUT_R, // Emit vertex/primitive 1493 OUT_R, // Emit vertex/primitive
@@ -1558,6 +1618,7 @@ public:
1558 Synch, 1618 Synch,
1559 Memory, 1619 Memory,
1560 Texture, 1620 Texture,
1621 Image,
1561 FloatSet, 1622 FloatSet,
1562 FloatSetPredicate, 1623 FloatSetPredicate,
1563 IntegerSet, 1624 IntegerSet,
@@ -1703,6 +1764,7 @@ private:
1703 INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"), 1764 INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"),
1704 INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"), 1765 INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"),
1705 INST("1101111101011---", Id::TMML, Type::Texture, "TMML"), 1766 INST("1101111101011---", Id::TMML, Type::Texture, "TMML"),
1767 INST("11101011001-----", Id::SUST, Type::Image, "SUST"),
1706 INST("11100000--------", Id::IPA, Type::Trivial, "IPA"), 1768 INST("11100000--------", Id::IPA, Type::Trivial, "IPA"),
1707 INST("1111101111100---", Id::OUT_R, Type::Trivial, "OUT_R"), 1769 INST("1111101111100---", Id::OUT_R, Type::Trivial, "OUT_R"),
1708 INST("1110111111010---", Id::ISBERD, Type::Trivial, "ISBERD"), 1770 INST("1110111111010---", Id::ISBERD, Type::Trivial, "ISBERD"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index ece386cdc..2ae2f1db2 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -180,6 +180,7 @@ public:
180 DeclareGlobalMemory(); 180 DeclareGlobalMemory();
181 DeclareSamplers(); 181 DeclareSamplers();
182 DeclarePhysicalAttributeReader(); 182 DeclarePhysicalAttributeReader();
183 DeclareImages();
183 184
184 code.AddLine("void execute_{}() {{", suffix); 185 code.AddLine("void execute_{}() {{", suffix);
185 ++code.scope; 186 ++code.scope;
@@ -531,6 +532,36 @@ private:
531 code.AddNewLine(); 532 code.AddNewLine();
532 } 533 }
533 534
535 void DeclareImages() {
536 const auto& images{ir.GetImages()};
537 for (const auto& image : images) {
538 const std::string image_type = [&]() {
539 switch (image.GetType()) {
540 case Tegra::Shader::ImageType::Texture1D:
541 return "image1D";
542 case Tegra::Shader::ImageType::TextureBuffer:
543 return "bufferImage";
544 case Tegra::Shader::ImageType::Texture1DArray:
545 return "image1DArray";
546 case Tegra::Shader::ImageType::Texture2D:
547 return "image2D";
548 case Tegra::Shader::ImageType::Texture2DArray:
549 return "image2DArray";
550 case Tegra::Shader::ImageType::Texture3D:
551 return "image3D";
552 default:
553 UNREACHABLE();
554 return "image1D";
555 }
556 }();
557 code.AddLine("layout (binding = IMAGE_BINDING_" + std::to_string(image.GetIndex()) +
558 ") coherent volatile writeonly uniform " + image_type + ' ' +
559 GetImage(image) + ';');
560 }
561 if (!images.empty())
562 code.AddNewLine();
563 }
564
534 void VisitBlock(const NodeBlock& bb) { 565 void VisitBlock(const NodeBlock& bb) {
535 for (const auto& node : bb) { 566 for (const auto& node : bb) {
536 if (const std::string expr = Visit(node); !expr.empty()) { 567 if (const std::string expr = Visit(node); !expr.empty()) {
@@ -1478,6 +1509,39 @@ private:
1478 return tmp; 1509 return tmp;
1479 } 1510 }
1480 1511
1512 std::string ImageStore(Operation operation) {
1513 constexpr std::array<const char*, 4> constructors{"int(", "ivec2(", "ivec3(", "ivec4("};
1514 const auto meta{std::get<MetaImage>(operation.GetMeta())};
1515
1516 std::string expr = "imageStore(";
1517 expr += GetImage(meta.image);
1518 expr += ", ";
1519
1520 const std::size_t coords_count{operation.GetOperandsCount()};
1521 expr += constructors.at(coords_count - 1);
1522 for (std::size_t i = 0; i < coords_count; ++i) {
1523 expr += VisitOperand(operation, i, Type::Int);
1524 if (i + 1 < coords_count) {
1525 expr += ", ";
1526 }
1527 }
1528 expr += "), ";
1529
1530 const std::size_t values_count{meta.values.size()};
1531 UNIMPLEMENTED_IF(values_count != 4);
1532 expr += "vec4(";
1533 for (std::size_t i = 0; i < values_count; ++i) {
1534 expr += Visit(meta.values.at(i));
1535 if (i + 1 < values_count) {
1536 expr += ", ";
1537 }
1538 }
1539 expr += "));";
1540
1541 code.AddLine(expr);
1542 return {};
1543 }
1544
1481 std::string Branch(Operation operation) { 1545 std::string Branch(Operation operation) {
1482 const auto target = std::get_if<ImmediateNode>(&*operation[0]); 1546 const auto target = std::get_if<ImmediateNode>(&*operation[0]);
1483 UNIMPLEMENTED_IF(!target); 1547 UNIMPLEMENTED_IF(!target);
@@ -1718,6 +1782,8 @@ private:
1718 &GLSLDecompiler::TextureQueryLod, 1782 &GLSLDecompiler::TextureQueryLod,
1719 &GLSLDecompiler::TexelFetch, 1783 &GLSLDecompiler::TexelFetch,
1720 1784
1785 &GLSLDecompiler::ImageStore,
1786
1721 &GLSLDecompiler::Branch, 1787 &GLSLDecompiler::Branch,
1722 &GLSLDecompiler::PushFlowStack, 1788 &GLSLDecompiler::PushFlowStack,
1723 &GLSLDecompiler::PopFlowStack, 1789 &GLSLDecompiler::PopFlowStack,
@@ -1786,6 +1852,10 @@ private:
1786 return GetDeclarationWithSuffix(static_cast<u32>(sampler.GetIndex()), "sampler"); 1852 return GetDeclarationWithSuffix(static_cast<u32>(sampler.GetIndex()), "sampler");
1787 } 1853 }
1788 1854
1855 std::string GetImage(const Image& image) const {
1856 return GetDeclarationWithSuffix(static_cast<u32>(image.GetIndex()), "image");
1857 }
1858
1789 void EmitIfdefIsBuffer(const Sampler& sampler) { 1859 void EmitIfdefIsBuffer(const Sampler& sampler) {
1790 code.AddLine(fmt::format("#ifdef SAMPLER_{}_IS_BUFFER", sampler.GetIndex())); 1860 code.AddLine(fmt::format("#ifdef SAMPLER_{}_IS_BUFFER", sampler.GetIndex()));
1791 } 1861 }
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 33ad9764a..97ce214b1 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -935,6 +935,11 @@ private:
935 return {}; 935 return {};
936 } 936 }
937 937
938 Id ImageStore(Operation operation) {
939 UNIMPLEMENTED();
940 return {};
941 }
942
938 Id Branch(Operation operation) { 943 Id Branch(Operation operation) {
939 const auto target = std::get_if<ImmediateNode>(&*operation[0]); 944 const auto target = std::get_if<ImmediateNode>(&*operation[0]);
940 UNIMPLEMENTED_IF(!target); 945 UNIMPLEMENTED_IF(!target);
@@ -1326,6 +1331,8 @@ private:
1326 &SPIRVDecompiler::TextureQueryLod, 1331 &SPIRVDecompiler::TextureQueryLod,
1327 &SPIRVDecompiler::TexelFetch, 1332 &SPIRVDecompiler::TexelFetch,
1328 1333
1334 &SPIRVDecompiler::ImageStore,
1335
1329 &SPIRVDecompiler::Branch, 1336 &SPIRVDecompiler::Branch,
1330 &SPIRVDecompiler::PushFlowStack, 1337 &SPIRVDecompiler::PushFlowStack,
1331 &SPIRVDecompiler::PopFlowStack, 1338 &SPIRVDecompiler::PopFlowStack,
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index a0554c97e..2c9ff28f2 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -169,6 +169,7 @@ u32 ShaderIR::DecodeInstr(NodeBlock& bb, u32 pc) {
169 {OpCode::Type::Conversion, &ShaderIR::DecodeConversion}, 169 {OpCode::Type::Conversion, &ShaderIR::DecodeConversion},
170 {OpCode::Type::Memory, &ShaderIR::DecodeMemory}, 170 {OpCode::Type::Memory, &ShaderIR::DecodeMemory},
171 {OpCode::Type::Texture, &ShaderIR::DecodeTexture}, 171 {OpCode::Type::Texture, &ShaderIR::DecodeTexture},
172 {OpCode::Type::Image, &ShaderIR::DecodeImage},
172 {OpCode::Type::FloatSetPredicate, &ShaderIR::DecodeFloatSetPredicate}, 173 {OpCode::Type::FloatSetPredicate, &ShaderIR::DecodeFloatSetPredicate},
173 {OpCode::Type::IntegerSetPredicate, &ShaderIR::DecodeIntegerSetPredicate}, 174 {OpCode::Type::IntegerSetPredicate, &ShaderIR::DecodeIntegerSetPredicate},
174 {OpCode::Type::HalfSetPredicate, &ShaderIR::DecodeHalfSetPredicate}, 175 {OpCode::Type::HalfSetPredicate, &ShaderIR::DecodeHalfSetPredicate},
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp
new file mode 100644
index 000000000..66fdf5714
--- /dev/null
+++ b/src/video_core/shader/decode/image.cpp
@@ -0,0 +1,89 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6
7#include "common/assert.h"
8#include "common/common_types.h"
9#include "video_core/engines/shader_bytecode.h"
10#include "video_core/shader/shader_ir.h"
11
12namespace VideoCommon::Shader {
13
14using Tegra::Shader::Instruction;
15using Tegra::Shader::OpCode;
16
17namespace {
18std::size_t GetImageTypeNumCoordinates(Tegra::Shader::ImageType image_type) {
19 switch (image_type) {
20 case Tegra::Shader::ImageType::Texture1D:
21 case Tegra::Shader::ImageType::TextureBuffer:
22 return 1;
23 case Tegra::Shader::ImageType::Texture1DArray:
24 case Tegra::Shader::ImageType::Texture2D:
25 return 2;
26 case Tegra::Shader::ImageType::Texture2DArray:
27 case Tegra::Shader::ImageType::Texture3D:
28 return 3;
29 }
30 UNREACHABLE();
31 return 1;
32}
33} // Anonymous namespace
34
35u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
36 const Instruction instr = {program_code[pc]};
37 const auto opcode = OpCode::Decode(instr);
38
39 switch (opcode->get().GetId()) {
40 case OpCode::Id::SUST: {
41 UNIMPLEMENTED_IF(instr.sust.mode != Tegra::Shader::SurfaceDataMode::P);
42 UNIMPLEMENTED_IF(instr.sust.image_type == Tegra::Shader::ImageType::TextureBuffer);
43 UNIMPLEMENTED_IF(instr.sust.out_of_bounds_store != Tegra::Shader::OutOfBoundsStore::Ignore);
44 UNIMPLEMENTED_IF(instr.sust.component_mask_selector != 0xf); // Ensure we have an RGBA store
45
46 std::vector<Node> values;
47 constexpr std::size_t hardcoded_size{4};
48 for (std::size_t i = 0; i < hardcoded_size; ++i) {
49 values.push_back(GetRegister(instr.gpr0.Value() + i));
50 }
51
52 std::vector<Node> coords;
53 const std::size_t num_coords{GetImageTypeNumCoordinates(instr.sust.image_type)};
54 for (std::size_t i = 0; i < num_coords; ++i) {
55 coords.push_back(GetRegister(instr.gpr8.Value() + i));
56 }
57
58 ASSERT(instr.sust.is_immediate);
59 const auto& image{GetImage(instr.image, instr.sust.image_type)};
60 MetaImage meta{image, values};
61 const Node store{Operation(OperationCode::ImageStore, meta, std::move(coords))};
62 bb.push_back(store);
63 break;
64 }
65 default:
66 UNIMPLEMENTED_MSG("Unhandled conversion instruction: {}", opcode->get().GetName());
67 }
68
69 return pc;
70}
71
72const Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) {
73 const auto offset{static_cast<std::size_t>(image.index.Value())};
74
75 // If this image has already been used, return the existing mapping.
76 const auto itr{std::find_if(used_images.begin(), used_images.end(),
77 [=](const Image& entry) { return entry.GetOffset() == offset; })};
78 if (itr != used_images.end()) {
79 ASSERT(itr->GetType() == type);
80 return *itr;
81 }
82
83 // Otherwise create a new mapping for this image.
84 const std::size_t next_index{used_images.size()};
85 const Image entry{offset, next_index, type};
86 return *used_images.emplace(entry).first;
87}
88
89} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 3cfb911bb..8b8d83ae7 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -146,6 +146,8 @@ enum class OperationCode {
146 TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 146 TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4
147 TexelFetch, /// (MetaTexture, int[N], int) -> float4 147 TexelFetch, /// (MetaTexture, int[N], int) -> float4
148 148
149 ImageStore, /// (MetaImage, float[N] coords) -> void
150
149 Branch, /// (uint branch_target) -> void 151 Branch, /// (uint branch_target) -> void
150 PushFlowStack, /// (uint branch_target) -> void 152 PushFlowStack, /// (uint branch_target) -> void
151 PopFlowStack, /// () -> void 153 PopFlowStack, /// () -> void
@@ -263,6 +265,39 @@ private:
263 bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. 265 bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not.
264}; 266};
265 267
268class Image {
269public:
270 explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type)
271 : offset{offset}, index{index}, type{type}, is_bindless{false} {}
272
273 std::size_t GetOffset() const {
274 return offset;
275 }
276
277 std::size_t GetIndex() const {
278 return index;
279 }
280
281 Tegra::Shader::ImageType GetType() const {
282 return type;
283 }
284
285 bool IsBindless() const {
286 return is_bindless;
287 }
288
289 bool operator<(const Image& rhs) const {
290 return std::tie(offset, index, type, is_bindless) <
291 std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless);
292 }
293
294private:
295 std::size_t offset{};
296 std::size_t index{};
297 Tegra::Shader::ImageType type{};
298 bool is_bindless{};
299};
300
266struct GlobalMemoryBase { 301struct GlobalMemoryBase {
267 u32 cbuf_index{}; 302 u32 cbuf_index{};
268 u32 cbuf_offset{}; 303 u32 cbuf_offset{};
@@ -289,8 +324,13 @@ struct MetaTexture {
289 u32 element{}; 324 u32 element{};
290}; 325};
291 326
327struct MetaImage {
328 const Image& image;
329 std::vector<Node> values;
330};
331
292/// Parameters that modify an operation but are not part of any particular operand 332/// Parameters that modify an operation but are not part of any particular operand
293using Meta = std::variant<MetaArithmetic, MetaTexture, MetaStackClass, Tegra::Shader::HalfType>; 333using Meta = std::variant<MetaArithmetic, MetaTexture, MetaImage, MetaStackClass, Tegra::Shader::HalfType>;
294 334
295/// Holds any kind of operation that can be done in the IR 335/// Holds any kind of operation that can be done in the IR
296class OperationNode final { 336class OperationNode final {
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 1b84c0672..c7f264371 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -104,6 +104,10 @@ public:
104 return used_samplers; 104 return used_samplers;
105 } 105 }
106 106
107 const std::set<Image>& GetImages() const {
108 return used_images;
109 }
110
107 const std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances>& GetClipDistances() 111 const std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances>& GetClipDistances()
108 const { 112 const {
109 return used_clip_distances; 113 return used_clip_distances;
@@ -154,6 +158,7 @@ private:
154 u32 DecodeConversion(NodeBlock& bb, u32 pc); 158 u32 DecodeConversion(NodeBlock& bb, u32 pc);
155 u32 DecodeMemory(NodeBlock& bb, u32 pc); 159 u32 DecodeMemory(NodeBlock& bb, u32 pc);
156 u32 DecodeTexture(NodeBlock& bb, u32 pc); 160 u32 DecodeTexture(NodeBlock& bb, u32 pc);
161 u32 DecodeImage(NodeBlock& bb, u32 pc);
157 u32 DecodeFloatSetPredicate(NodeBlock& bb, u32 pc); 162 u32 DecodeFloatSetPredicate(NodeBlock& bb, u32 pc);
158 u32 DecodeIntegerSetPredicate(NodeBlock& bb, u32 pc); 163 u32 DecodeIntegerSetPredicate(NodeBlock& bb, u32 pc);
159 u32 DecodeHalfSetPredicate(NodeBlock& bb, u32 pc); 164 u32 DecodeHalfSetPredicate(NodeBlock& bb, u32 pc);
@@ -254,6 +259,9 @@ private:
254 Tegra::Shader::TextureType type, bool is_array, 259 Tegra::Shader::TextureType type, bool is_array,
255 bool is_shadow); 260 bool is_shadow);
256 261
262 /// Accesses an image.
263 const Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type);
264
257 /// Extracts a sequence of bits from a node 265 /// Extracts a sequence of bits from a node
258 Node BitfieldExtract(Node value, u32 offset, u32 bits); 266 Node BitfieldExtract(Node value, u32 offset, u32 bits);
259 267
@@ -329,6 +337,7 @@ private:
329 std::set<Tegra::Shader::Attribute::Index> used_output_attributes; 337 std::set<Tegra::Shader::Attribute::Index> used_output_attributes;
330 std::map<u32, ConstBuffer> used_cbufs; 338 std::map<u32, ConstBuffer> used_cbufs;
331 std::set<Sampler> used_samplers; 339 std::set<Sampler> used_samplers;
340 std::set<Image> used_images;
332 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; 341 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{};
333 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; 342 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory;
334 bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes 343 bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes