diff options
Diffstat (limited to 'src/shader_recompiler')
5 files changed, 54 insertions, 53 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index e22bb5371..2d39ea373 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -314,7 +314,7 @@ void EmitContext::DefineSharedMemory(const IR::Program& program) { | |||
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | void EmitContext::DefineAttributeMemAccess(const Info& info) { | 316 | void EmitContext::DefineAttributeMemAccess(const Info& info) { |
| 317 | const auto make_load{[&]() { | 317 | const auto make_load{[&] { |
| 318 | const Id end_block{OpLabel()}; | 318 | const Id end_block{OpLabel()}; |
| 319 | const Id default_label{OpLabel()}; | 319 | const Id default_label{OpLabel()}; |
| 320 | 320 | ||
| @@ -322,9 +322,9 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 322 | const Id func{OpFunction(F32[1], spv::FunctionControlMask::MaskNone, func_type_load)}; | 322 | const Id func{OpFunction(F32[1], spv::FunctionControlMask::MaskNone, func_type_load)}; |
| 323 | const Id offset{OpFunctionParameter(U32[1])}; | 323 | const Id offset{OpFunctionParameter(U32[1])}; |
| 324 | AddLabel(); | 324 | AddLabel(); |
| 325 | const Id base_index{OpShiftRightLogical(U32[1], offset, Constant(U32[1], 2U))}; | 325 | const Id base_index{OpShiftRightArithmetic(U32[1], offset, Constant(U32[1], 2U))}; |
| 326 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))}; | 326 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))}; |
| 327 | const Id compare_index{OpShiftRightLogical(U32[1], base_index, Constant(U32[1], 2U))}; | 327 | const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Constant(U32[1], 2U))}; |
| 328 | std::vector<Sirit::Literal> literals; | 328 | std::vector<Sirit::Literal> literals; |
| 329 | std::vector<Id> labels; | 329 | std::vector<Id> labels; |
| 330 | if (info.loads_position) { | 330 | if (info.loads_position) { |
| @@ -343,22 +343,22 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 343 | OpSwitch(compare_index, default_label, literals, labels); | 343 | OpSwitch(compare_index, default_label, literals, labels); |
| 344 | AddLabel(default_label); | 344 | AddLabel(default_label); |
| 345 | OpReturnValue(Constant(F32[1], 0.0f)); | 345 | OpReturnValue(Constant(F32[1], 0.0f)); |
| 346 | size_t label_index = 0; | 346 | size_t label_index{0}; |
| 347 | if (info.loads_position) { | 347 | if (info.loads_position) { |
| 348 | AddLabel(labels[label_index]); | 348 | AddLabel(labels[label_index]); |
| 349 | const Id result{OpLoad(F32[1], OpAccessChain(input_f32, input_position, masked_index))}; | 349 | const Id result{OpLoad(F32[1], OpAccessChain(input_f32, input_position, masked_index))}; |
| 350 | OpReturnValue(result); | 350 | OpReturnValue(result); |
| 351 | label_index++; | 351 | ++label_index; |
| 352 | } | 352 | } |
| 353 | for (u32 i = 0; i < info.input_generics.size(); i++) { | 353 | for (size_t i = 0; i < info.input_generics.size(); i++) { |
| 354 | if (!info.input_generics[i].used) { | 354 | if (!info.input_generics[i].used) { |
| 355 | continue; | 355 | continue; |
| 356 | } | 356 | } |
| 357 | AddLabel(labels[label_index]); | 357 | AddLabel(labels[label_index]); |
| 358 | const auto type{AttrTypes(*this, i)}; | 358 | const auto type{AttrTypes(*this, static_cast<u32>(i))}; |
| 359 | if (!type) { | 359 | if (!type) { |
| 360 | OpReturnValue(Constant(F32[1], 0.0f)); | 360 | OpReturnValue(Constant(F32[1], 0.0f)); |
| 361 | label_index++; | 361 | ++label_index; |
| 362 | continue; | 362 | continue; |
| 363 | } | 363 | } |
| 364 | const Id generic_id{input_generics.at(i)}; | 364 | const Id generic_id{input_generics.at(i)}; |
| @@ -366,14 +366,14 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 366 | const Id value{OpLoad(type->id, pointer)}; | 366 | const Id value{OpLoad(type->id, pointer)}; |
| 367 | const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value}; | 367 | const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value}; |
| 368 | OpReturnValue(result); | 368 | OpReturnValue(result); |
| 369 | label_index++; | 369 | ++label_index; |
| 370 | } | 370 | } |
| 371 | AddLabel(end_block); | 371 | AddLabel(end_block); |
| 372 | OpUnreachable(); | 372 | OpUnreachable(); |
| 373 | OpFunctionEnd(); | 373 | OpFunctionEnd(); |
| 374 | return func; | 374 | return func; |
| 375 | }}; | 375 | }}; |
| 376 | const auto make_store{[&]() { | 376 | const auto make_store{[&] { |
| 377 | const Id end_block{OpLabel()}; | 377 | const Id end_block{OpLabel()}; |
| 378 | const Id default_label{OpLabel()}; | 378 | const Id default_label{OpLabel()}; |
| 379 | 379 | ||
| @@ -382,9 +382,9 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 382 | const Id offset{OpFunctionParameter(U32[1])}; | 382 | const Id offset{OpFunctionParameter(U32[1])}; |
| 383 | const Id store_value{OpFunctionParameter(F32[1])}; | 383 | const Id store_value{OpFunctionParameter(F32[1])}; |
| 384 | AddLabel(); | 384 | AddLabel(); |
| 385 | const Id base_index{OpShiftRightLogical(U32[1], offset, Constant(U32[1], 2U))}; | 385 | const Id base_index{OpShiftRightArithmetic(U32[1], offset, Constant(U32[1], 2U))}; |
| 386 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))}; | 386 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))}; |
| 387 | const Id compare_index{OpShiftRightLogical(U32[1], base_index, Constant(U32[1], 2U))}; | 387 | const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Constant(U32[1], 2U))}; |
| 388 | std::vector<Sirit::Literal> literals; | 388 | std::vector<Sirit::Literal> literals; |
| 389 | std::vector<Id> labels; | 389 | std::vector<Id> labels; |
| 390 | if (info.stores_position) { | 390 | if (info.stores_position) { |
| @@ -392,11 +392,11 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 392 | labels.push_back(OpLabel()); | 392 | labels.push_back(OpLabel()); |
| 393 | } | 393 | } |
| 394 | const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2; | 394 | const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2; |
| 395 | for (u32 i = 0; i < info.stores_generics.size(); i++) { | 395 | for (size_t i = 0; i < info.stores_generics.size(); i++) { |
| 396 | if (!info.stores_generics[i]) { | 396 | if (!info.stores_generics[i]) { |
| 397 | continue; | 397 | continue; |
| 398 | } | 398 | } |
| 399 | literals.push_back(base_attribute_value + i); | 399 | literals.push_back(base_attribute_value + static_cast<u32>(i)); |
| 400 | labels.push_back(OpLabel()); | 400 | labels.push_back(OpLabel()); |
| 401 | } | 401 | } |
| 402 | if (info.stores_clip_distance) { | 402 | if (info.stores_clip_distance) { |
| @@ -409,15 +409,15 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 409 | OpSwitch(compare_index, default_label, literals, labels); | 409 | OpSwitch(compare_index, default_label, literals, labels); |
| 410 | AddLabel(default_label); | 410 | AddLabel(default_label); |
| 411 | OpReturn(); | 411 | OpReturn(); |
| 412 | size_t label_index = 0; | 412 | size_t label_index{0}; |
| 413 | if (info.stores_position) { | 413 | if (info.stores_position) { |
| 414 | AddLabel(labels[label_index]); | 414 | AddLabel(labels[label_index]); |
| 415 | const Id pointer{OpAccessChain(output_f32, output_position, masked_index)}; | 415 | const Id pointer{OpAccessChain(output_f32, output_position, masked_index)}; |
| 416 | OpStore(pointer, store_value); | 416 | OpStore(pointer, store_value); |
| 417 | OpReturn(); | 417 | OpReturn(); |
| 418 | label_index++; | 418 | ++label_index; |
| 419 | } | 419 | } |
| 420 | for (u32 i = 0; i < info.stores_generics.size(); i++) { | 420 | for (size_t i = 0; i < info.stores_generics.size(); i++) { |
| 421 | if (!info.stores_generics[i]) { | 421 | if (!info.stores_generics[i]) { |
| 422 | continue; | 422 | continue; |
| 423 | } | 423 | } |
| @@ -426,20 +426,20 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 426 | const Id pointer{OpAccessChain(output_f32, generic_id, masked_index)}; | 426 | const Id pointer{OpAccessChain(output_f32, generic_id, masked_index)}; |
| 427 | OpStore(pointer, store_value); | 427 | OpStore(pointer, store_value); |
| 428 | OpReturn(); | 428 | OpReturn(); |
| 429 | label_index++; | 429 | ++label_index; |
| 430 | } | 430 | } |
| 431 | if (info.stores_clip_distance) { | 431 | if (info.stores_clip_distance) { |
| 432 | AddLabel(labels[label_index]); | 432 | AddLabel(labels[label_index]); |
| 433 | const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; | 433 | const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; |
| 434 | OpStore(pointer, store_value); | 434 | OpStore(pointer, store_value); |
| 435 | OpReturn(); | 435 | OpReturn(); |
| 436 | label_index++; | 436 | ++label_index; |
| 437 | AddLabel(labels[label_index]); | 437 | AddLabel(labels[label_index]); |
| 438 | const Id fixed_index{OpIAdd(U32[1], masked_index, Constant(U32[1], 4))}; | 438 | const Id fixed_index{OpIAdd(U32[1], masked_index, Constant(U32[1], 4))}; |
| 439 | const Id pointer2{OpAccessChain(output_f32, clip_distances, fixed_index)}; | 439 | const Id pointer2{OpAccessChain(output_f32, clip_distances, fixed_index)}; |
| 440 | OpStore(pointer2, store_value); | 440 | OpStore(pointer2, store_value); |
| 441 | OpReturn(); | 441 | OpReturn(); |
| 442 | label_index++; | 442 | ++label_index; |
| 443 | } | 443 | } |
| 444 | AddLabel(end_block); | 444 | AddLabel(end_block); |
| 445 | OpUnreachable(); | 445 | OpUnreachable(); |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index e4e9b260c..13eb2de4c 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -307,11 +307,11 @@ void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value) { | |||
| 307 | Inst(Opcode::SetAttribute, attribute, value); | 307 | Inst(Opcode::SetAttribute, attribute, value); |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | F32 IREmitter::GetAttributeIndexed(IR::U32 phys_address) { | 310 | F32 IREmitter::GetAttributeIndexed(const U32& phys_address) { |
| 311 | return Inst<F32>(Opcode::GetAttributeIndexed, phys_address); | 311 | return Inst<F32>(Opcode::GetAttributeIndexed, phys_address); |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | void IREmitter::SetAttributeIndexed(IR::U32 phys_address, const F32& value) { | 314 | void IREmitter::SetAttributeIndexed(const U32& phys_address, const F32& value) { |
| 315 | Inst(Opcode::SetAttributeIndexed, phys_address, value); | 315 | Inst(Opcode::SetAttributeIndexed, phys_address, value); |
| 316 | } | 316 | } |
| 317 | 317 | ||
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index afa8bd924..2cab1dc5d 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -76,8 +76,8 @@ public: | |||
| 76 | [[nodiscard]] F32 GetAttribute(IR::Attribute attribute); | 76 | [[nodiscard]] F32 GetAttribute(IR::Attribute attribute); |
| 77 | void SetAttribute(IR::Attribute attribute, const F32& value); | 77 | void SetAttribute(IR::Attribute attribute, const F32& value); |
| 78 | 78 | ||
| 79 | [[nodiscard]] F32 GetAttributeIndexed(IR::U32 phys_address); | 79 | [[nodiscard]] F32 GetAttributeIndexed(const U32& phys_address); |
| 80 | void SetAttributeIndexed(IR::U32 phys_address, const F32& value); | 80 | void SetAttributeIndexed(const U32& phys_address, const F32& value); |
| 81 | 81 | ||
| 82 | void SetFragColor(u32 index, u32 component, const F32& value); | 82 | void SetFragColor(u32 index, u32 component, const F32& value); |
| 83 | void SetFragDepth(const F32& value); | 83 | void SetFragDepth(const F32& value); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp index 0d248c020..f629e7167 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp | |||
| @@ -44,6 +44,17 @@ u32 NumElements(Size size) { | |||
| 44 | } | 44 | } |
| 45 | throw InvalidArgument("Invalid size {}", size); | 45 | throw InvalidArgument("Invalid size {}", size); |
| 46 | } | 46 | } |
| 47 | |||
| 48 | template <typename F> | ||
| 49 | void HandleIndexed(TranslatorVisitor& v, IR::Reg index_reg, u32 num_elements, F&& f) { | ||
| 50 | const IR::U32 index_value{v.X(index_reg)}; | ||
| 51 | for (u32 element = 0; element < num_elements; ++element) { | ||
| 52 | const IR::U32 final_offset{ | ||
| 53 | element == 0 ? index_value : IR::U32{v.ir.IAdd(index_value, v.ir.Imm32(element * 4U))}}; | ||
| 54 | f(element, final_offset); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 47 | } // Anonymous namespace | 58 | } // Anonymous namespace |
| 48 | 59 | ||
| 49 | void TranslatorVisitor::ALD(u64 insn) { | 60 | void TranslatorVisitor::ALD(u64 insn) { |
| @@ -70,18 +81,15 @@ void TranslatorVisitor::ALD(u64 insn) { | |||
| 70 | throw NotImplementedException("Unaligned absolute offset {}", offset); | 81 | throw NotImplementedException("Unaligned absolute offset {}", offset); |
| 71 | } | 82 | } |
| 72 | const u32 num_elements{NumElements(ald.size)}; | 83 | const u32 num_elements{NumElements(ald.size)}; |
| 73 | if (ald.index_reg != IR::Reg::RZ) { | 84 | if (ald.index_reg == IR::Reg::RZ) { |
| 74 | const IR::U32 index_value = X(ald.index_reg); | ||
| 75 | for (u32 element = 0; element < num_elements; ++element) { | 85 | for (u32 element = 0; element < num_elements; ++element) { |
| 76 | const IR::U32 final_offset = | 86 | F(ald.dest_reg + element, ir.GetAttribute(IR::Attribute{offset / 4 + element})); |
| 77 | element == 0 ? index_value : IR::U32{ir.IAdd(index_value, ir.Imm32(element * 4U))}; | ||
| 78 | F(ald.dest_reg + element, ir.GetAttributeIndexed(final_offset)); | ||
| 79 | } | 87 | } |
| 80 | return; | 88 | return; |
| 81 | } | 89 | } |
| 82 | for (u32 element = 0; element < num_elements; ++element) { | 90 | HandleIndexed(*this, ald.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) { |
| 83 | F(ald.dest_reg + element, ir.GetAttribute(IR::Attribute{offset / 4 + element})); | 91 | F(ald.dest_reg + element, ir.GetAttributeIndexed(final_offset)); |
| 84 | } | 92 | }); |
| 85 | } | 93 | } |
| 86 | 94 | ||
| 87 | void TranslatorVisitor::AST(u64 insn) { | 95 | void TranslatorVisitor::AST(u64 insn) { |
| @@ -110,18 +118,15 @@ void TranslatorVisitor::AST(u64 insn) { | |||
| 110 | throw NotImplementedException("Unaligned absolute offset {}", offset); | 118 | throw NotImplementedException("Unaligned absolute offset {}", offset); |
| 111 | } | 119 | } |
| 112 | const u32 num_elements{NumElements(ast.size)}; | 120 | const u32 num_elements{NumElements(ast.size)}; |
| 113 | if (ast.index_reg != IR::Reg::RZ) { | 121 | if (ast.index_reg == IR::Reg::RZ) { |
| 114 | const IR::U32 index_value = X(ast.index_reg); | ||
| 115 | for (u32 element = 0; element < num_elements; ++element) { | 122 | for (u32 element = 0; element < num_elements; ++element) { |
| 116 | const IR::U32 final_offset = | 123 | ir.SetAttribute(IR::Attribute{offset / 4 + element}, F(ast.src_reg + element)); |
| 117 | element == 0 ? index_value : IR::U32{ir.IAdd(index_value, ir.Imm32(element * 4U))}; | ||
| 118 | ir.SetAttributeIndexed(final_offset, F(ast.src_reg + element)); | ||
| 119 | } | 124 | } |
| 120 | return; | 125 | return; |
| 121 | } | 126 | } |
| 122 | for (u32 element = 0; element < num_elements; ++element) { | 127 | HandleIndexed(*this, ast.index_reg, num_elements, [&](u32 element, IR::U32 final_offset) { |
| 123 | ir.SetAttribute(IR::Attribute{offset / 4 + element}, F(ast.src_reg + element)); | 128 | ir.SetAttributeIndexed(final_offset, F(ast.src_reg + element)); |
| 124 | } | 129 | }); |
| 125 | } | 130 | } |
| 126 | 131 | ||
| 127 | void TranslatorVisitor::IPA(u64 insn) { | 132 | void TranslatorVisitor::IPA(u64 insn) { |
diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index a14465598..1c03ee82a 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | |||
| @@ -511,37 +511,33 @@ void Visit(Info& info, IR::Inst& inst) { | |||
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | void GatherInfoFromHeader(Environment& env, Info& info) { | 513 | void GatherInfoFromHeader(Environment& env, Info& info) { |
| 514 | auto stage = env.ShaderStage(); | 514 | Stage stage{env.ShaderStage()}; |
| 515 | if (stage == Stage::Compute) { | 515 | if (stage == Stage::Compute) { |
| 516 | return; | 516 | return; |
| 517 | } | 517 | } |
| 518 | const auto& header = env.SPH(); | 518 | const auto& header{env.SPH()}; |
| 519 | if (stage == Stage::Fragment) { | 519 | if (stage == Stage::Fragment) { |
| 520 | if (!info.loads_indexed_attributes) { | 520 | if (!info.loads_indexed_attributes) { |
| 521 | return; | 521 | return; |
| 522 | } | 522 | } |
| 523 | for (size_t i = 0; i < info.input_generics.size(); i++) { | 523 | for (size_t i = 0; i < info.input_generics.size(); i++) { |
| 524 | info.input_generics[i].used = | 524 | info.input_generics[i].used |= header.ps.IsGenericVectorActive(i); |
| 525 | info.input_generics[i].used || header.ps.IsGenericVectorActive(i); | ||
| 526 | } | 525 | } |
| 527 | info.loads_position = info.loads_position || header.ps.imap_systemb.position != 0; | 526 | info.loads_position |= header.ps.imap_systemb.position != 0; |
| 528 | return; | 527 | return; |
| 529 | } | 528 | } |
| 530 | if (info.loads_indexed_attributes) { | 529 | if (info.loads_indexed_attributes) { |
| 531 | for (size_t i = 0; i < info.input_generics.size(); i++) { | 530 | for (size_t i = 0; i < info.input_generics.size(); i++) { |
| 532 | info.input_generics[i].used = | 531 | info.input_generics[i].used |= header.vtg.IsInputGenericVectorActive(i); |
| 533 | info.input_generics[i].used || header.vtg.IsInputGenericVectorActive(i); | ||
| 534 | } | 532 | } |
| 533 | info.loads_position |= header.vtg.imap_systemb.position != 0; | ||
| 535 | } | 534 | } |
| 536 | if (info.stores_indexed_attributes) { | 535 | if (info.stores_indexed_attributes) { |
| 537 | info.loads_position = info.loads_position || header.vtg.imap_systemb.position != 0; | ||
| 538 | for (size_t i = 0; i < info.stores_generics.size(); i++) { | 536 | for (size_t i = 0; i < info.stores_generics.size(); i++) { |
| 539 | info.stores_generics[i] = | 537 | info.stores_generics[i] |= header.vtg.IsOutputGenericVectorActive(i); |
| 540 | info.stores_generics[i] || header.vtg.IsOutputGenericVectorActive(i); | ||
| 541 | } | 538 | } |
| 542 | info.stores_clip_distance = | 539 | info.stores_clip_distance |= header.vtg.omap_systemc.clip_distances != 0; |
| 543 | info.stores_clip_distance || header.vtg.omap_systemc.clip_distances != 0; | 540 | info.stores_position |= header.vtg.omap_systemb.position != 0; |
| 544 | info.stores_position = info.stores_position || header.vtg.omap_systemb.position != 0; | ||
| 545 | } | 541 | } |
| 546 | } | 542 | } |
| 547 | 543 | ||