summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp68
1 files changed, 59 insertions, 9 deletions
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index 4bad811c2..0726d4d21 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -174,20 +174,41 @@ bool IsTextureInstruction(const IR::Inst& inst) {
174 return IndexedInstruction(inst) != IR::Opcode::Void; 174 return IndexedInstruction(inst) != IR::Opcode::Void;
175} 175}
176 176
177std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst); 177std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst, Environment& env);
178 178
179std::optional<ConstBufferAddr> Track(const IR::Value& value) { 179std::optional<ConstBufferAddr> Track(const IR::Value& value, Environment& env) {
180 return IR::BreadthFirstSearch(value, TryGetConstBuffer); 180 return IR::BreadthFirstSearch(
181 value, [&env](const IR::Inst* inst) { return TryGetConstBuffer(inst, env); });
181} 182}
182 183
183std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) { 184std::optional<u32> TryGetConstant(IR::Value& value, Environment& env) {
185 const IR::Inst* inst = value.InstRecursive();
186 if (inst->GetOpcode() != IR::Opcode::GetCbufU32) {
187 return std::nullopt;
188 }
189 const IR::Value index{inst->Arg(0)};
190 const IR::Value offset{inst->Arg(1)};
191 if (!index.IsImmediate()) {
192 return std::nullopt;
193 }
194 if (!offset.IsImmediate()) {
195 return std::nullopt;
196 }
197 const auto index_number = index.U32();
198 if (index_number != 1) {
199 return std::nullopt;
200 }
201 const auto offset_number = offset.U32();
202 return env.ReadCbufValue(index_number, offset_number);
203}
204
205std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst, Environment& env) {
184 switch (inst->GetOpcode()) { 206 switch (inst->GetOpcode()) {
185 default: 207 default:
186 return std::nullopt; 208 return std::nullopt;
187 case IR::Opcode::BitwiseXor32:
188 case IR::Opcode::BitwiseOr32: { 209 case IR::Opcode::BitwiseOr32: {
189 std::optional lhs{Track(inst->Arg(0))}; 210 std::optional lhs{Track(inst->Arg(0), env)};
190 std::optional rhs{Track(inst->Arg(1))}; 211 std::optional rhs{Track(inst->Arg(1), env)};
191 if (!lhs || !rhs) { 212 if (!lhs || !rhs) {
192 return std::nullopt; 213 return std::nullopt;
193 } 214 }
@@ -217,13 +238,42 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) {
217 if (!shift.IsImmediate()) { 238 if (!shift.IsImmediate()) {
218 return std::nullopt; 239 return std::nullopt;
219 } 240 }
220 std::optional lhs{Track(inst->Arg(0))}; 241 std::optional lhs{Track(inst->Arg(0), env)};
221 if (lhs) { 242 if (lhs) {
222 lhs->shift_left = shift.U32(); 243 lhs->shift_left = shift.U32();
223 } 244 }
224 return lhs; 245 return lhs;
225 break; 246 break;
226 } 247 }
248 case IR::Opcode::BitwiseAnd32: {
249 IR::Value op1{inst->Arg(0)};
250 IR::Value op2{inst->Arg(1)};
251 if (op1.IsImmediate()) {
252 std::swap(op1, op2);
253 }
254 if (!op2.IsImmediate() && !op1.IsImmediate()) {
255 do {
256 auto try_index = TryGetConstant(op1, env);
257 if (try_index) {
258 op1 = op2;
259 op2 = IR::Value{*try_index};
260 break;
261 }
262 auto try_index_2 = TryGetConstant(op2, env);
263 if (try_index_2) {
264 op2 = IR::Value{*try_index_2};
265 break;
266 }
267 return std::nullopt;
268 } while (false);
269 }
270 std::optional lhs{Track(op1, env)};
271 if (lhs) {
272 lhs->shift_left = std::countr_zero(op2.U32());
273 }
274 return lhs;
275 break;
276 }
227 case IR::Opcode::GetCbufU32x2: 277 case IR::Opcode::GetCbufU32x2:
228 case IR::Opcode::GetCbufU32: 278 case IR::Opcode::GetCbufU32:
229 break; 279 break;
@@ -279,7 +329,7 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) {
279TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { 329TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
280 ConstBufferAddr addr; 330 ConstBufferAddr addr;
281 if (IsBindless(inst)) { 331 if (IsBindless(inst)) {
282 const std::optional<ConstBufferAddr> track_addr{Track(inst.Arg(0))}; 332 const std::optional<ConstBufferAddr> track_addr{Track(inst.Arg(0), env)};
283 if (!track_addr) { 333 if (!track_addr) {
284 throw NotImplementedException("Failed to track bindless texture constant buffer"); 334 throw NotImplementedException("Failed to track bindless texture constant buffer");
285 } 335 }