diff options
| author | 2020-03-06 05:10:39 -0300 | |
|---|---|---|
| committer | 2020-03-13 18:33:05 -0300 | |
| commit | b67360c0f86c8acc1e56547382f07f35039fbcbf (patch) | |
| tree | ed52c58ccbf4a29045bd312fe115805b5122b37a /src | |
| parent | vk_device: Enable VK_EXT_transform_feedback when available (diff) | |
| download | yuzu-b67360c0f86c8acc1e56547382f07f35039fbcbf.tar.gz yuzu-b67360c0f86c8acc1e56547382f07f35039fbcbf.tar.xz yuzu-b67360c0f86c8acc1e56547382f07f35039fbcbf.zip | |
vk_shader_decompiler: Add XFB decorations to generic varyings
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 105 |
1 files changed, 89 insertions, 16 deletions
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 802fe8747..3117a8d74 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -5,7 +5,9 @@ | |||
| 5 | #include <functional> | 5 | #include <functional> |
| 6 | #include <limits> | 6 | #include <limits> |
| 7 | #include <map> | 7 | #include <map> |
| 8 | #include <optional> | ||
| 8 | #include <type_traits> | 9 | #include <type_traits> |
| 10 | #include <unordered_map> | ||
| 9 | #include <utility> | 11 | #include <utility> |
| 10 | 12 | ||
| 11 | #include <fmt/format.h> | 13 | #include <fmt/format.h> |
| @@ -94,6 +96,12 @@ struct VertexIndices { | |||
| 94 | std::optional<u32> clip_distances; | 96 | std::optional<u32> clip_distances; |
| 95 | }; | 97 | }; |
| 96 | 98 | ||
| 99 | struct GenericVaryingDescription { | ||
| 100 | Id id = nullptr; | ||
| 101 | u32 first_element = 0; | ||
| 102 | bool is_scalar = false; | ||
| 103 | }; | ||
| 104 | |||
| 97 | spv::Dim GetSamplerDim(const Sampler& sampler) { | 105 | spv::Dim GetSamplerDim(const Sampler& sampler) { |
| 98 | ASSERT(!sampler.IsBuffer()); | 106 | ASSERT(!sampler.IsBuffer()); |
| 99 | switch (sampler.GetType()) { | 107 | switch (sampler.GetType()) { |
| @@ -288,6 +296,15 @@ public: | |||
| 288 | AddExtension("SPV_KHR_variable_pointers"); | 296 | AddExtension("SPV_KHR_variable_pointers"); |
| 289 | AddExtension("SPV_KHR_shader_draw_parameters"); | 297 | AddExtension("SPV_KHR_shader_draw_parameters"); |
| 290 | 298 | ||
| 299 | if (!transform_feedback.empty()) { | ||
| 300 | if (device.IsExtTransformFeedbackSupported()) { | ||
| 301 | AddCapability(spv::Capability::TransformFeedback); | ||
| 302 | } else { | ||
| 303 | LOG_ERROR(Render_Vulkan, "Shader requires transform feedbacks but these are not " | ||
| 304 | "supported on this device"); | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 291 | if (ir.UsesLayer() || ir.UsesViewportIndex()) { | 308 | if (ir.UsesLayer() || ir.UsesViewportIndex()) { |
| 292 | if (ir.UsesViewportIndex()) { | 309 | if (ir.UsesViewportIndex()) { |
| 293 | AddCapability(spv::Capability::MultiViewport); | 310 | AddCapability(spv::Capability::MultiViewport); |
| @@ -406,7 +423,7 @@ private: | |||
| 406 | // Clear Position to avoid reading trash on the Z conversion. | 423 | // Clear Position to avoid reading trash on the Z conversion. |
| 407 | const auto position_index = out_indices.position.value(); | 424 | const auto position_index = out_indices.position.value(); |
| 408 | const Id position = AccessElement(t_out_float4, out_vertex, position_index); | 425 | const Id position = AccessElement(t_out_float4, out_vertex, position_index); |
| 409 | OpStore(position, v_varying_default); | 426 | OpStore(position, ConstantNull(t_float4)); |
| 410 | 427 | ||
| 411 | if (specialization.point_size) { | 428 | if (specialization.point_size) { |
| 412 | const u32 point_size_index = out_indices.point_size.value(); | 429 | const u32 point_size_index = out_indices.point_size.value(); |
| @@ -749,13 +766,35 @@ private: | |||
| 749 | } | 766 | } |
| 750 | 767 | ||
| 751 | void DeclareOutputAttributes() { | 768 | void DeclareOutputAttributes() { |
| 769 | if (stage == ShaderType::Compute || stage == ShaderType::Fragment) { | ||
| 770 | return; | ||
| 771 | } | ||
| 772 | |||
| 773 | UNIMPLEMENTED_IF(registry.GetGraphicsInfo().tfb_enabled && stage != ShaderType::Vertex); | ||
| 752 | for (const auto index : ir.GetOutputAttributes()) { | 774 | for (const auto index : ir.GetOutputAttributes()) { |
| 753 | if (!IsGenericAttribute(index)) { | 775 | if (!IsGenericAttribute(index)) { |
| 754 | continue; | 776 | continue; |
| 755 | } | 777 | } |
| 756 | const u32 location = GetGenericAttributeLocation(index); | 778 | DeclareOutputAttribute(index); |
| 757 | Id type = t_float4; | 779 | } |
| 758 | Id varying_default = v_varying_default; | 780 | } |
| 781 | |||
| 782 | void DeclareOutputAttribute(Attribute::Index index) { | ||
| 783 | static constexpr std::string_view swizzle = "xyzw"; | ||
| 784 | |||
| 785 | const u32 location = GetGenericAttributeLocation(index); | ||
| 786 | u8 element = 0; | ||
| 787 | while (element < 4) { | ||
| 788 | const std::size_t remainder = 4 - element; | ||
| 789 | |||
| 790 | std::size_t num_components = remainder; | ||
| 791 | const std::optional tfb = GetTransformFeedbackInfo(index, element); | ||
| 792 | if (tfb) { | ||
| 793 | num_components = tfb->components; | ||
| 794 | } | ||
| 795 | |||
| 796 | Id type = GetTypeVectorDefinitionLut(Type::Float).at(num_components - 1); | ||
| 797 | Id varying_default = ConstantNull(type); | ||
| 759 | if (IsOutputAttributeArray()) { | 798 | if (IsOutputAttributeArray()) { |
| 760 | const u32 num = GetNumOutputVertices(); | 799 | const u32 num = GetNumOutputVertices(); |
| 761 | type = TypeArray(type, Constant(t_uint, num)); | 800 | type = TypeArray(type, Constant(t_uint, num)); |
| @@ -767,15 +806,47 @@ private: | |||
| 767 | } | 806 | } |
| 768 | type = TypePointer(spv::StorageClass::Output, type); | 807 | type = TypePointer(spv::StorageClass::Output, type); |
| 769 | 808 | ||
| 809 | std::string name = fmt::format("out_attr{}", location); | ||
| 810 | if (num_components < 4 || element > 0) { | ||
| 811 | name = fmt::format("{}_{}", name, swizzle.substr(element, num_components)); | ||
| 812 | } | ||
| 813 | |||
| 770 | const Id id = OpVariable(type, spv::StorageClass::Output, varying_default); | 814 | const Id id = OpVariable(type, spv::StorageClass::Output, varying_default); |
| 771 | Name(AddGlobalVariable(id), fmt::format("out_attr{}", location)); | 815 | Name(AddGlobalVariable(id), name); |
| 772 | output_attributes.emplace(index, id); | 816 | |
| 817 | GenericVaryingDescription description; | ||
| 818 | description.id = id; | ||
| 819 | description.first_element = element; | ||
| 820 | description.is_scalar = num_components == 1; | ||
| 821 | for (u32 i = 0; i < num_components; ++i) { | ||
| 822 | const u8 offset = static_cast<u8>(static_cast<u32>(index) * 4 + element + i); | ||
| 823 | output_attributes.emplace(offset, description); | ||
| 824 | } | ||
| 773 | interfaces.push_back(id); | 825 | interfaces.push_back(id); |
| 774 | 826 | ||
| 775 | Decorate(id, spv::Decoration::Location, location); | 827 | Decorate(id, spv::Decoration::Location, location); |
| 828 | if (element > 0) { | ||
| 829 | Decorate(id, spv::Decoration::Component, static_cast<u32>(element)); | ||
| 830 | } | ||
| 831 | if (tfb && device.IsExtTransformFeedbackSupported()) { | ||
| 832 | Decorate(id, spv::Decoration::XfbBuffer, static_cast<u32>(tfb->buffer)); | ||
| 833 | Decorate(id, spv::Decoration::XfbStride, static_cast<u32>(tfb->stride)); | ||
| 834 | Decorate(id, spv::Decoration::Offset, static_cast<u32>(tfb->offset)); | ||
| 835 | } | ||
| 836 | |||
| 837 | element += static_cast<u8>(num_components); | ||
| 776 | } | 838 | } |
| 777 | } | 839 | } |
| 778 | 840 | ||
| 841 | std::optional<VaryingTFB> GetTransformFeedbackInfo(Attribute::Index index, u8 element = 0) { | ||
| 842 | const u8 location = static_cast<u8>(index) * 4 + element; | ||
| 843 | const auto it = transform_feedback.find(location); | ||
| 844 | if (it == transform_feedback.end()) { | ||
| 845 | return {}; | ||
| 846 | } | ||
| 847 | return it->second; | ||
| 848 | } | ||
| 849 | |||
| 779 | u32 DeclareConstantBuffers(u32 binding) { | 850 | u32 DeclareConstantBuffers(u32 binding) { |
| 780 | for (const auto& [index, size] : ir.GetConstantBuffers()) { | 851 | for (const auto& [index, size] : ir.GetConstantBuffers()) { |
| 781 | const Id type = device.IsKhrUniformBufferStandardLayoutSupported() ? t_cbuf_scalar_ubo | 852 | const Id type = device.IsKhrUniformBufferStandardLayoutSupported() ? t_cbuf_scalar_ubo |
| @@ -1353,8 +1424,14 @@ private: | |||
| 1353 | } | 1424 | } |
| 1354 | default: | 1425 | default: |
| 1355 | if (IsGenericAttribute(attribute)) { | 1426 | if (IsGenericAttribute(attribute)) { |
| 1356 | const Id composite = output_attributes.at(attribute); | 1427 | const u8 offset = static_cast<u8>(static_cast<u8>(attribute) * 4 + element); |
| 1357 | return {ArrayPass(t_out_float, composite, {element}), Type::Float}; | 1428 | const GenericVaryingDescription description = output_attributes.at(offset); |
| 1429 | const Id composite = description.id; | ||
| 1430 | std::vector<u32> indices; | ||
| 1431 | if (!description.is_scalar) { | ||
| 1432 | indices.push_back(element - description.first_element); | ||
| 1433 | } | ||
| 1434 | return {ArrayPass(t_out_float, composite, indices), Type::Float}; | ||
| 1358 | } | 1435 | } |
| 1359 | UNIMPLEMENTED_MSG("Unhandled output attribute: {}", | 1436 | UNIMPLEMENTED_MSG("Unhandled output attribute: {}", |
| 1360 | static_cast<u32>(attribute)); | 1437 | static_cast<u32>(attribute)); |
| @@ -2265,11 +2342,11 @@ private: | |||
| 2265 | std::array<Id, 4> GetTypeVectorDefinitionLut(Type type) const { | 2342 | std::array<Id, 4> GetTypeVectorDefinitionLut(Type type) const { |
| 2266 | switch (type) { | 2343 | switch (type) { |
| 2267 | case Type::Float: | 2344 | case Type::Float: |
| 2268 | return {nullptr, t_float2, t_float3, t_float4}; | 2345 | return {t_float, t_float2, t_float3, t_float4}; |
| 2269 | case Type::Int: | 2346 | case Type::Int: |
| 2270 | return {nullptr, t_int2, t_int3, t_int4}; | 2347 | return {t_int, t_int2, t_int3, t_int4}; |
| 2271 | case Type::Uint: | 2348 | case Type::Uint: |
| 2272 | return {nullptr, t_uint2, t_uint3, t_uint4}; | 2349 | return {t_uint, t_uint2, t_uint3, t_uint4}; |
| 2273 | default: | 2350 | default: |
| 2274 | UNIMPLEMENTED(); | 2351 | UNIMPLEMENTED(); |
| 2275 | return {}; | 2352 | return {}; |
| @@ -2573,10 +2650,6 @@ private: | |||
| 2573 | const Id v_float_zero = Constant(t_float, 0.0f); | 2650 | const Id v_float_zero = Constant(t_float, 0.0f); |
| 2574 | const Id v_float_one = Constant(t_float, 1.0f); | 2651 | const Id v_float_one = Constant(t_float, 1.0f); |
| 2575 | 2652 | ||
| 2576 | // Nvidia uses these defaults for varyings (e.g. position and generic attributes) | ||
| 2577 | const Id v_varying_default = | ||
| 2578 | ConstantComposite(t_float4, v_float_zero, v_float_zero, v_float_zero, v_float_one); | ||
| 2579 | |||
| 2580 | const Id v_true = ConstantTrue(t_bool); | 2653 | const Id v_true = ConstantTrue(t_bool); |
| 2581 | const Id v_false = ConstantFalse(t_bool); | 2654 | const Id v_false = ConstantFalse(t_bool); |
| 2582 | 2655 | ||
| @@ -2593,7 +2666,7 @@ private: | |||
| 2593 | Id shared_memory{}; | 2666 | Id shared_memory{}; |
| 2594 | std::array<Id, INTERNAL_FLAGS_COUNT> internal_flags{}; | 2667 | std::array<Id, INTERNAL_FLAGS_COUNT> internal_flags{}; |
| 2595 | std::map<Attribute::Index, Id> input_attributes; | 2668 | std::map<Attribute::Index, Id> input_attributes; |
| 2596 | std::map<Attribute::Index, Id> output_attributes; | 2669 | std::unordered_map<u8, GenericVaryingDescription> output_attributes; |
| 2597 | std::map<u32, Id> constant_buffers; | 2670 | std::map<u32, Id> constant_buffers; |
| 2598 | std::map<GlobalMemoryBase, Id> global_buffers; | 2671 | std::map<GlobalMemoryBase, Id> global_buffers; |
| 2599 | std::map<u32, TexelBuffer> texel_buffers; | 2672 | std::map<u32, TexelBuffer> texel_buffers; |