summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-03-06 05:10:39 -0300
committerGravatar ReinUsesLisp2020-03-13 18:33:05 -0300
commitb67360c0f86c8acc1e56547382f07f35039fbcbf (patch)
treeed52c58ccbf4a29045bd312fe115805b5122b37a /src
parentvk_device: Enable VK_EXT_transform_feedback when available (diff)
downloadyuzu-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.cpp105
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
99struct GenericVaryingDescription {
100 Id id = nullptr;
101 u32 first_element = 0;
102 bool is_scalar = false;
103};
104
97spv::Dim GetSamplerDim(const Sampler& sampler) { 105spv::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;