summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/ir_opt/texture_pass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/ir_opt/texture_pass.cpp')
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp80
1 files changed, 69 insertions, 11 deletions
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index e1d5a2ce1..5ac485522 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -19,6 +19,9 @@ namespace {
19struct ConstBufferAddr { 19struct ConstBufferAddr {
20 u32 index; 20 u32 index;
21 u32 offset; 21 u32 offset;
22 u32 secondary_index;
23 u32 secondary_offset;
24 bool has_secondary;
22}; 25};
23 26
24struct TextureInst { 27struct TextureInst {
@@ -109,9 +112,38 @@ bool IsTextureInstruction(const IR::Inst& inst) {
109 return IndexedInstruction(inst) != IR::Opcode::Void; 112 return IndexedInstruction(inst) != IR::Opcode::Void;
110} 113}
111 114
115std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst);
116
117std::optional<ConstBufferAddr> Track(const IR::Value& value) {
118 return IR::BreadthFirstSearch(value, TryGetConstBuffer);
119}
120
112std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) { 121std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) {
113 if (inst->GetOpcode() != IR::Opcode::GetCbufU32) { 122 switch (inst->GetOpcode()) {
123 default:
114 return std::nullopt; 124 return std::nullopt;
125 case IR::Opcode::BitwiseOr32: {
126 std::optional lhs{Track(inst->Arg(0))};
127 std::optional rhs{Track(inst->Arg(1))};
128 if (!lhs || !rhs) {
129 return std::nullopt;
130 }
131 if (lhs->has_secondary || rhs->has_secondary) {
132 return std::nullopt;
133 }
134 if (lhs->index > rhs->index || lhs->offset > rhs->offset) {
135 std::swap(lhs, rhs);
136 }
137 return ConstBufferAddr{
138 .index = lhs->index,
139 .offset = lhs->offset,
140 .secondary_index = rhs->index,
141 .secondary_offset = rhs->offset,
142 .has_secondary = true,
143 };
144 }
145 case IR::Opcode::GetCbufU32:
146 break;
115 } 147 }
116 const IR::Value index{inst->Arg(0)}; 148 const IR::Value index{inst->Arg(0)};
117 const IR::Value offset{inst->Arg(1)}; 149 const IR::Value offset{inst->Arg(1)};
@@ -127,13 +159,12 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) {
127 return ConstBufferAddr{ 159 return ConstBufferAddr{
128 .index{index.U32()}, 160 .index{index.U32()},
129 .offset{offset.U32()}, 161 .offset{offset.U32()},
162 .secondary_index = 0,
163 .secondary_offset = 0,
164 .has_secondary = false,
130 }; 165 };
131} 166}
132 167
133std::optional<ConstBufferAddr> Track(const IR::Value& value) {
134 return IR::BreadthFirstSearch(value, TryGetConstBuffer);
135}
136
137TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { 168TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
138 ConstBufferAddr addr; 169 ConstBufferAddr addr;
139 if (IsBindless(inst)) { 170 if (IsBindless(inst)) {
@@ -146,6 +177,9 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
146 addr = ConstBufferAddr{ 177 addr = ConstBufferAddr{
147 .index = env.TextureBoundBuffer(), 178 .index = env.TextureBoundBuffer(),
148 .offset = inst.Arg(0).U32(), 179 .offset = inst.Arg(0).U32(),
180 .secondary_index = 0,
181 .secondary_offset = 0,
182 .has_secondary = false,
149 }; 183 };
150 } 184 }
151 return TextureInst{ 185 return TextureInst{
@@ -155,6 +189,14 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
155 }; 189 };
156} 190}
157 191
192TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) {
193 const u32 secondary_index{cbuf.has_secondary ? cbuf.index : cbuf.secondary_index};
194 const u32 secondary_offset{cbuf.has_secondary ? cbuf.offset : cbuf.secondary_offset};
195 const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset)};
196 const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)};
197 return env.ReadTextureType(lhs_raw | rhs_raw);
198}
199
158class Descriptors { 200class Descriptors {
159public: 201public:
160 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_, 202 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_,
@@ -167,8 +209,11 @@ public:
167 209
168 u32 Add(const TextureBufferDescriptor& desc) { 210 u32 Add(const TextureBufferDescriptor& desc) {
169 return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { 211 return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) {
170 return desc.cbuf_index == existing.cbuf_index && 212 return desc.has_secondary == existing.has_secondary &&
171 desc.cbuf_offset == existing.cbuf_offset; 213 desc.cbuf_index == existing.cbuf_index &&
214 desc.cbuf_offset == existing.cbuf_offset &&
215 desc.secondary_cbuf_index == existing.secondary_cbuf_index &&
216 desc.secondary_cbuf_offset == existing.secondary_cbuf_offset;
172 }); 217 });
173 } 218 }
174 219
@@ -181,8 +226,12 @@ public:
181 226
182 u32 Add(const TextureDescriptor& desc) { 227 u32 Add(const TextureDescriptor& desc) {
183 return Add(texture_descriptors, desc, [&desc](const auto& existing) { 228 return Add(texture_descriptors, desc, [&desc](const auto& existing) {
184 return desc.cbuf_index == existing.cbuf_index && 229 return desc.type == existing.type && desc.is_depth == existing.is_depth &&
185 desc.cbuf_offset == existing.cbuf_offset && desc.type == existing.type; 230 desc.has_secondary == existing.has_secondary &&
231 desc.cbuf_index == existing.cbuf_index &&
232 desc.cbuf_offset == existing.cbuf_offset &&
233 desc.secondary_cbuf_index == existing.secondary_cbuf_index &&
234 desc.secondary_cbuf_offset == existing.secondary_cbuf_offset;
186 }); 235 });
187 } 236 }
188 237
@@ -247,14 +296,14 @@ void TexturePass(Environment& env, IR::Program& program) {
247 auto flags{inst->Flags<IR::TextureInstInfo>()}; 296 auto flags{inst->Flags<IR::TextureInstInfo>()};
248 switch (inst->GetOpcode()) { 297 switch (inst->GetOpcode()) {
249 case IR::Opcode::ImageQueryDimensions: 298 case IR::Opcode::ImageQueryDimensions:
250 flags.type.Assign(env.ReadTextureType(cbuf.index, cbuf.offset)); 299 flags.type.Assign(ReadTextureType(env, cbuf));
251 inst->SetFlags(flags); 300 inst->SetFlags(flags);
252 break; 301 break;
253 case IR::Opcode::ImageFetch: 302 case IR::Opcode::ImageFetch:
254 if (flags.type != TextureType::Color1D) { 303 if (flags.type != TextureType::Color1D) {
255 break; 304 break;
256 } 305 }
257 if (env.ReadTextureType(cbuf.index, cbuf.offset) == TextureType::Buffer) { 306 if (ReadTextureType(env, cbuf) == TextureType::Buffer) {
258 // Replace with the bound texture type only when it's a texture buffer 307 // Replace with the bound texture type only when it's a texture buffer
259 // If the instruction is 1D and the bound type is 2D, don't change the code and let 308 // If the instruction is 1D and the bound type is 2D, don't change the code and let
260 // the rasterizer robustness handle it 309 // the rasterizer robustness handle it
@@ -270,6 +319,9 @@ void TexturePass(Environment& env, IR::Program& program) {
270 switch (inst->GetOpcode()) { 319 switch (inst->GetOpcode()) {
271 case IR::Opcode::ImageRead: 320 case IR::Opcode::ImageRead:
272 case IR::Opcode::ImageWrite: { 321 case IR::Opcode::ImageWrite: {
322 if (cbuf.has_secondary) {
323 throw NotImplementedException("Unexpected separate sampler");
324 }
273 const bool is_written{inst->GetOpcode() == IR::Opcode::ImageWrite}; 325 const bool is_written{inst->GetOpcode() == IR::Opcode::ImageWrite};
274 if (flags.type == TextureType::Buffer) { 326 if (flags.type == TextureType::Buffer) {
275 index = descriptors.Add(ImageBufferDescriptor{ 327 index = descriptors.Add(ImageBufferDescriptor{
@@ -294,16 +346,22 @@ void TexturePass(Environment& env, IR::Program& program) {
294 default: 346 default:
295 if (flags.type == TextureType::Buffer) { 347 if (flags.type == TextureType::Buffer) {
296 index = descriptors.Add(TextureBufferDescriptor{ 348 index = descriptors.Add(TextureBufferDescriptor{
349 .has_secondary = cbuf.has_secondary,
297 .cbuf_index = cbuf.index, 350 .cbuf_index = cbuf.index,
298 .cbuf_offset = cbuf.offset, 351 .cbuf_offset = cbuf.offset,
352 .secondary_cbuf_index = cbuf.secondary_index,
353 .secondary_cbuf_offset = cbuf.secondary_offset,
299 .count = 1, 354 .count = 1,
300 }); 355 });
301 } else { 356 } else {
302 index = descriptors.Add(TextureDescriptor{ 357 index = descriptors.Add(TextureDescriptor{
303 .type = flags.type, 358 .type = flags.type,
304 .is_depth = flags.is_depth != 0, 359 .is_depth = flags.is_depth != 0,
360 .has_secondary = cbuf.has_secondary,
305 .cbuf_index = cbuf.index, 361 .cbuf_index = cbuf.index,
306 .cbuf_offset = cbuf.offset, 362 .cbuf_offset = cbuf.offset,
363 .secondary_cbuf_index = cbuf.secondary_index,
364 .secondary_cbuf_offset = cbuf.secondary_offset,
307 .count = 1, 365 .count = 1,
308 }); 366 });
309 } 367 }