diff options
| author | 2022-03-26 13:40:42 +0100 | |
|---|---|---|
| committer | 2022-10-06 21:00:53 +0200 | |
| commit | 3d02143476cbc92450587c4e56eafe1cb76cd9ad (patch) | |
| tree | 207a054f2dc887b1356778d8d6fda057974ae935 | |
| parent | Shader Decompiler: Check for shift when deriving composite samplers. (diff) | |
| download | yuzu-3d02143476cbc92450587c4e56eafe1cb76cd9ad.tar.gz yuzu-3d02143476cbc92450587c4e56eafe1cb76cd9ad.tar.xz yuzu-3d02143476cbc92450587c4e56eafe1cb76cd9ad.zip | |
Shader Decompiler: implement better tracking for Vulkan samplers.
Diffstat (limited to '')
| -rw-r--r-- | src/shader_recompiler/ir_opt/texture_pass.cpp | 68 |
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 | ||
| 177 | std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst); | 177 | std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst, Environment& env); |
| 178 | 178 | ||
| 179 | std::optional<ConstBufferAddr> Track(const IR::Value& value) { | 179 | std::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 | ||
| 183 | std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) { | 184 | std::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 | |||
| 205 | std::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) { | |||
| 279 | TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { | 329 | TextureInst 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 | } |