summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp165
-rw-r--r--src/video_core/shader/shader_ir.h2
2 files changed, 101 insertions, 66 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 1ad33107d..47bfa5538 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -165,6 +165,7 @@ public:
165 DeclareConstantBuffers(); 165 DeclareConstantBuffers();
166 DeclareGlobalMemory(); 166 DeclareGlobalMemory();
167 DeclareSamplers(); 167 DeclareSamplers();
168 DeclarePhysicalAttributeReader();
168 169
169 code.AddLine("void execute_" + suffix + "() {"); 170 code.AddLine("void execute_" + suffix + "() {");
170 ++code.scope; 171 ++code.scope;
@@ -330,8 +331,7 @@ private:
330 331
331 void DeclareInputAttributes() { 332 void DeclareInputAttributes() {
332 if (ir.HasPhysicalAttributes()) { 333 if (ir.HasPhysicalAttributes()) {
333 const u32 num_inputs{stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() 334 const u32 num_inputs{GetNumPhysicalInputAttributes()};
334 : GetNumPhysicalVaryings()};
335 for (u32 i = 0; i < num_inputs; ++i) { 335 for (u32 i = 0; i < num_inputs; ++i) {
336 DeclareInputAttribute(ToGenericAttribute(i)); 336 DeclareInputAttribute(ToGenericAttribute(i));
337 } 337 }
@@ -374,7 +374,7 @@ private:
374 } 374 }
375 375
376 void DeclareOutputAttributes() { 376 void DeclareOutputAttributes() {
377 if (ir.HasPhysicalAttributes()) { 377 if (ir.HasPhysicalAttributes() && stage != ShaderStage::Fragment) {
378 for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) { 378 for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) {
379 DeclareOutputAttribute(ToGenericAttribute(i)); 379 DeclareOutputAttribute(ToGenericAttribute(i));
380 } 380 }
@@ -461,6 +461,31 @@ private:
461 code.AddNewLine(); 461 code.AddNewLine();
462 } 462 }
463 463
464 void DeclarePhysicalAttributeReader() {
465 if (!ir.HasPhysicalAttributes()) {
466 return;
467 }
468 code.AddLine("float readPhysicalAttribute(uint physical_address) {");
469 ++code.scope;
470 code.AddLine("switch (physical_address) {");
471
472 // Just declare generic attributes for now.
473 const auto num_attributes{static_cast<u32>(GetNumPhysicalAttributes())};
474 for (u32 index = 0; index < num_attributes; ++index) {
475 for (u32 element = 0; element < 4; ++element) {
476 code.AddLine(fmt::format("case 0x{:x}: return {};", 0x80 + index * 16 + element * 4,
477 ReadAttribute(ToGenericAttribute(index), element)));
478 }
479 }
480
481 code.AddLine("default: return 0;");
482
483 code.AddLine('}');
484 --code.scope;
485 code.AddLine('}');
486 code.AddNewLine();
487 }
488
464 void VisitBlock(const NodeBlock& bb) { 489 void VisitBlock(const NodeBlock& bb) {
465 for (const Node node : bb) { 490 for (const Node node : bb) {
466 if (const std::string expr = Visit(node); !expr.empty()) { 491 if (const std::string expr = Visit(node); !expr.empty()) {
@@ -515,69 +540,12 @@ private:
515 return value; 540 return value;
516 541
517 } else if (const auto abuf = std::get_if<AbufNode>(node)) { 542 } else if (const auto abuf = std::get_if<AbufNode>(node)) {
518 const auto attribute = abuf->GetIndex(); 543 UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ShaderStage::Geometry,
519 const auto element = abuf->GetElement(); 544 "Physical attributes in geometry shaders are not implemented");
520 545 if (abuf->IsPhysicalBuffer()) {
521 const auto GeometryPass = [&](const std::string& name) { 546 return "readPhysicalAttribute(ftou(" + Visit(abuf->GetPhysicalAddress()) + "))";
522 if (stage == ShaderStage::Geometry && abuf->GetBuffer()) {
523 // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
524 // set an 0x80000000 index for those and the shader fails to build. Find out why
525 // this happens and what's its intent.
526 return "gs_" + name + "[ftou(" + Visit(abuf->GetBuffer()) +
527 ") % MAX_VERTEX_INPUT]";
528 }
529 return name;
530 };
531
532 switch (attribute) {
533 case Attribute::Index::Position:
534 if (stage != ShaderStage::Fragment) {
535 return GeometryPass("position") + GetSwizzle(element);
536 } else {
537 return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element);
538 }
539 case Attribute::Index::PointCoord:
540 switch (element) {
541 case 0:
542 return "gl_PointCoord.x";
543 case 1:
544 return "gl_PointCoord.y";
545 case 2:
546 case 3:
547 return "0";
548 }
549 UNREACHABLE();
550 return "0";
551 case Attribute::Index::TessCoordInstanceIDVertexID:
552 // TODO(Subv): Find out what the values are for the first two elements when inside a
553 // vertex shader, and what's the value of the fourth element when inside a Tess Eval
554 // shader.
555 ASSERT(stage == ShaderStage::Vertex);
556 switch (element) {
557 case 2:
558 // Config pack's first value is instance_id.
559 return "uintBitsToFloat(config_pack[0])";
560 case 3:
561 return "uintBitsToFloat(gl_VertexID)";
562 }
563 UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element);
564 return "0";
565 case Attribute::Index::FrontFacing:
566 // TODO(Subv): Find out what the values are for the other elements.
567 ASSERT(stage == ShaderStage::Fragment);
568 switch (element) {
569 case 3:
570 return "itof(gl_FrontFacing ? -1 : 0)";
571 }
572 UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element);
573 return "0";
574 default:
575 if (IsGenericAttribute(attribute)) {
576 return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element);
577 }
578 break;
579 } 547 }
580 UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); 548 return ReadAttribute(abuf->GetIndex(), abuf->GetElement(), abuf->GetBuffer());
581 549
582 } else if (const auto cbuf = std::get_if<CbufNode>(node)) { 550 } else if (const auto cbuf = std::get_if<CbufNode>(node)) {
583 const Node offset = cbuf->GetOffset(); 551 const Node offset = cbuf->GetOffset();
@@ -629,6 +597,69 @@ private:
629 return {}; 597 return {};
630 } 598 }
631 599
600 std::string ReadAttribute(Attribute::Index attribute, u32 element, Node buffer = {}) {
601 const auto GeometryPass = [&](std::string name) {
602 if (stage == ShaderStage::Geometry && buffer) {
603 // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
604 // set an 0x80000000 index for those and the shader fails to build. Find out why
605 // this happens and what's its intent.
606 return "gs_" + std::move(name) + "[ftou(" + Visit(buffer) + ") % MAX_VERTEX_INPUT]";
607 }
608 return name;
609 };
610
611 switch (attribute) {
612 case Attribute::Index::Position:
613 if (stage != ShaderStage::Fragment) {
614 return GeometryPass("position") + GetSwizzle(element);
615 } else {
616 return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element);
617 }
618 case Attribute::Index::PointCoord:
619 switch (element) {
620 case 0:
621 return "gl_PointCoord.x";
622 case 1:
623 return "gl_PointCoord.y";
624 case 2:
625 case 3:
626 return "0";
627 }
628 UNREACHABLE();
629 return "0";
630 case Attribute::Index::TessCoordInstanceIDVertexID:
631 // TODO(Subv): Find out what the values are for the first two elements when inside a
632 // vertex shader, and what's the value of the fourth element when inside a Tess Eval
633 // shader.
634 ASSERT(stage == ShaderStage::Vertex);
635 switch (element) {
636 case 2:
637 // Config pack's first value is instance_id.
638 return "uintBitsToFloat(config_pack[0])";
639 case 3:
640 return "uintBitsToFloat(gl_VertexID)";
641 }
642 UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element);
643 return "0";
644 case Attribute::Index::FrontFacing:
645 // TODO(Subv): Find out what the values are for the other elements.
646 ASSERT(stage == ShaderStage::Fragment);
647 switch (element) {
648 case 3:
649 return "itof(gl_FrontFacing ? -1 : 0)";
650 }
651 UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element);
652 return "0";
653 default:
654 if (IsGenericAttribute(attribute)) {
655 return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element);
656 }
657 break;
658 }
659 UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
660 return "0";
661 }
662
632 std::string ApplyPrecise(Operation operation, const std::string& value) { 663 std::string ApplyPrecise(Operation operation, const std::string& value) {
633 if (!IsPrecise(operation)) { 664 if (!IsPrecise(operation)) {
634 return value; 665 return value;
@@ -1677,6 +1708,10 @@ private:
1677 return name + '_' + std::to_string(index) + '_' + suffix; 1708 return name + '_' + std::to_string(index) + '_' + suffix;
1678 } 1709 }
1679 1710
1711 u32 GetNumPhysicalInputAttributes() const {
1712 return stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings();
1713 }
1714
1680 u32 GetNumPhysicalAttributes() const { 1715 u32 GetNumPhysicalAttributes() const {
1681 return std::min<u32>(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes); 1716 return std::min<u32>(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes);
1682 } 1717 }
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 3a1164d4f..a4bb0c41c 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -885,7 +885,7 @@ private:
885 std::set<Sampler> used_samplers; 885 std::set<Sampler> used_samplers;
886 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; 886 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{};
887 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; 887 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory;
888 bool use_physical_attributes = true; // Shader uses AL2P 888 bool use_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes
889 889
890 Tegra::Shader::Header header; 890 Tegra::Shader::Header header;
891}; 891};