summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h56
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp30
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp21
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp3
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.h5
8 files changed, 103 insertions, 27 deletions
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index 4847db6b6..7ba6078df 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -20,6 +20,8 @@
20 20
21namespace Vulkan { 21namespace Vulkan {
22 22
23constexpr size_t MAX_RESCALING_WORDS = 4;
24
23class DescriptorLayoutBuilder { 25class DescriptorLayoutBuilder {
24public: 26public:
25 DescriptorLayoutBuilder(const Device& device_) : device{&device_} {} 27 DescriptorLayoutBuilder(const Device& device_) : device{&device_} {}
@@ -68,18 +70,26 @@ public:
68 } 70 }
69 71
70 vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const { 72 vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const {
73 const VkPushConstantRange range{
74 .stageFlags = static_cast<VkShaderStageFlags>(
75 is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS),
76 .offset = 0,
77 .size = (is_compute ? 0 : sizeof(f32)) + sizeof(std::array<u32, MAX_RESCALING_WORDS>),
78 };
71 return device->GetLogical().CreatePipelineLayout({ 79 return device->GetLogical().CreatePipelineLayout({
72 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 80 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
73 .pNext = nullptr, 81 .pNext = nullptr,
74 .flags = 0, 82 .flags = 0,
75 .setLayoutCount = descriptor_set_layout ? 1U : 0U, 83 .setLayoutCount = descriptor_set_layout ? 1U : 0U,
76 .pSetLayouts = bindings.empty() ? nullptr : &descriptor_set_layout, 84 .pSetLayouts = bindings.empty() ? nullptr : &descriptor_set_layout,
77 .pushConstantRangeCount = 0, 85 .pushConstantRangeCount = 1,
78 .pPushConstantRanges = nullptr, 86 .pPushConstantRanges = &range,
79 }); 87 });
80 } 88 }
81 89
82 void Add(const Shader::Info& info, VkShaderStageFlags stage) { 90 void Add(const Shader::Info& info, VkShaderStageFlags stage) {
91 is_compute |= (stage & VK_SHADER_STAGE_COMPUTE_BIT) != 0;
92
83 Add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stage, info.constant_buffer_descriptors); 93 Add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stage, info.constant_buffer_descriptors);
84 Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage, info.storage_buffers_descriptors); 94 Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage, info.storage_buffers_descriptors);
85 Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage, info.texture_buffer_descriptors); 95 Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage, info.texture_buffer_descriptors);
@@ -115,6 +125,7 @@ private:
115 } 125 }
116 126
117 const Device* device{}; 127 const Device* device{};
128 bool is_compute{};
118 boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings; 129 boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings;
119 boost::container::small_vector<VkDescriptorUpdateTemplateEntryKHR, 32> entries; 130 boost::container::small_vector<VkDescriptorUpdateTemplateEntryKHR, 32> entries;
120 u32 binding{}; 131 u32 binding{};
@@ -122,21 +133,46 @@ private:
122 size_t offset{}; 133 size_t offset{};
123}; 134};
124 135
125inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers, 136class RescalingPushConstant {
126 const ImageId*& image_view_ids, TextureCache& texture_cache, 137public:
127 VKUpdateDescriptorQueue& update_descriptor_queue) { 138 explicit RescalingPushConstant(u32 num_textures) noexcept {}
128 for (const auto& desc : info.texture_buffer_descriptors) { 139
129 image_view_ids += desc.count; 140 void PushTexture(bool is_rescaled) noexcept {
141 *texture_ptr |= is_rescaled ? texture_bit : 0;
142 texture_bit <<= 1;
143 if (texture_bit == 0) {
144 texture_bit = 1u;
145 ++texture_ptr;
146 }
130 } 147 }
131 for (const auto& desc : info.image_buffer_descriptors) { 148
132 image_view_ids += desc.count; 149 const std::array<u32, MAX_RESCALING_WORDS>& Data() const noexcept {
150 return words;
133 } 151 }
152
153private:
154 std::array<u32, MAX_RESCALING_WORDS> words{};
155 u32* texture_ptr{words.data()};
156 u32 texture_bit{1u};
157};
158
159inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers,
160 const ImageId*& image_view_ids, TextureCache& texture_cache,
161 VKUpdateDescriptorQueue& update_descriptor_queue,
162 RescalingPushConstant& rescaling) {
163 static constexpr VideoCommon::ImageViewId NULL_IMAGE_VIEW_ID{0};
164 image_view_ids += Shader::NumDescriptors(info.texture_buffer_descriptors);
165 image_view_ids += Shader::NumDescriptors(info.image_buffer_descriptors);
134 for (const auto& desc : info.texture_descriptors) { 166 for (const auto& desc : info.texture_descriptors) {
135 for (u32 index = 0; index < desc.count; ++index) { 167 for (u32 index = 0; index < desc.count; ++index) {
168 const VideoCommon::ImageViewId image_view_id{*(image_view_ids++)};
136 const VkSampler sampler{*(samplers++)}; 169 const VkSampler sampler{*(samplers++)};
137 ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; 170 ImageView& image_view{texture_cache.GetImageView(image_view_id)};
171 const Image& image{texture_cache.GetImage(image_view.image_id)};
138 const VkImageView vk_image_view{image_view.Handle(desc.type)}; 172 const VkImageView vk_image_view{image_view.Handle(desc.type)};
139 update_descriptor_queue.AddSampledImage(vk_image_view, sampler); 173 update_descriptor_queue.AddSampledImage(vk_image_view, sampler);
174 rescaling.PushTexture(image_view_id != NULL_IMAGE_VIEW_ID &&
175 True(image.flags & VideoCommon::ImageFlagBits::Rescaled));
140 } 176 }
141 } 177 }
142 for (const auto& desc : info.image_descriptors) { 178 for (const auto& desc : info.image_descriptors) {
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 44faf626a..bda75788c 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -180,9 +180,11 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
180 buffer_cache.UpdateComputeBuffers(); 180 buffer_cache.UpdateComputeBuffers();
181 buffer_cache.BindHostComputeBuffers(); 181 buffer_cache.BindHostComputeBuffers();
182 182
183 RescalingPushConstant rescaling(num_textures);
183 const VkSampler* samplers_it{samplers.data()}; 184 const VkSampler* samplers_it{samplers.data()};
184 const ImageId* views_it{image_view_ids.data()}; 185 const ImageId* views_it{image_view_ids.data()};
185 PushImageDescriptors(info, samplers_it, views_it, texture_cache, update_descriptor_queue); 186 PushImageDescriptors(info, samplers_it, views_it, texture_cache, update_descriptor_queue,
187 rescaling);
186 188
187 if (!is_built.load(std::memory_order::relaxed)) { 189 if (!is_built.load(std::memory_order::relaxed)) {
188 // Wait for the pipeline to be built 190 // Wait for the pipeline to be built
@@ -192,17 +194,21 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
192 }); 194 });
193 } 195 }
194 const void* const descriptor_data{update_descriptor_queue.UpdateData()}; 196 const void* const descriptor_data{update_descriptor_queue.UpdateData()};
195 scheduler.Record([this, descriptor_data](vk::CommandBuffer cmdbuf) { 197 scheduler.Record(
196 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 198 [this, descriptor_data, rescaling_data = rescaling.Data()](vk::CommandBuffer cmdbuf) {
197 if (!descriptor_set_layout) { 199 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
198 return; 200 if (!descriptor_set_layout) {
199 } 201 return;
200 const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; 202 }
201 const vk::Device& dev{device.GetLogical()}; 203 if (num_textures > 0) {
202 dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data); 204 cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, rescaling_data);
203 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0, 205 }
204 descriptor_set, nullptr); 206 const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
205 }); 207 const vk::Device& dev{device.GetLogical()};
208 dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data);
209 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0,
210 descriptor_set, nullptr);
211 });
206} 212}
207 213
208} // namespace Vulkan 214} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
index 8c4b0a301..e79ce4d7c 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -59,6 +59,7 @@ private:
59 vk::PipelineLayout pipeline_layout; 59 vk::PipelineLayout pipeline_layout;
60 vk::DescriptorUpdateTemplateKHR descriptor_update_template; 60 vk::DescriptorUpdateTemplateKHR descriptor_update_template;
61 vk::Pipeline pipeline; 61 vk::Pipeline pipeline;
62 u32 num_textures{};
62 63
63 std::condition_variable build_condvar; 64 std::condition_variable build_condvar;
64 std::mutex build_mutex; 65 std::mutex build_mutex;
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 7e48d4458..967762c37 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -235,6 +235,7 @@ GraphicsPipeline::GraphicsPipeline(
235 stage_infos[stage] = *info; 235 stage_infos[stage] = *info;
236 enabled_uniform_buffer_masks[stage] = info->constant_buffer_mask; 236 enabled_uniform_buffer_masks[stage] = info->constant_buffer_mask;
237 std::ranges::copy(info->constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin()); 237 std::ranges::copy(info->constant_buffer_used_sizes, uniform_buffer_sizes[stage].begin());
238 num_textures += Shader::NumDescriptors(info->texture_descriptors);
238 } 239 }
239 auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool, pipeline_statistics] { 240 auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool, pipeline_statistics] {
240 DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)}; 241 DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)};
@@ -428,12 +429,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
428 429
429 update_descriptor_queue.Acquire(); 430 update_descriptor_queue.Acquire();
430 431
432 RescalingPushConstant rescaling(num_textures);
431 const VkSampler* samplers_it{samplers.data()}; 433 const VkSampler* samplers_it{samplers.data()};
432 const ImageId* views_it{image_view_ids.data()}; 434 const ImageId* views_it{image_view_ids.data()};
433 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { 435 const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
434 buffer_cache.BindHostStageBuffers(stage); 436 buffer_cache.BindHostStageBuffers(stage);
435 PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache, 437 PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache,
436 update_descriptor_queue); 438 update_descriptor_queue, rescaling);
437 }}; 439 }};
438 if constexpr (Spec::enabled_stages[0]) { 440 if constexpr (Spec::enabled_stages[0]) {
439 prepare_stage(0); 441 prepare_stage(0);
@@ -450,10 +452,10 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
450 if constexpr (Spec::enabled_stages[4]) { 452 if constexpr (Spec::enabled_stages[4]) {
451 prepare_stage(4); 453 prepare_stage(4);
452 } 454 }
453 ConfigureDraw(); 455 ConfigureDraw(rescaling);
454} 456}
455 457
456void GraphicsPipeline::ConfigureDraw() { 458void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling) {
457 texture_cache.UpdateRenderTargets(false); 459 texture_cache.UpdateRenderTargets(false);
458 scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); 460 scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
459 461
@@ -464,12 +466,23 @@ void GraphicsPipeline::ConfigureDraw() {
464 build_condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); }); 466 build_condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); });
465 }); 467 });
466 } 468 }
469 const bool is_rescaling{texture_cache.IsRescaling()};
470 const bool update_rescaling{scheduler.UpdateRescaling(is_rescaling)};
467 const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)}; 471 const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)};
468 const void* const descriptor_data{update_descriptor_queue.UpdateData()}; 472 const void* const descriptor_data{update_descriptor_queue.UpdateData()};
469 scheduler.Record([this, descriptor_data, bind_pipeline](vk::CommandBuffer cmdbuf) { 473 scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
474 is_rescaling, update_rescaling](vk::CommandBuffer cmdbuf) {
470 if (bind_pipeline) { 475 if (bind_pipeline) {
471 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 476 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
472 } 477 }
478 if (update_rescaling) {
479 const f32 config_down_factor{Settings::values.resolution_info.down_factor};
480 const float scale_down_factor{is_rescaling ? config_down_factor : 1.0f};
481 cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, 0,
482 sizeof(scale_down_factor), &scale_down_factor);
483 }
484 cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS, sizeof(f32),
485 sizeof(rescaling_data), rescaling_data.data());
473 if (!descriptor_set_layout) { 486 if (!descriptor_set_layout) {
474 return; 487 return;
475 } 488 }
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index 1c780e944..a0c1d8f07 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -62,6 +62,7 @@ namespace Vulkan {
62class Device; 62class Device;
63class PipelineStatistics; 63class PipelineStatistics;
64class RenderPassCache; 64class RenderPassCache;
65class RescalingPushConstant;
65class VKScheduler; 66class VKScheduler;
66class VKUpdateDescriptorQueue; 67class VKUpdateDescriptorQueue;
67 68
@@ -113,7 +114,7 @@ private:
113 template <typename Spec> 114 template <typename Spec>
114 void ConfigureImpl(bool is_indexed); 115 void ConfigureImpl(bool is_indexed);
115 116
116 void ConfigureDraw(); 117 void ConfigureDraw(const RescalingPushConstant& rescaling);
117 118
118 void MakePipeline(VkRenderPass render_pass); 119 void MakePipeline(VkRenderPass render_pass);
119 120
@@ -138,6 +139,7 @@ private:
138 std::array<Shader::Info, NUM_STAGES> stage_infos; 139 std::array<Shader::Info, NUM_STAGES> stage_infos;
139 std::array<u32, 5> enabled_uniform_buffer_masks{}; 140 std::array<u32, 5> enabled_uniform_buffer_masks{};
140 VideoCommon::UniformBufferSizes uniform_buffer_sizes{}; 141 VideoCommon::UniformBufferSizes uniform_buffer_sizes{};
142 u32 num_textures{};
141 143
142 vk::DescriptorSetLayout descriptor_set_layout; 144 vk::DescriptorSetLayout descriptor_set_layout;
143 DescriptorAllocator descriptor_allocator; 145 DescriptorAllocator descriptor_allocator;
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index eb8b4e08b..691ef0841 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -139,6 +139,9 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
139 } else { 139 } else {
140 info.previous_stage_stores.mask.set(); 140 info.previous_stage_stores.mask.set();
141 } 141 }
142 for (const auto& stage : programs) {
143 info.num_textures += Shader::NumDescriptors(stage.info.texture_descriptors);
144 }
142 const Shader::Stage stage{program.stage}; 145 const Shader::Stage stage{program.stage};
143 const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough}; 146 const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough};
144 const bool gl_ndc{key.state.ndc_minus_one_to_one != 0}; 147 const bool gl_ndc{key.state.ndc_minus_one_to_one != 0};
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
index 0c11c814f..3bfdf41ba 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
@@ -128,6 +128,15 @@ bool VKScheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
128 return true; 128 return true;
129} 129}
130 130
131bool VKScheduler::UpdateRescaling(bool is_rescaling) {
132 if (state.rescaling_defined && is_rescaling == state.is_rescaling) {
133 return false;
134 }
135 state.rescaling_defined = true;
136 state.is_rescaling = is_rescaling;
137 return true;
138}
139
131void VKScheduler::WorkerThread(std::stop_token stop_token) { 140void VKScheduler::WorkerThread(std::stop_token stop_token) {
132 Common::SetCurrentThreadName("yuzu:VulkanWorker"); 141 Common::SetCurrentThreadName("yuzu:VulkanWorker");
133 do { 142 do {
@@ -227,6 +236,7 @@ void VKScheduler::AllocateNewContext() {
227 236
228void VKScheduler::InvalidateState() { 237void VKScheduler::InvalidateState() {
229 state.graphics_pipeline = nullptr; 238 state.graphics_pipeline = nullptr;
239 state.rescaling_defined = false;
230 state_tracker.InvalidateCommandBufferState(); 240 state_tracker.InvalidateCommandBufferState();
231} 241}
232 242
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h
index 85fc1712f..1b06c9296 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.h
+++ b/src/video_core/renderer_vulkan/vk_scheduler.h
@@ -56,6 +56,9 @@ public:
56 /// Update the pipeline to the current execution context. 56 /// Update the pipeline to the current execution context.
57 bool UpdateGraphicsPipeline(GraphicsPipeline* pipeline); 57 bool UpdateGraphicsPipeline(GraphicsPipeline* pipeline);
58 58
59 /// Update the rescaling state. Returns true if the state has to be updated.
60 bool UpdateRescaling(bool is_rescaling);
61
59 /// Invalidates current command buffer state except for render passes 62 /// Invalidates current command buffer state except for render passes
60 void InvalidateState(); 63 void InvalidateState();
61 64
@@ -185,6 +188,8 @@ private:
185 VkFramebuffer framebuffer = nullptr; 188 VkFramebuffer framebuffer = nullptr;
186 VkExtent2D render_area = {0, 0}; 189 VkExtent2D render_area = {0, 0};
187 GraphicsPipeline* graphics_pipeline = nullptr; 190 GraphicsPipeline* graphics_pipeline = nullptr;
191 bool is_rescaling = false;
192 bool rescaling_defined = false;
188 }; 193 };
189 194
190 void WorkerThread(std::stop_token stop_token); 195 void WorkerThread(std::stop_token stop_token);