diff options
| author | 2019-12-22 12:36:56 -0400 | |
|---|---|---|
| committer | 2019-12-22 12:36:56 -0400 | |
| commit | 3dc585d011af857d853adb124d64b743cc1e6d24 (patch) | |
| tree | ce84ad9f5023c31c1d1c6a52e026e817ee51f9e5 | |
| parent | Merge pull request #3230 from ReinUsesLisp/vk-emu-shaders (diff) | |
| parent | vk_shader_decompiler: Fix full decompilation (diff) | |
| download | yuzu-3dc585d011af857d853adb124d64b743cc1e6d24.tar.gz yuzu-3dc585d011af857d853adb124d64b743cc1e6d24.tar.xz yuzu-3dc585d011af857d853adb124d64b743cc1e6d24.zip | |
Merge pull request #3237 from ReinUsesLisp/vk-shader-decompiler
vk_shader_decompiler: Misc changes
| m--------- | externals/sirit | 0 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 83 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.h | 4 |
3 files changed, 49 insertions, 38 deletions
diff --git a/externals/sirit b/externals/sirit | |||
| Subproject 12f40a80324d7c154f19f25c448a5ce27d38cd1 | Subproject 9f4d057aa28c4e9509bdc767afb27b4aee303b7 | ||
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index fae8c95c8..a8baf91de 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -543,7 +543,7 @@ private: | |||
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | for (u32 rt = 0; rt < static_cast<u32>(frag_colors.size()); ++rt) { | 545 | for (u32 rt = 0; rt < static_cast<u32>(frag_colors.size()); ++rt) { |
| 546 | if (!IsRenderTargetUsed(rt)) { | 546 | if (!specialization.enabled_rendertargets[rt]) { |
| 547 | continue; | 547 | continue; |
| 548 | } | 548 | } |
| 549 | 549 | ||
| @@ -1555,40 +1555,48 @@ private: | |||
| 1555 | 1555 | ||
| 1556 | Expression Texture(Operation operation) { | 1556 | Expression Texture(Operation operation) { |
| 1557 | const auto& meta = std::get<MetaTexture>(operation.GetMeta()); | 1557 | const auto& meta = std::get<MetaTexture>(operation.GetMeta()); |
| 1558 | UNIMPLEMENTED_IF(!meta.aoffi.empty()); | ||
| 1559 | 1558 | ||
| 1560 | const bool can_implicit = stage == ShaderType::Fragment; | 1559 | const bool can_implicit = stage == ShaderType::Fragment; |
| 1561 | const Id sampler = GetTextureSampler(operation); | 1560 | const Id sampler = GetTextureSampler(operation); |
| 1562 | const Id coords = GetCoordinates(operation, Type::Float); | 1561 | const Id coords = GetCoordinates(operation, Type::Float); |
| 1563 | 1562 | ||
| 1563 | std::vector<Id> operands; | ||
| 1564 | spv::ImageOperandsMask mask{}; | ||
| 1565 | if (meta.bias) { | ||
| 1566 | mask = mask | spv::ImageOperandsMask::Bias; | ||
| 1567 | operands.push_back(AsFloat(Visit(meta.bias))); | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | if (!can_implicit) { | ||
| 1571 | mask = mask | spv::ImageOperandsMask::Lod; | ||
| 1572 | operands.push_back(v_float_zero); | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | if (!meta.aoffi.empty()) { | ||
| 1576 | mask = mask | spv::ImageOperandsMask::Offset; | ||
| 1577 | operands.push_back(GetOffsetCoordinates(operation)); | ||
| 1578 | } | ||
| 1579 | |||
| 1564 | if (meta.depth_compare) { | 1580 | if (meta.depth_compare) { |
| 1565 | // Depth sampling | 1581 | // Depth sampling |
| 1566 | UNIMPLEMENTED_IF(meta.bias); | 1582 | UNIMPLEMENTED_IF(meta.bias); |
| 1567 | const Id dref = AsFloat(Visit(meta.depth_compare)); | 1583 | const Id dref = AsFloat(Visit(meta.depth_compare)); |
| 1568 | if (can_implicit) { | 1584 | if (can_implicit) { |
| 1569 | return {OpImageSampleDrefImplicitLod(t_float, sampler, coords, dref, {}), | 1585 | return { |
| 1570 | Type::Float}; | 1586 | OpImageSampleDrefImplicitLod(t_float, sampler, coords, dref, mask, operands), |
| 1587 | Type::Float}; | ||
| 1571 | } else { | 1588 | } else { |
| 1572 | return {OpImageSampleDrefExplicitLod(t_float, sampler, coords, dref, | 1589 | return { |
| 1573 | spv::ImageOperandsMask::Lod, v_float_zero), | 1590 | OpImageSampleDrefExplicitLod(t_float, sampler, coords, dref, mask, operands), |
| 1574 | Type::Float}; | 1591 | Type::Float}; |
| 1575 | } | 1592 | } |
| 1576 | } | 1593 | } |
| 1577 | 1594 | ||
| 1578 | std::vector<Id> operands; | ||
| 1579 | spv::ImageOperandsMask mask{}; | ||
| 1580 | if (meta.bias) { | ||
| 1581 | mask = mask | spv::ImageOperandsMask::Bias; | ||
| 1582 | operands.push_back(AsFloat(Visit(meta.bias))); | ||
| 1583 | } | ||
| 1584 | |||
| 1585 | Id texture; | 1595 | Id texture; |
| 1586 | if (can_implicit) { | 1596 | if (can_implicit) { |
| 1587 | texture = OpImageSampleImplicitLod(t_float4, sampler, coords, mask, operands); | 1597 | texture = OpImageSampleImplicitLod(t_float4, sampler, coords, mask, operands); |
| 1588 | } else { | 1598 | } else { |
| 1589 | texture = OpImageSampleExplicitLod(t_float4, sampler, coords, | 1599 | texture = OpImageSampleExplicitLod(t_float4, sampler, coords, mask, operands); |
| 1590 | mask | spv::ImageOperandsMask::Lod, v_float_zero, | ||
| 1591 | operands); | ||
| 1592 | } | 1600 | } |
| 1593 | return GetTextureElement(operation, texture, Type::Float); | 1601 | return GetTextureElement(operation, texture, Type::Float); |
| 1594 | } | 1602 | } |
| @@ -1601,7 +1609,8 @@ private: | |||
| 1601 | const Id lod = AsFloat(Visit(meta.lod)); | 1609 | const Id lod = AsFloat(Visit(meta.lod)); |
| 1602 | 1610 | ||
| 1603 | spv::ImageOperandsMask mask = spv::ImageOperandsMask::Lod; | 1611 | spv::ImageOperandsMask mask = spv::ImageOperandsMask::Lod; |
| 1604 | std::vector<Id> operands; | 1612 | std::vector<Id> operands{lod}; |
| 1613 | |||
| 1605 | if (!meta.aoffi.empty()) { | 1614 | if (!meta.aoffi.empty()) { |
| 1606 | mask = mask | spv::ImageOperandsMask::Offset; | 1615 | mask = mask | spv::ImageOperandsMask::Offset; |
| 1607 | operands.push_back(GetOffsetCoordinates(operation)); | 1616 | operands.push_back(GetOffsetCoordinates(operation)); |
| @@ -1609,11 +1618,10 @@ private: | |||
| 1609 | 1618 | ||
| 1610 | if (meta.sampler.IsShadow()) { | 1619 | if (meta.sampler.IsShadow()) { |
| 1611 | const Id dref = AsFloat(Visit(meta.depth_compare)); | 1620 | const Id dref = AsFloat(Visit(meta.depth_compare)); |
| 1612 | return { | 1621 | return {OpImageSampleDrefExplicitLod(t_float, sampler, coords, dref, mask, operands), |
| 1613 | OpImageSampleDrefExplicitLod(t_float, sampler, coords, dref, mask, lod, operands), | 1622 | Type::Float}; |
| 1614 | Type::Float}; | ||
| 1615 | } | 1623 | } |
| 1616 | const Id texture = OpImageSampleExplicitLod(t_float4, sampler, coords, mask, lod, operands); | 1624 | const Id texture = OpImageSampleExplicitLod(t_float4, sampler, coords, mask, operands); |
| 1617 | return GetTextureElement(operation, texture, Type::Float); | 1625 | return GetTextureElement(operation, texture, Type::Float); |
| 1618 | } | 1626 | } |
| 1619 | 1627 | ||
| @@ -1722,7 +1730,7 @@ private: | |||
| 1722 | const std::vector grad = {dx, dy}; | 1730 | const std::vector grad = {dx, dy}; |
| 1723 | 1731 | ||
| 1724 | static constexpr auto mask = spv::ImageOperandsMask::Grad; | 1732 | static constexpr auto mask = spv::ImageOperandsMask::Grad; |
| 1725 | const Id texture = OpImageSampleImplicitLod(t_float4, sampler, coords, mask, grad); | 1733 | const Id texture = OpImageSampleExplicitLod(t_float4, sampler, coords, mask, grad); |
| 1726 | return GetTextureElement(operation, texture, Type::Float); | 1734 | return GetTextureElement(operation, texture, Type::Float); |
| 1727 | } | 1735 | } |
| 1728 | 1736 | ||
| @@ -1833,7 +1841,7 @@ private: | |||
| 1833 | } | 1841 | } |
| 1834 | 1842 | ||
| 1835 | void PreExit() { | 1843 | void PreExit() { |
| 1836 | if (stage == ShaderType::Vertex) { | 1844 | if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) { |
| 1837 | const u32 position_index = out_indices.position.value(); | 1845 | const u32 position_index = out_indices.position.value(); |
| 1838 | const Id z_pointer = AccessElement(t_out_float, out_vertex, position_index, 2U); | 1846 | const Id z_pointer = AccessElement(t_out_float, out_vertex, position_index, 2U); |
| 1839 | const Id w_pointer = AccessElement(t_out_float, out_vertex, position_index, 3U); | 1847 | const Id w_pointer = AccessElement(t_out_float, out_vertex, position_index, 3U); |
| @@ -1860,12 +1868,18 @@ private: | |||
| 1860 | // rendertargets/components are skipped in the register assignment. | 1868 | // rendertargets/components are skipped in the register assignment. |
| 1861 | u32 current_reg = 0; | 1869 | u32 current_reg = 0; |
| 1862 | for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { | 1870 | for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { |
| 1871 | if (!specialization.enabled_rendertargets[rt]) { | ||
| 1872 | // Skip rendertargets that are not enabled | ||
| 1873 | continue; | ||
| 1874 | } | ||
| 1863 | // TODO(Subv): Figure out how dual-source blending is configured in the Switch. | 1875 | // TODO(Subv): Figure out how dual-source blending is configured in the Switch. |
| 1864 | for (u32 component = 0; component < 4; ++component) { | 1876 | for (u32 component = 0; component < 4; ++component) { |
| 1877 | const Id pointer = AccessElement(t_out_float, frag_colors.at(rt), component); | ||
| 1865 | if (header.ps.IsColorComponentOutputEnabled(rt, component)) { | 1878 | if (header.ps.IsColorComponentOutputEnabled(rt, component)) { |
| 1866 | OpStore(AccessElement(t_out_float, frag_colors.at(rt), component), | 1879 | OpStore(pointer, SafeGetRegister(current_reg)); |
| 1867 | SafeGetRegister(current_reg)); | ||
| 1868 | ++current_reg; | 1880 | ++current_reg; |
| 1881 | } else { | ||
| 1882 | OpStore(pointer, component == 3 ? v_float_one : v_float_zero); | ||
| 1869 | } | 1883 | } |
| 1870 | } | 1884 | } |
| 1871 | } | 1885 | } |
| @@ -1995,15 +2009,6 @@ private: | |||
| 1995 | return DeclareBuiltIn(builtin, spv::StorageClass::Input, type, std::move(name)); | 2009 | return DeclareBuiltIn(builtin, spv::StorageClass::Input, type, std::move(name)); |
| 1996 | } | 2010 | } |
| 1997 | 2011 | ||
| 1998 | bool IsRenderTargetUsed(u32 rt) const { | ||
| 1999 | for (u32 component = 0; component < 4; ++component) { | ||
| 2000 | if (header.ps.IsColorComponentOutputEnabled(rt, component)) { | ||
| 2001 | return true; | ||
| 2002 | } | ||
| 2003 | } | ||
| 2004 | return false; | ||
| 2005 | } | ||
| 2006 | |||
| 2007 | template <typename... Args> | 2012 | template <typename... Args> |
| 2008 | Id AccessElement(Id pointer_type, Id composite, Args... elements_) { | 2013 | Id AccessElement(Id pointer_type, Id composite, Args... elements_) { |
| 2009 | std::vector<Id> members; | 2014 | std::vector<Id> members; |
| @@ -2567,7 +2572,7 @@ public: | |||
| 2567 | const Id target = decomp.Constant(decomp.t_uint, expr.value); | 2572 | const Id target = decomp.Constant(decomp.t_uint, expr.value); |
| 2568 | Id gpr = decomp.OpLoad(decomp.t_float, decomp.registers.at(expr.gpr)); | 2573 | Id gpr = decomp.OpLoad(decomp.t_float, decomp.registers.at(expr.gpr)); |
| 2569 | gpr = decomp.OpBitcast(decomp.t_uint, gpr); | 2574 | gpr = decomp.OpBitcast(decomp.t_uint, gpr); |
| 2570 | return decomp.OpLogicalEqual(decomp.t_uint, gpr, target); | 2575 | return decomp.OpIEqual(decomp.t_bool, gpr, target); |
| 2571 | } | 2576 | } |
| 2572 | 2577 | ||
| 2573 | Id Visit(const Expr& node) { | 2578 | Id Visit(const Expr& node) { |
| @@ -2637,11 +2642,11 @@ public: | |||
| 2637 | const Id loop_label = decomp.OpLabel(); | 2642 | const Id loop_label = decomp.OpLabel(); |
| 2638 | const Id endloop_label = decomp.OpLabel(); | 2643 | const Id endloop_label = decomp.OpLabel(); |
| 2639 | const Id loop_start_block = decomp.OpLabel(); | 2644 | const Id loop_start_block = decomp.OpLabel(); |
| 2640 | const Id loop_end_block = decomp.OpLabel(); | 2645 | const Id loop_continue_block = decomp.OpLabel(); |
| 2641 | current_loop_exit = endloop_label; | 2646 | current_loop_exit = endloop_label; |
| 2642 | decomp.OpBranch(loop_label); | 2647 | decomp.OpBranch(loop_label); |
| 2643 | decomp.AddLabel(loop_label); | 2648 | decomp.AddLabel(loop_label); |
| 2644 | decomp.OpLoopMerge(endloop_label, loop_end_block, spv::LoopControlMask::MaskNone); | 2649 | decomp.OpLoopMerge(endloop_label, loop_continue_block, spv::LoopControlMask::MaskNone); |
| 2645 | decomp.OpBranch(loop_start_block); | 2650 | decomp.OpBranch(loop_start_block); |
| 2646 | decomp.AddLabel(loop_start_block); | 2651 | decomp.AddLabel(loop_start_block); |
| 2647 | ASTNode current = ast.nodes.GetFirst(); | 2652 | ASTNode current = ast.nodes.GetFirst(); |
| @@ -2649,6 +2654,8 @@ public: | |||
| 2649 | Visit(current); | 2654 | Visit(current); |
| 2650 | current = current->GetNext(); | 2655 | current = current->GetNext(); |
| 2651 | } | 2656 | } |
| 2657 | decomp.OpBranch(loop_continue_block); | ||
| 2658 | decomp.AddLabel(loop_continue_block); | ||
| 2652 | ExprDecompiler expr_parser{decomp}; | 2659 | ExprDecompiler expr_parser{decomp}; |
| 2653 | const Id condition = expr_parser.Visit(ast.condition); | 2660 | const Id condition = expr_parser.Visit(ast.condition); |
| 2654 | decomp.OpBranchConditional(condition, loop_label, endloop_label); | 2661 | decomp.OpBranchConditional(condition, loop_label, endloop_label); |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.h b/src/video_core/renderer_vulkan/vk_shader_decompiler.h index 2b01321b6..10794be1c 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.h +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.h | |||
| @@ -94,6 +94,7 @@ struct Specialization final { | |||
| 94 | Maxwell::PrimitiveTopology primitive_topology{}; | 94 | Maxwell::PrimitiveTopology primitive_topology{}; |
| 95 | std::optional<float> point_size{}; | 95 | std::optional<float> point_size{}; |
| 96 | std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{}; | 96 | std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{}; |
| 97 | bool ndc_minus_one_to_one{}; | ||
| 97 | 98 | ||
| 98 | // Tessellation specific | 99 | // Tessellation specific |
| 99 | struct { | 100 | struct { |
| @@ -101,6 +102,9 @@ struct Specialization final { | |||
| 101 | Maxwell::TessellationSpacing spacing{}; | 102 | Maxwell::TessellationSpacing spacing{}; |
| 102 | bool clockwise{}; | 103 | bool clockwise{}; |
| 103 | } tessellation; | 104 | } tessellation; |
| 105 | |||
| 106 | // Fragment specific | ||
| 107 | std::bitset<8> enabled_rendertargets; | ||
| 104 | }; | 108 | }; |
| 105 | // Old gcc versions don't consider this trivially copyable. | 109 | // Old gcc versions don't consider this trivially copyable. |
| 106 | // static_assert(std::is_trivially_copyable_v<Specialization>); | 110 | // static_assert(std::is_trivially_copyable_v<Specialization>); |