summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/engines/maxwell_3d.h2
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp35
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h99
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp28
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp20
6 files changed, 85 insertions, 101 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 5cf6a4cc3..59d5752d2 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -1149,7 +1149,7 @@ public:
1149 1149
1150 /// Returns whether the vertex array specified by index is supposed to be 1150 /// Returns whether the vertex array specified by index is supposed to be
1151 /// accessed per instance or not. 1151 /// accessed per instance or not.
1152 bool IsInstancingEnabled(u32 index) const { 1152 bool IsInstancingEnabled(std::size_t index) const {
1153 return is_instanced[index]; 1153 return is_instanced[index];
1154 } 1154 }
1155 } instanced_arrays; 1155 } instanced_arrays;
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index 2bb376555..97aab951a 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -6,6 +6,7 @@
6 6
7#include <boost/functional/hash.hpp> 7#include <boost/functional/hash.hpp>
8 8
9#include "common/cityhash.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "video_core/renderer_vulkan/fixed_pipeline_state.h" 11#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
11 12
@@ -128,25 +129,6 @@ constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs)
128 129
129} // Anonymous namespace 130} // Anonymous namespace
130 131
131std::size_t FixedPipelineState::VertexBinding::Hash() const noexcept {
132 return (index << stride) ^ divisor;
133}
134
135bool FixedPipelineState::VertexBinding::operator==(const VertexBinding& rhs) const noexcept {
136 return std::tie(index, stride, divisor) == std::tie(rhs.index, rhs.stride, rhs.divisor);
137}
138
139std::size_t FixedPipelineState::VertexAttribute::Hash() const noexcept {
140 return static_cast<std::size_t>(index) ^ (static_cast<std::size_t>(buffer) << 13) ^
141 (static_cast<std::size_t>(type) << 22) ^ (static_cast<std::size_t>(size) << 31) ^
142 (static_cast<std::size_t>(offset) << 36);
143}
144
145bool FixedPipelineState::VertexAttribute::operator==(const VertexAttribute& rhs) const noexcept {
146 return std::tie(index, buffer, type, size, offset) ==
147 std::tie(rhs.index, rhs.buffer, rhs.type, rhs.size, rhs.offset);
148}
149
150std::size_t FixedPipelineState::StencilFace::Hash() const noexcept { 132std::size_t FixedPipelineState::StencilFace::Hash() const noexcept {
151 return static_cast<std::size_t>(action_stencil_fail) ^ 133 return static_cast<std::size_t>(action_stencil_fail) ^
152 (static_cast<std::size_t>(action_depth_fail) << 4) ^ 134 (static_cast<std::size_t>(action_depth_fail) << 4) ^
@@ -182,21 +164,12 @@ bool FixedPipelineState::BlendingAttachment::operator==(const BlendingAttachment
182} 164}
183 165
184std::size_t FixedPipelineState::VertexInput::Hash() const noexcept { 166std::size_t FixedPipelineState::VertexInput::Hash() const noexcept {
185 std::size_t hash = num_bindings ^ (num_attributes << 32); 167 // TODO(Rodrigo): Replace this
186 for (std::size_t i = 0; i < num_bindings; ++i) { 168 return Common::CityHash64(reinterpret_cast<const char*>(this), sizeof *this);
187 boost::hash_combine(hash, bindings[i].Hash());
188 }
189 for (std::size_t i = 0; i < num_attributes; ++i) {
190 boost::hash_combine(hash, attributes[i].Hash());
191 }
192 return hash;
193} 169}
194 170
195bool FixedPipelineState::VertexInput::operator==(const VertexInput& rhs) const noexcept { 171bool FixedPipelineState::VertexInput::operator==(const VertexInput& rhs) const noexcept {
196 return std::equal(bindings.begin(), bindings.begin() + num_bindings, rhs.bindings.begin(), 172 return std::memcmp(this, &rhs, sizeof *this) == 0;
197 rhs.bindings.begin() + rhs.num_bindings) &&
198 std::equal(attributes.begin(), attributes.begin() + num_attributes,
199 rhs.attributes.begin(), rhs.attributes.begin() + rhs.num_attributes);
200} 173}
201 174
202std::size_t FixedPipelineState::InputAssembly::Hash() const noexcept { 175std::size_t FixedPipelineState::InputAssembly::Hash() const noexcept {
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
index 4c8ba7f90..d82a82f75 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -7,6 +7,7 @@
7#include <array> 7#include <array>
8#include <type_traits> 8#include <type_traits>
9 9
10#include "common/bit_field.h"
10#include "common/common_types.h" 11#include "common/common_types.h"
11 12
12#include "video_core/engines/maxwell_3d.h" 13#include "video_core/engines/maxwell_3d.h"
@@ -18,48 +19,11 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs;
18 19
19// TODO(Rodrigo): Optimize this structure. 20// TODO(Rodrigo): Optimize this structure.
20 21
21struct FixedPipelineState { 22template <class T>
22 using PixelFormat = VideoCore::Surface::PixelFormat; 23inline constexpr bool IsHashable = std::has_unique_object_representations_v<T>&&
23 24 std::is_trivially_copyable_v<T>&& std::is_trivially_constructible_v<T>;
24 struct VertexBinding {
25 constexpr VertexBinding(u32 index, u32 stride, u32 divisor)
26 : index{index}, stride{stride}, divisor{divisor} {}
27 VertexBinding() = default;
28
29 u32 index;
30 u32 stride;
31 u32 divisor;
32
33 std::size_t Hash() const noexcept;
34
35 bool operator==(const VertexBinding& rhs) const noexcept;
36
37 bool operator!=(const VertexBinding& rhs) const noexcept {
38 return !operator==(rhs);
39 }
40 };
41
42 struct VertexAttribute {
43 constexpr VertexAttribute(u32 index, u32 buffer, Maxwell::VertexAttribute::Type type,
44 Maxwell::VertexAttribute::Size size, u32 offset)
45 : index{index}, buffer{buffer}, type{type}, size{size}, offset{offset} {}
46 VertexAttribute() = default;
47
48 u32 index;
49 u32 buffer;
50 Maxwell::VertexAttribute::Type type;
51 Maxwell::VertexAttribute::Size size;
52 u32 offset;
53
54 std::size_t Hash() const noexcept;
55
56 bool operator==(const VertexAttribute& rhs) const noexcept;
57
58 bool operator!=(const VertexAttribute& rhs) const noexcept {
59 return !operator==(rhs);
60 }
61 };
62 25
26struct FixedPipelineState {
63 struct StencilFace { 27 struct StencilFace {
64 constexpr StencilFace(Maxwell::StencilOp action_stencil_fail, 28 constexpr StencilFace(Maxwell::StencilOp action_stencil_fail,
65 Maxwell::StencilOp action_depth_fail, 29 Maxwell::StencilOp action_depth_fail,
@@ -114,10 +78,52 @@ struct FixedPipelineState {
114 }; 78 };
115 79
116 struct VertexInput { 80 struct VertexInput {
117 std::size_t num_bindings = 0; 81 union Binding {
118 std::size_t num_attributes = 0; 82 u16 raw;
119 std::array<VertexBinding, Maxwell::NumVertexArrays> bindings; 83 BitField<0, 1, u16> enabled;
120 std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes; 84 BitField<1, 12, u16> stride;
85 };
86
87 union Attribute {
88 u32 raw;
89 BitField<0, 1, u32> enabled;
90 BitField<1, 5, u32> buffer;
91 BitField<6, 14, u32> offset;
92 BitField<20, 3, u32> type;
93 BitField<23, 6, u32> size;
94
95 constexpr Maxwell::VertexAttribute::Type Type() const noexcept {
96 return static_cast<Maxwell::VertexAttribute::Type>(type.Value());
97 }
98
99 constexpr Maxwell::VertexAttribute::Size Size() const noexcept {
100 return static_cast<Maxwell::VertexAttribute::Size>(size.Value());
101 }
102 };
103
104 std::array<Binding, Maxwell::NumVertexArrays> bindings;
105 std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
106 std::array<Attribute, Maxwell::NumVertexAttributes> attributes;
107
108 void SetBinding(std::size_t index, bool enabled, u32 stride, u32 divisor) noexcept {
109 auto& binding = bindings[index];
110 binding.raw = 0;
111 binding.enabled.Assign(enabled ? 1 : 0);
112 binding.stride.Assign(stride);
113 binding_divisors[index] = divisor;
114 }
115
116 void SetAttribute(std::size_t index, bool enabled, u32 buffer, u32 offset,
117 Maxwell::VertexAttribute::Type type,
118 Maxwell::VertexAttribute::Size size) noexcept {
119 auto& attribute = attributes[index];
120 attribute.raw = 0;
121 attribute.enabled.Assign(enabled ? 1 : 0);
122 attribute.buffer.Assign(buffer);
123 attribute.offset.Assign(offset);
124 attribute.type.Assign(static_cast<u32>(type));
125 attribute.size.Assign(static_cast<u32>(size));
126 }
121 127
122 std::size_t Hash() const noexcept; 128 std::size_t Hash() const noexcept;
123 129
@@ -127,6 +133,7 @@ struct FixedPipelineState {
127 return !operator==(rhs); 133 return !operator==(rhs);
128 } 134 }
129 }; 135 };
136 static_assert(IsHashable<VertexInput>);
130 137
131 struct InputAssembly { 138 struct InputAssembly {
132 constexpr InputAssembly(Maxwell::PrimitiveTopology topology, bool primitive_restart_enable, 139 constexpr InputAssembly(Maxwell::PrimitiveTopology topology, bool primitive_restart_enable,
@@ -256,8 +263,6 @@ struct FixedPipelineState {
256 DepthStencil depth_stencil; 263 DepthStencil depth_stencil;
257 ColorBlending color_blending; 264 ColorBlending color_blending;
258}; 265};
259static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexBinding>);
260static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexAttribute>);
261static_assert(std::is_trivially_copyable_v<FixedPipelineState::StencilFace>); 266static_assert(std::is_trivially_copyable_v<FixedPipelineState::StencilFace>);
262static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>); 267static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>);
263static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>); 268static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>);
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index b540b838d..718feafbd 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -165,35 +165,41 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
165 165
166 std::vector<VkVertexInputBindingDescription> vertex_bindings; 166 std::vector<VkVertexInputBindingDescription> vertex_bindings;
167 std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors; 167 std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors;
168 for (std::size_t i = 0; i < vi.num_bindings; ++i) { 168 for (std::size_t index = 0; index < std::size(vi.bindings); ++index) {
169 const auto& binding = vi.bindings[i]; 169 const auto& binding = vi.bindings[index];
170 const bool instanced = binding.divisor != 0; 170 if (!binding.enabled) {
171 continue;
172 }
173 const bool instanced = vi.binding_divisors[index] != 0;
171 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; 174 const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
172 175
173 auto& vertex_binding = vertex_bindings.emplace_back(); 176 auto& vertex_binding = vertex_bindings.emplace_back();
174 vertex_binding.binding = binding.index; 177 vertex_binding.binding = static_cast<u32>(index);
175 vertex_binding.stride = binding.stride; 178 vertex_binding.stride = binding.stride;
176 vertex_binding.inputRate = rate; 179 vertex_binding.inputRate = rate;
177 180
178 if (instanced) { 181 if (instanced) {
179 auto& binding_divisor = vertex_binding_divisors.emplace_back(); 182 auto& binding_divisor = vertex_binding_divisors.emplace_back();
180 binding_divisor.binding = binding.index; 183 binding_divisor.binding = static_cast<u32>(index);
181 binding_divisor.divisor = binding.divisor; 184 binding_divisor.divisor = vi.binding_divisors[index];
182 } 185 }
183 } 186 }
184 187
185 std::vector<VkVertexInputAttributeDescription> vertex_attributes; 188 std::vector<VkVertexInputAttributeDescription> vertex_attributes;
186 const auto& input_attributes = program[0]->entries.attributes; 189 const auto& input_attributes = program[0]->entries.attributes;
187 for (std::size_t i = 0; i < vi.num_attributes; ++i) { 190 for (std::size_t index = 0; index < std::size(vi.attributes); ++index) {
188 const auto& attribute = vi.attributes[i]; 191 const auto& attribute = vi.attributes[index];
189 if (input_attributes.find(attribute.index) == input_attributes.end()) { 192 if (!attribute.enabled) {
193 continue;
194 }
195 if (input_attributes.find(static_cast<u32>(index)) == input_attributes.end()) {
190 // Skip attributes not used by the vertex shaders. 196 // Skip attributes not used by the vertex shaders.
191 continue; 197 continue;
192 } 198 }
193 auto& vertex_attribute = vertex_attributes.emplace_back(); 199 auto& vertex_attribute = vertex_attributes.emplace_back();
194 vertex_attribute.location = attribute.index; 200 vertex_attribute.location = static_cast<u32>(index);
195 vertex_attribute.binding = attribute.buffer; 201 vertex_attribute.binding = attribute.buffer;
196 vertex_attribute.format = MaxwellToVK::VertexFormat(attribute.type, attribute.size); 202 vertex_attribute.format = MaxwellToVK::VertexFormat(attribute.Type(), attribute.Size());
197 vertex_attribute.offset = attribute.offset; 203 vertex_attribute.offset = attribute.offset;
198 } 204 }
199 205
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 90e3a8edd..083da9999 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -334,7 +334,7 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
334 specialization.point_size = fixed_state.input_assembly.point_size; 334 specialization.point_size = fixed_state.input_assembly.point_size;
335 } 335 }
336 for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) { 336 for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) {
337 specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].type; 337 specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].Type();
338 } 338 }
339 specialization.ndc_minus_one_to_one = fixed_state.rasterizer.ndc_minus_one_to_one; 339 specialization.ndc_minus_one_to_one = fixed_state.rasterizer.ndc_minus_one_to_one;
340 340
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 4ca0febb8..7a6aa52bc 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -806,25 +806,29 @@ void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex
806 BufferBindings& buffer_bindings) { 806 BufferBindings& buffer_bindings) {
807 const auto& regs = system.GPU().Maxwell3D().regs; 807 const auto& regs = system.GPU().Maxwell3D().regs;
808 808
809 for (u32 index = 0; index < static_cast<u32>(Maxwell::NumVertexAttributes); ++index) { 809 for (std::size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
810 const auto& attrib = regs.vertex_attrib_format[index]; 810 const auto& attrib = regs.vertex_attrib_format[index];
811 if (!attrib.IsValid()) { 811 if (!attrib.IsValid()) {
812 vertex_input.SetAttribute(index, false, 0, 0, {}, {});
812 continue; 813 continue;
813 } 814 }
814 815
815 const auto& buffer = regs.vertex_array[attrib.buffer]; 816 [[maybe_unused]] const auto& buffer = regs.vertex_array[attrib.buffer];
816 ASSERT(buffer.IsEnabled()); 817 ASSERT(buffer.IsEnabled());
817 818
818 vertex_input.attributes[vertex_input.num_attributes++] = 819 vertex_input.SetAttribute(index, true, attrib.buffer, attrib.offset, attrib.type.Value(),
819 FixedPipelineState::VertexAttribute(index, attrib.buffer, attrib.type, attrib.size, 820 attrib.size.Value());
820 attrib.offset);
821 } 821 }
822 822
823 for (u32 index = 0; index < static_cast<u32>(Maxwell::NumVertexArrays); ++index) { 823 for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
824 const auto& vertex_array = regs.vertex_array[index]; 824 const auto& vertex_array = regs.vertex_array[index];
825 if (!vertex_array.IsEnabled()) { 825 if (!vertex_array.IsEnabled()) {
826 vertex_input.SetBinding(index, false, 0, 0);
826 continue; 827 continue;
827 } 828 }
829 vertex_input.SetBinding(
830 index, true, vertex_array.stride,
831 regs.instanced_arrays.IsInstancingEnabled(index) ? vertex_array.divisor : 0);
828 832
829 const GPUVAddr start{vertex_array.StartAddress()}; 833 const GPUVAddr start{vertex_array.StartAddress()};
830 const GPUVAddr end{regs.vertex_array_limit[index].LimitAddress()}; 834 const GPUVAddr end{regs.vertex_array_limit[index].LimitAddress()};
@@ -832,10 +836,6 @@ void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex
832 ASSERT(end > start); 836 ASSERT(end > start);
833 const std::size_t size{end - start + 1}; 837 const std::size_t size{end - start + 1};
834 const auto [buffer, offset] = buffer_cache.UploadMemory(start, size); 838 const auto [buffer, offset] = buffer_cache.UploadMemory(start, size);
835
836 vertex_input.bindings[vertex_input.num_bindings++] = FixedPipelineState::VertexBinding(
837 index, vertex_array.stride,
838 regs.instanced_arrays.IsInstancingEnabled(index) ? vertex_array.divisor : 0);
839 buffer_bindings.AddVertexBinding(buffer, offset); 839 buffer_bindings.AddVertexBinding(buffer, offset);
840 } 840 }
841} 841}