summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp239
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.h22
2 files changed, 230 insertions, 31 deletions
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 100a5e07a..674226cb7 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -19,14 +19,24 @@
19#include "video_core/renderer_vulkan/vk_update_descriptor.h" 19#include "video_core/renderer_vulkan/vk_update_descriptor.h"
20#include "video_core/vulkan_common/vulkan_device.h" 20#include "video_core/vulkan_common/vulkan_device.h"
21 21
22#ifdef _MSC_VER
23#define LAMBDA_FORCEINLINE [[msvc::forceinline]]
24#else
25#define LAMBDA_FORCEINLINE
26#endif
27
22namespace Vulkan { 28namespace Vulkan {
23namespace { 29namespace {
24using boost::container::small_vector; 30using boost::container::small_vector;
25using boost::container::static_vector; 31using boost::container::static_vector;
32using Shader::ImageBufferDescriptor;
26using VideoCore::Surface::PixelFormat; 33using VideoCore::Surface::PixelFormat;
27using VideoCore::Surface::PixelFormatFromDepthFormat; 34using VideoCore::Surface::PixelFormatFromDepthFormat;
28using VideoCore::Surface::PixelFormatFromRenderTargetFormat; 35using VideoCore::Surface::PixelFormatFromRenderTargetFormat;
29 36
37constexpr size_t NUM_STAGES = Maxwell::MaxShaderStage;
38constexpr size_t MAX_IMAGE_ELEMENTS = 64;
39
30DescriptorLayoutBuilder MakeBuilder(const Device& device, std::span<const Shader::Info> infos) { 40DescriptorLayoutBuilder MakeBuilder(const Device& device, std::span<const Shader::Info> infos) {
31 DescriptorLayoutBuilder builder{device.GetLogical()}; 41 DescriptorLayoutBuilder builder{device.GetLogical()};
32 for (size_t index = 0; index < infos.size(); ++index) { 42 for (size_t index = 0; index < infos.size(); ++index) {
@@ -116,6 +126,80 @@ size_t NumAttachments(const FixedPipelineState& state) {
116 } 126 }
117 return num; 127 return num;
118} 128}
129
130template <typename Spec>
131bool Passes(const std::array<vk::ShaderModule, NUM_STAGES>& modules,
132 const std::array<Shader::Info, NUM_STAGES>& stage_infos) {
133 for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
134 if (!Spec::enabled_stages[stage] && modules[stage]) {
135 return false;
136 }
137 const auto& info{stage_infos[stage]};
138 if constexpr (!Spec::has_storage_buffers) {
139 if (!info.storage_buffers_descriptors.empty()) {
140 return false;
141 }
142 }
143 if constexpr (!Spec::has_texture_buffers) {
144 if (!info.texture_buffer_descriptors.empty()) {
145 return false;
146 }
147 }
148 if constexpr (!Spec::has_image_buffers) {
149 if (!info.image_buffer_descriptors.empty()) {
150 return false;
151 }
152 }
153 if constexpr (!Spec::has_images) {
154 if (!info.image_descriptors.empty()) {
155 return false;
156 }
157 }
158 }
159 return true;
160}
161
162using ConfigureFuncPtr = void (*)(GraphicsPipeline*, bool);
163
164template <typename Spec, typename... Specs>
165ConfigureFuncPtr FindSpec(const std::array<vk::ShaderModule, NUM_STAGES>& modules,
166 const std::array<Shader::Info, NUM_STAGES>& stage_infos) {
167 if constexpr (sizeof...(Specs) > 0) {
168 if (!Passes<Spec>(modules, stage_infos)) {
169 return FindSpec<Specs...>(modules, stage_infos);
170 }
171 }
172 return GraphicsPipeline::MakeConfigureSpecFunc<Spec>();
173}
174
175struct SimpleVertexFragmentSpec {
176 static constexpr std::array<bool, 5> enabled_stages{true, false, false, false, true};
177 static constexpr bool has_storage_buffers = false;
178 static constexpr bool has_texture_buffers = false;
179 static constexpr bool has_image_buffers = false;
180 static constexpr bool has_images = false;
181};
182
183struct SimpleVertexSpec {
184 static constexpr std::array<bool, 5> enabled_stages{true, false, false, false, false};
185 static constexpr bool has_storage_buffers = false;
186 static constexpr bool has_texture_buffers = false;
187 static constexpr bool has_image_buffers = false;
188 static constexpr bool has_images = false;
189};
190
191struct DefaultSpec {
192 static constexpr std::array<bool, 5> enabled_stages{true, true, true, true, true};
193 static constexpr bool has_storage_buffers = true;
194 static constexpr bool has_texture_buffers = true;
195 static constexpr bool has_image_buffers = true;
196 static constexpr bool has_images = true;
197};
198
199ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& modules,
200 const std::array<Shader::Info, NUM_STAGES>& infos) {
201 return FindSpec<SimpleVertexSpec, SimpleVertexFragmentSpec, DefaultSpec>(modules, infos);
202}
119} // Anonymous namespace 203} // Anonymous namespace
120 204
121GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_, 205GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
@@ -144,6 +228,7 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
144 descriptor_update_template = builder.CreateTemplate(set_layout, *pipeline_layout); 228 descriptor_update_template = builder.CreateTemplate(set_layout, *pipeline_layout);
145 229
146 const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(key.state))}; 230 const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(key.state))};
231 Validate();
147 MakePipeline(device, render_pass); 232 MakePipeline(device, render_pass);
148 233
149 std::lock_guard lock{build_mutex}; 234 std::lock_guard lock{build_mutex};
@@ -155,6 +240,7 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
155 } else { 240 } else {
156 func(); 241 func();
157 } 242 }
243 configure_func = ConfigureFunc(spv_modules, stage_infos);
158} 244}
159 245
160void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) { 246void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) {
@@ -162,26 +248,29 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) {
162 transitions.push_back(transition); 248 transitions.push_back(transition);
163} 249}
164 250
165void GraphicsPipeline::Configure(bool is_indexed) { 251template <typename Spec>
166 static constexpr size_t max_images_elements = 64; 252void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
167 std::array<ImageId, max_images_elements> image_view_ids; 253 std::array<ImageId, MAX_IMAGE_ELEMENTS> image_view_ids;
168 static_vector<u32, max_images_elements> image_view_indices; 254 std::array<u32, MAX_IMAGE_ELEMENTS> image_view_indices;
169 static_vector<VkSampler, max_images_elements> samplers; 255 std::array<VkSampler, MAX_IMAGE_ELEMENTS> samplers;
256 size_t image_index{};
170 257
171 texture_cache.SynchronizeGraphicsDescriptors(); 258 texture_cache.SynchronizeGraphicsDescriptors();
172 259
173 const auto& regs{maxwell3d.regs}; 260 const auto& regs{maxwell3d.regs};
174 const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; 261 const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
175 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { 262 const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
176 const Shader::Info& info{stage_infos[stage]}; 263 const Shader::Info& info{stage_infos[stage]};
177 buffer_cache.SetEnabledUniformBuffers(stage, info.constant_buffer_mask); 264 buffer_cache.SetEnabledUniformBuffers(stage, info.constant_buffer_mask);
178 buffer_cache.UnbindGraphicsStorageBuffers(stage); 265 buffer_cache.UnbindGraphicsStorageBuffers(stage);
179 size_t ssbo_index{}; 266 if constexpr (Spec::has_storage_buffers) {
180 for (const auto& desc : info.storage_buffers_descriptors) { 267 size_t ssbo_index{};
181 ASSERT(desc.count == 1); 268 for (const auto& desc : info.storage_buffers_descriptors) {
182 buffer_cache.BindGraphicsStorageBuffer(stage, ssbo_index, desc.cbuf_index, 269 ASSERT(desc.count == 1);
183 desc.cbuf_offset, desc.is_written); 270 buffer_cache.BindGraphicsStorageBuffer(stage, ssbo_index, desc.cbuf_index,
184 ++ssbo_index; 271 desc.cbuf_offset, desc.is_written);
272 ++ssbo_index;
273 }
185 } 274 }
186 const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers}; 275 const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers};
187 const auto read_handle{[&](const auto& desc, u32 index) { 276 const auto read_handle{[&](const auto& desc, u32 index) {
@@ -207,33 +296,60 @@ void GraphicsPipeline::Configure(bool is_indexed) {
207 const auto add_image{[&](const auto& desc) { 296 const auto add_image{[&](const auto& desc) {
208 for (u32 index = 0; index < desc.count; ++index) { 297 for (u32 index = 0; index < desc.count; ++index) {
209 const TextureHandle handle{read_handle(desc, index)}; 298 const TextureHandle handle{read_handle(desc, index)};
210 image_view_indices.push_back(handle.image); 299 image_view_indices[image_index++] = handle.image;
211 } 300 }
212 }}; 301 }};
213 std::ranges::for_each(info.texture_buffer_descriptors, add_image); 302 if constexpr (Spec::has_texture_buffers) {
214 std::ranges::for_each(info.image_buffer_descriptors, add_image); 303 for (const auto& desc : info.texture_buffer_descriptors) {
304 add_image(desc);
305 }
306 }
307 if constexpr (Spec::has_image_buffers) {
308 for (const auto& desc : info.image_buffer_descriptors) {
309 add_image(desc);
310 }
311 }
215 for (const auto& desc : info.texture_descriptors) { 312 for (const auto& desc : info.texture_descriptors) {
216 for (u32 index = 0; index < desc.count; ++index) { 313 for (u32 index = 0; index < desc.count; ++index) {
217 const TextureHandle handle{read_handle(desc, index)}; 314 const TextureHandle handle{read_handle(desc, index)};
218 image_view_indices.push_back(handle.image); 315 image_view_indices[image_index] = handle.image;
219 316
220 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; 317 Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)};
221 samplers.push_back(sampler->Handle()); 318 samplers[image_index] = sampler->Handle();
319 ++image_index;
320 }
321 }
322 if constexpr (Spec::has_images) {
323 for (const auto& desc : info.image_descriptors) {
324 add_image(desc);
222 } 325 }
223 } 326 }
224 std::ranges::for_each(info.image_descriptors, add_image); 327 }};
328 if constexpr (Spec::enabled_stages[0]) {
329 config_stage(0);
330 }
331 if constexpr (Spec::enabled_stages[1]) {
332 config_stage(1);
333 }
334 if constexpr (Spec::enabled_stages[2]) {
335 config_stage(2);
225 } 336 }
226 const std::span indices_span(image_view_indices.data(), image_view_indices.size()); 337 if constexpr (Spec::enabled_stages[3]) {
338 config_stage(3);
339 }
340 if constexpr (Spec::enabled_stages[4]) {
341 config_stage(4);
342 }
343 const std::span indices_span(image_view_indices.data(), image_index);
227 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); 344 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
228 345
229 ImageId* texture_buffer_index{image_view_ids.data()}; 346 ImageId* texture_buffer_index{image_view_ids.data()};
230 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { 347 const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE {
231 size_t index{}; 348 size_t index{};
232 const auto add_buffer{[&](const auto& desc) { 349 const auto add_buffer{[&](const auto& desc) {
233 for (u32 i = 0; i < desc.count; ++i) { 350 for (u32 i = 0; i < desc.count; ++i) {
234 bool is_written{false}; 351 bool is_written{false};
235 if constexpr (std::is_same_v<decltype(desc), 352 if constexpr (std::is_same_v<decltype(desc), const ImageBufferDescriptor&>) {
236 const Shader::ImageBufferDescriptor&>) {
237 is_written = desc.is_written; 353 is_written = desc.is_written;
238 } 354 }
239 ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)}; 355 ImageView& image_view{texture_cache.GetImageView(*texture_buffer_index)};
@@ -245,29 +361,75 @@ void GraphicsPipeline::Configure(bool is_indexed) {
245 } 361 }
246 }}; 362 }};
247 const Shader::Info& info{stage_infos[stage]}; 363 const Shader::Info& info{stage_infos[stage]};
248 buffer_cache.UnbindGraphicsTextureBuffers(stage); 364 if constexpr (Spec::has_texture_buffers || Spec::has_image_buffers) {
249 std::ranges::for_each(info.texture_buffer_descriptors, add_buffer); 365 buffer_cache.UnbindGraphicsTextureBuffers(stage);
250 std::ranges::for_each(info.image_buffer_descriptors, add_buffer); 366 }
367 if constexpr (Spec::has_texture_buffers) {
368 for (const auto& desc : info.texture_buffer_descriptors) {
369 add_buffer(desc);
370 }
371 }
372 if constexpr (Spec::has_image_buffers) {
373 for (const auto& desc : info.image_buffer_descriptors) {
374 add_buffer(desc);
375 }
376 }
251 for (const auto& desc : info.texture_descriptors) { 377 for (const auto& desc : info.texture_descriptors) {
252 texture_buffer_index += desc.count; 378 texture_buffer_index += desc.count;
253 } 379 }
254 for (const auto& desc : info.image_descriptors) { 380 if constexpr (Spec::has_images) {
255 texture_buffer_index += desc.count; 381 for (const auto& desc : info.image_descriptors) {
382 texture_buffer_index += desc.count;
383 }
256 } 384 }
385 }};
386 if constexpr (Spec::enabled_stages[0]) {
387 bind_stage_info(0);
388 }
389 if constexpr (Spec::enabled_stages[1]) {
390 bind_stage_info(1);
391 }
392 if constexpr (Spec::enabled_stages[2]) {
393 bind_stage_info(2);
394 }
395 if constexpr (Spec::enabled_stages[3]) {
396 bind_stage_info(3);
397 }
398 if constexpr (Spec::enabled_stages[4]) {
399 bind_stage_info(4);
257 } 400 }
258 buffer_cache.UpdateGraphicsBuffers(is_indexed);
259 401
402 buffer_cache.UpdateGraphicsBuffers(is_indexed);
260 buffer_cache.BindHostGeometryBuffers(is_indexed); 403 buffer_cache.BindHostGeometryBuffers(is_indexed);
261 404
262 update_descriptor_queue.Acquire(); 405 update_descriptor_queue.Acquire();
263 406
264 const VkSampler* samplers_it{samplers.data()}; 407 const VkSampler* samplers_it{samplers.data()};
265 const ImageId* views_it{image_view_ids.data()}; 408 const ImageId* views_it{image_view_ids.data()};
266 for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { 409 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
267 buffer_cache.BindHostStageBuffers(stage); 410 buffer_cache.BindHostStageBuffers(stage);
268 PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache, 411 PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache,
269 update_descriptor_queue); 412 update_descriptor_queue);
413 }};
414 if constexpr (Spec::enabled_stages[0]) {
415 prepare_stage(0);
416 }
417 if constexpr (Spec::enabled_stages[1]) {
418 prepare_stage(1);
419 }
420 if constexpr (Spec::enabled_stages[2]) {
421 prepare_stage(2);
422 }
423 if constexpr (Spec::enabled_stages[3]) {
424 prepare_stage(3);
270 } 425 }
426 if constexpr (Spec::enabled_stages[4]) {
427 prepare_stage(4);
428 }
429 ConfigureDraw();
430}
431
432void GraphicsPipeline::ConfigureDraw() {
271 texture_cache.UpdateRenderTargets(false); 433 texture_cache.UpdateRenderTargets(false);
272 scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); 434 scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
273 435
@@ -550,4 +712,23 @@ void GraphicsPipeline::MakePipeline(const Device& device, VkRenderPass render_pa
550 }); 712 });
551} 713}
552 714
715void GraphicsPipeline::Validate() {
716 size_t num_images{};
717 for (const auto& info : stage_infos) {
718 for (const auto& desc : info.texture_buffer_descriptors) {
719 num_images += desc.count;
720 }
721 for (const auto& desc : info.image_buffer_descriptors) {
722 num_images += desc.count;
723 }
724 for (const auto& desc : info.texture_descriptors) {
725 num_images += desc.count;
726 }
727 for (const auto& desc : info.image_descriptors) {
728 num_images += desc.count;
729 }
730 }
731 ASSERT(num_images <= MAX_IMAGE_ELEMENTS);
732}
733
553} // namespace Vulkan 734} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index fd787840b..edab5703f 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -75,8 +75,6 @@ public:
75 std::array<vk::ShaderModule, NUM_STAGES> stages, 75 std::array<vk::ShaderModule, NUM_STAGES> stages,
76 const std::array<const Shader::Info*, NUM_STAGES>& infos); 76 const std::array<const Shader::Info*, NUM_STAGES>& infos);
77 77
78 void Configure(bool is_indexed);
79
80 GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; 78 GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete;
81 GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; 79 GraphicsPipeline(GraphicsPipeline&&) noexcept = delete;
82 80
@@ -85,6 +83,10 @@ public:
85 83
86 void AddTransition(GraphicsPipeline* transition); 84 void AddTransition(GraphicsPipeline* transition);
87 85
86 void Configure(bool is_indexed) {
87 configure_func(this, is_indexed);
88 }
89
88 GraphicsPipeline* Next(const GraphicsPipelineCacheKey& current_key) noexcept { 90 GraphicsPipeline* Next(const GraphicsPipelineCacheKey& current_key) noexcept {
89 if (key == current_key) { 91 if (key == current_key) {
90 return this; 92 return this;
@@ -94,9 +96,23 @@ public:
94 : nullptr; 96 : nullptr;
95 } 97 }
96 98
99 template <typename Spec>
100 static auto MakeConfigureSpecFunc() {
101 return [](GraphicsPipeline* pipeline, bool is_indexed) {
102 pipeline->ConfigureImpl<Spec>(is_indexed);
103 };
104 }
105
97private: 106private:
107 template <typename Spec>
108 void ConfigureImpl(bool is_indexed);
109
110 void ConfigureDraw();
111
98 void MakePipeline(const Device& device, VkRenderPass render_pass); 112 void MakePipeline(const Device& device, VkRenderPass render_pass);
99 113
114 void Validate();
115
100 const GraphicsPipelineCacheKey key; 116 const GraphicsPipelineCacheKey key;
101 Tegra::Engines::Maxwell3D& maxwell3d; 117 Tegra::Engines::Maxwell3D& maxwell3d;
102 Tegra::MemoryManager& gpu_memory; 118 Tegra::MemoryManager& gpu_memory;
@@ -105,6 +121,8 @@ private:
105 VKScheduler& scheduler; 121 VKScheduler& scheduler;
106 VKUpdateDescriptorQueue& update_descriptor_queue; 122 VKUpdateDescriptorQueue& update_descriptor_queue;
107 123
124 void (*configure_func)(GraphicsPipeline*, bool);
125
108 std::vector<GraphicsPipelineCacheKey> transition_keys; 126 std::vector<GraphicsPipelineCacheKey> transition_keys;
109 std::vector<GraphicsPipeline*> transitions; 127 std::vector<GraphicsPipeline*> transitions;
110 128