diff options
| author | 2022-10-06 21:29:53 +0200 | |
|---|---|---|
| committer | 2022-10-06 21:29:53 +0200 | |
| commit | 1effa578f12f79d7816e3543291f302f126cc1d2 (patch) | |
| tree | 14803b31b6817294d40d57446f6fa94c5ff3fe9a /src/video_core/renderer_vulkan | |
| parent | Merge pull request #9025 from FernandoS27/slava-ukrayini (diff) | |
| parent | vulkan_blitter: Fix pool allocation double free. (diff) | |
| download | yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.tar.gz yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.tar.xz yuzu-1effa578f12f79d7816e3543291f302f126cc1d2.zip | |
Merge pull request #8467 from FernandoS27/yfc-rel-1
Project yuzu Fried Chicken (Y.F.C.) Part 1
Diffstat (limited to 'src/video_core/renderer_vulkan')
21 files changed, 240 insertions, 159 deletions
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 6703b8e68..e7104d377 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -184,7 +184,7 @@ struct FormatTuple { | |||
| 184 | {VK_FORMAT_BC3_SRGB_BLOCK}, // BC3_SRGB | 184 | {VK_FORMAT_BC3_SRGB_BLOCK}, // BC3_SRGB |
| 185 | {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7_SRGB | 185 | {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7_SRGB |
| 186 | {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable}, // A4B4G4R4_UNORM | 186 | {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable}, // A4B4G4R4_UNORM |
| 187 | {VK_FORMAT_R4G4_UNORM_PACK8}, // R4G4_UNORM | 187 | {VK_FORMAT_R4G4_UNORM_PACK8}, // G4R4_UNORM |
| 188 | {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB | 188 | {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB |
| 189 | {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB | 189 | {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB |
| 190 | {VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, // ASTC_2D_8X5_SRGB | 190 | {VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, // ASTC_2D_8X5_SRGB |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 7c78d0299..d8131232a 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -102,13 +102,13 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 102 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), | 102 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), |
| 103 | surface(CreateSurface(instance, render_window)), | 103 | surface(CreateSurface(instance, render_window)), |
| 104 | device(CreateDevice(instance, dld, *surface)), memory_allocator(device, false), | 104 | device(CreateDevice(instance, dld, *surface)), memory_allocator(device, false), |
| 105 | state_tracker(gpu), scheduler(device, state_tracker), | 105 | state_tracker(), scheduler(device, state_tracker), |
| 106 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, | 106 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, |
| 107 | render_window.GetFramebufferLayout().height, false), | 107 | render_window.GetFramebufferLayout().height, false), |
| 108 | blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, scheduler, | 108 | blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, scheduler, |
| 109 | screen_info), | 109 | screen_info), |
| 110 | rasterizer(render_window, gpu, gpu.MemoryManager(), cpu_memory, screen_info, device, | 110 | rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, |
| 111 | memory_allocator, state_tracker, scheduler) { | 111 | state_tracker, scheduler) { |
| 112 | Report(); | 112 | Report(); |
| 113 | } catch (const vk::Exception& exception) { | 113 | } catch (const vk::Exception& exception) { |
| 114 | LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what()); | 114 | LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what()); |
| @@ -142,7 +142,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 142 | const auto recreate_swapchain = [&] { | 142 | const auto recreate_swapchain = [&] { |
| 143 | if (!has_been_recreated) { | 143 | if (!has_been_recreated) { |
| 144 | has_been_recreated = true; | 144 | has_been_recreated = true; |
| 145 | scheduler.WaitWorker(); | 145 | scheduler.Finish(); |
| 146 | } | 146 | } |
| 147 | const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout(); | 147 | const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout(); |
| 148 | swapchain.Create(layout.width, layout.height, is_srgb); | 148 | swapchain.Create(layout.width, layout.height, is_srgb); |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 444c29f68..cb7fa2078 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -145,6 +145,11 @@ VkSemaphore BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | |||
| 145 | // Finish any pending renderpass | 145 | // Finish any pending renderpass |
| 146 | scheduler.RequestOutsideRenderPassOperationContext(); | 146 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 147 | 147 | ||
| 148 | if (const auto swapchain_images = swapchain.GetImageCount(); swapchain_images != image_count) { | ||
| 149 | image_count = swapchain_images; | ||
| 150 | Recreate(); | ||
| 151 | } | ||
| 152 | |||
| 148 | const std::size_t image_index = swapchain.GetImageIndex(); | 153 | const std::size_t image_index = swapchain.GetImageIndex(); |
| 149 | 154 | ||
| 150 | scheduler.Wait(resource_ticks[image_index]); | 155 | scheduler.Wait(resource_ticks[image_index]); |
| @@ -448,15 +453,15 @@ vk::Framebuffer BlitScreen::CreateFramebuffer(const VkImageView& image_view, VkE | |||
| 448 | 453 | ||
| 449 | void BlitScreen::CreateStaticResources() { | 454 | void BlitScreen::CreateStaticResources() { |
| 450 | CreateShaders(); | 455 | CreateShaders(); |
| 456 | CreateSampler(); | ||
| 457 | } | ||
| 458 | |||
| 459 | void BlitScreen::CreateDynamicResources() { | ||
| 451 | CreateSemaphores(); | 460 | CreateSemaphores(); |
| 452 | CreateDescriptorPool(); | 461 | CreateDescriptorPool(); |
| 453 | CreateDescriptorSetLayout(); | 462 | CreateDescriptorSetLayout(); |
| 454 | CreateDescriptorSets(); | 463 | CreateDescriptorSets(); |
| 455 | CreatePipelineLayout(); | 464 | CreatePipelineLayout(); |
| 456 | CreateSampler(); | ||
| 457 | } | ||
| 458 | |||
| 459 | void BlitScreen::CreateDynamicResources() { | ||
| 460 | CreateRenderPass(); | 465 | CreateRenderPass(); |
| 461 | CreateFramebuffers(); | 466 | CreateFramebuffers(); |
| 462 | CreateGraphicsPipeline(); | 467 | CreateGraphicsPipeline(); |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index b8c67bef0..29e2ea925 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h | |||
| @@ -109,7 +109,7 @@ private: | |||
| 109 | MemoryAllocator& memory_allocator; | 109 | MemoryAllocator& memory_allocator; |
| 110 | Swapchain& swapchain; | 110 | Swapchain& swapchain; |
| 111 | Scheduler& scheduler; | 111 | Scheduler& scheduler; |
| 112 | const std::size_t image_count; | 112 | std::size_t image_count; |
| 113 | const ScreenInfo& screen_info; | 113 | const ScreenInfo& screen_info; |
| 114 | 114 | ||
| 115 | vk::ShaderModule vertex_shader; | 115 | vk::ShaderModule vertex_shader; |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index f17a5ccd6..241d7573e 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp | |||
| @@ -26,8 +26,6 @@ | |||
| 26 | 26 | ||
| 27 | namespace Vulkan { | 27 | namespace Vulkan { |
| 28 | 28 | ||
| 29 | using Tegra::Texture::SWIZZLE_TABLE; | ||
| 30 | |||
| 31 | namespace { | 29 | namespace { |
| 32 | 30 | ||
| 33 | constexpr u32 ASTC_BINDING_INPUT_BUFFER = 0; | 31 | constexpr u32 ASTC_BINDING_INPUT_BUFFER = 0; |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 6447210e2..7906e11a8 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -126,8 +126,8 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 126 | const u32 secondary_offset{desc.secondary_cbuf_offset + index_offset}; | 126 | const u32 secondary_offset{desc.secondary_cbuf_offset + index_offset}; |
| 127 | const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].Address() + | 127 | const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].Address() + |
| 128 | secondary_offset}; | 128 | secondary_offset}; |
| 129 | const u32 lhs_raw{gpu_memory.Read<u32>(addr)}; | 129 | const u32 lhs_raw{gpu_memory.Read<u32>(addr) << desc.shift_left}; |
| 130 | const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr)}; | 130 | const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr) << desc.secondary_shift_left}; |
| 131 | return TexturePair(lhs_raw | rhs_raw, via_header_index); | 131 | return TexturePair(lhs_raw | rhs_raw, via_header_index); |
| 132 | } | 132 | } |
| 133 | } | 133 | } |
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.cpp b/src/video_core/renderer_vulkan/vk_fence_manager.cpp index c249b34d4..0214b103a 100644 --- a/src/video_core/renderer_vulkan/vk_fence_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_fence_manager.cpp | |||
| @@ -11,11 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | namespace Vulkan { | 12 | namespace Vulkan { |
| 13 | 13 | ||
| 14 | InnerFence::InnerFence(Scheduler& scheduler_, u32 payload_, bool is_stubbed_) | 14 | InnerFence::InnerFence(Scheduler& scheduler_, bool is_stubbed_) |
| 15 | : FenceBase{payload_, is_stubbed_}, scheduler{scheduler_} {} | 15 | : FenceBase{is_stubbed_}, scheduler{scheduler_} {} |
| 16 | |||
| 17 | InnerFence::InnerFence(Scheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_) | ||
| 18 | : FenceBase{address_, payload_, is_stubbed_}, scheduler{scheduler_} {} | ||
| 19 | 16 | ||
| 20 | InnerFence::~InnerFence() = default; | 17 | InnerFence::~InnerFence() = default; |
| 21 | 18 | ||
| @@ -48,12 +45,8 @@ FenceManager::FenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::G | |||
| 48 | : GenericFenceManager{rasterizer_, gpu_, texture_cache_, buffer_cache_, query_cache_}, | 45 | : GenericFenceManager{rasterizer_, gpu_, texture_cache_, buffer_cache_, query_cache_}, |
| 49 | scheduler{scheduler_} {} | 46 | scheduler{scheduler_} {} |
| 50 | 47 | ||
| 51 | Fence FenceManager::CreateFence(u32 value, bool is_stubbed) { | 48 | Fence FenceManager::CreateFence(bool is_stubbed) { |
| 52 | return std::make_shared<InnerFence>(scheduler, value, is_stubbed); | 49 | return std::make_shared<InnerFence>(scheduler, is_stubbed); |
| 53 | } | ||
| 54 | |||
| 55 | Fence FenceManager::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) { | ||
| 56 | return std::make_shared<InnerFence>(scheduler, addr, value, is_stubbed); | ||
| 57 | } | 50 | } |
| 58 | 51 | ||
| 59 | void FenceManager::QueueFence(Fence& fence) { | 52 | void FenceManager::QueueFence(Fence& fence) { |
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.h b/src/video_core/renderer_vulkan/vk_fence_manager.h index 7c0bbd80a..7fe2afcd9 100644 --- a/src/video_core/renderer_vulkan/vk_fence_manager.h +++ b/src/video_core/renderer_vulkan/vk_fence_manager.h | |||
| @@ -25,8 +25,7 @@ class Scheduler; | |||
| 25 | 25 | ||
| 26 | class InnerFence : public VideoCommon::FenceBase { | 26 | class InnerFence : public VideoCommon::FenceBase { |
| 27 | public: | 27 | public: |
| 28 | explicit InnerFence(Scheduler& scheduler_, u32 payload_, bool is_stubbed_); | 28 | explicit InnerFence(Scheduler& scheduler_, bool is_stubbed_); |
| 29 | explicit InnerFence(Scheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_); | ||
| 30 | ~InnerFence(); | 29 | ~InnerFence(); |
| 31 | 30 | ||
| 32 | void Queue(); | 31 | void Queue(); |
| @@ -50,8 +49,7 @@ public: | |||
| 50 | QueryCache& query_cache, const Device& device, Scheduler& scheduler); | 49 | QueryCache& query_cache, const Device& device, Scheduler& scheduler); |
| 51 | 50 | ||
| 52 | protected: | 51 | protected: |
| 53 | Fence CreateFence(u32 value, bool is_stubbed) override; | 52 | Fence CreateFence(bool is_stubbed) override; |
| 54 | Fence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) override; | ||
| 55 | void QueueFence(Fence& fence) override; | 53 | void QueueFence(Fence& fence) override; |
| 56 | bool IsFenceSignaled(Fence& fence) const override; | 54 | bool IsFenceSignaled(Fence& fence) const override; |
| 57 | void WaitFence(Fence& fence) override; | 55 | void WaitFence(Fence& fence) override; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 5aca8f038..f47786f48 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -215,15 +215,14 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m | |||
| 215 | } // Anonymous namespace | 215 | } // Anonymous namespace |
| 216 | 216 | ||
| 217 | GraphicsPipeline::GraphicsPipeline( | 217 | GraphicsPipeline::GraphicsPipeline( |
| 218 | Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, Scheduler& scheduler_, | 218 | Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_, |
| 219 | BufferCache& buffer_cache_, TextureCache& texture_cache_, | ||
| 220 | VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool, | 219 | VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool, |
| 221 | UpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread, | 220 | UpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread, |
| 222 | PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, | 221 | PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, |
| 223 | const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages, | 222 | const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages, |
| 224 | const std::array<const Shader::Info*, NUM_STAGES>& infos) | 223 | const std::array<const Shader::Info*, NUM_STAGES>& infos) |
| 225 | : key{key_}, maxwell3d{maxwell3d_}, gpu_memory{gpu_memory_}, device{device_}, | 224 | : key{key_}, device{device_}, texture_cache{texture_cache_}, |
| 226 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, scheduler{scheduler_}, | 225 | buffer_cache{buffer_cache_}, scheduler{scheduler_}, |
| 227 | update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} { | 226 | update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} { |
| 228 | if (shader_notify) { | 227 | if (shader_notify) { |
| 229 | shader_notify->MarkShaderBuilding(); | 228 | shader_notify->MarkShaderBuilding(); |
| @@ -288,7 +287,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 288 | 287 | ||
| 289 | buffer_cache.SetUniformBuffersState(enabled_uniform_buffer_masks, &uniform_buffer_sizes); | 288 | buffer_cache.SetUniformBuffersState(enabled_uniform_buffer_masks, &uniform_buffer_sizes); |
| 290 | 289 | ||
| 291 | const auto& regs{maxwell3d.regs}; | 290 | const auto& regs{maxwell3d->regs}; |
| 292 | const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; | 291 | const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex}; |
| 293 | const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE { | 292 | const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE { |
| 294 | const Shader::Info& info{stage_infos[stage]}; | 293 | const Shader::Info& info{stage_infos[stage]}; |
| @@ -302,7 +301,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 302 | ++ssbo_index; | 301 | ++ssbo_index; |
| 303 | } | 302 | } |
| 304 | } | 303 | } |
| 305 | const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers}; | 304 | const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers}; |
| 306 | const auto read_handle{[&](const auto& desc, u32 index) { | 305 | const auto read_handle{[&](const auto& desc, u32 index) { |
| 307 | ASSERT(cbufs[desc.cbuf_index].enabled); | 306 | ASSERT(cbufs[desc.cbuf_index].enabled); |
| 308 | const u32 index_offset{index << desc.size_shift}; | 307 | const u32 index_offset{index << desc.size_shift}; |
| @@ -315,13 +314,14 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 315 | const u32 second_offset{desc.secondary_cbuf_offset + index_offset}; | 314 | const u32 second_offset{desc.secondary_cbuf_offset + index_offset}; |
| 316 | const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].address + | 315 | const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].address + |
| 317 | second_offset}; | 316 | second_offset}; |
| 318 | const u32 lhs_raw{gpu_memory.Read<u32>(addr)}; | 317 | const u32 lhs_raw{gpu_memory->Read<u32>(addr) << desc.shift_left}; |
| 319 | const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr)}; | 318 | const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr) |
| 319 | << desc.secondary_shift_left}; | ||
| 320 | const u32 raw{lhs_raw | rhs_raw}; | 320 | const u32 raw{lhs_raw | rhs_raw}; |
| 321 | return TexturePair(raw, via_header_index); | 321 | return TexturePair(raw, via_header_index); |
| 322 | } | 322 | } |
| 323 | } | 323 | } |
| 324 | return TexturePair(gpu_memory.Read<u32>(addr), via_header_index); | 324 | return TexturePair(gpu_memory->Read<u32>(addr), via_header_index); |
| 325 | }}; | 325 | }}; |
| 326 | const auto add_image{[&](const auto& desc, bool blacklist) LAMBDA_FORCEINLINE { | 326 | const auto add_image{[&](const auto& desc, bool blacklist) LAMBDA_FORCEINLINE { |
| 327 | for (u32 index = 0; index < desc.count; ++index) { | 327 | for (u32 index = 0; index < desc.count; ++index) { |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index e8949a9ab..85602592b 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h | |||
| @@ -69,15 +69,16 @@ class GraphicsPipeline { | |||
| 69 | static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; | 69 | static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; |
| 70 | 70 | ||
| 71 | public: | 71 | public: |
| 72 | explicit GraphicsPipeline( | 72 | explicit GraphicsPipeline(Scheduler& scheduler, BufferCache& buffer_cache, |
| 73 | Tegra::Engines::Maxwell3D& maxwell3d, Tegra::MemoryManager& gpu_memory, | 73 | TextureCache& texture_cache, VideoCore::ShaderNotify* shader_notify, |
| 74 | Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache, | 74 | const Device& device, DescriptorPool& descriptor_pool, |
| 75 | VideoCore::ShaderNotify* shader_notify, const Device& device, | 75 | UpdateDescriptorQueue& update_descriptor_queue, |
| 76 | DescriptorPool& descriptor_pool, UpdateDescriptorQueue& update_descriptor_queue, | 76 | Common::ThreadWorker* worker_thread, |
| 77 | Common::ThreadWorker* worker_thread, PipelineStatistics* pipeline_statistics, | 77 | PipelineStatistics* pipeline_statistics, |
| 78 | RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key, | 78 | RenderPassCache& render_pass_cache, |
| 79 | std::array<vk::ShaderModule, NUM_STAGES> stages, | 79 | const GraphicsPipelineCacheKey& key, |
| 80 | const std::array<const Shader::Info*, NUM_STAGES>& infos); | 80 | std::array<vk::ShaderModule, NUM_STAGES> stages, |
| 81 | const std::array<const Shader::Info*, NUM_STAGES>& infos); | ||
| 81 | 82 | ||
| 82 | GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; | 83 | GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; |
| 83 | GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; | 84 | GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; |
| @@ -109,6 +110,11 @@ public: | |||
| 109 | return [](GraphicsPipeline* pl, bool is_indexed) { pl->ConfigureImpl<Spec>(is_indexed); }; | 110 | return [](GraphicsPipeline* pl, bool is_indexed) { pl->ConfigureImpl<Spec>(is_indexed); }; |
| 110 | } | 111 | } |
| 111 | 112 | ||
| 113 | void SetEngine(Tegra::Engines::Maxwell3D* maxwell3d_, Tegra::MemoryManager* gpu_memory_) { | ||
| 114 | maxwell3d = maxwell3d_; | ||
| 115 | gpu_memory = gpu_memory_; | ||
| 116 | } | ||
| 117 | |||
| 112 | private: | 118 | private: |
| 113 | template <typename Spec> | 119 | template <typename Spec> |
| 114 | void ConfigureImpl(bool is_indexed); | 120 | void ConfigureImpl(bool is_indexed); |
| @@ -120,8 +126,8 @@ private: | |||
| 120 | void Validate(); | 126 | void Validate(); |
| 121 | 127 | ||
| 122 | const GraphicsPipelineCacheKey key; | 128 | const GraphicsPipelineCacheKey key; |
| 123 | Tegra::Engines::Maxwell3D& maxwell3d; | 129 | Tegra::Engines::Maxwell3D* maxwell3d; |
| 124 | Tegra::MemoryManager& gpu_memory; | 130 | Tegra::MemoryManager* gpu_memory; |
| 125 | const Device& device; | 131 | const Device& device; |
| 126 | TextureCache& texture_cache; | 132 | TextureCache& texture_cache; |
| 127 | BufferCache& buffer_cache; | 133 | BufferCache& buffer_cache; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index accbfc8e1..732e7b6f2 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -259,17 +259,15 @@ bool GraphicsPipelineCacheKey::operator==(const GraphicsPipelineCacheKey& rhs) c | |||
| 259 | return std::memcmp(&rhs, this, Size()) == 0; | 259 | return std::memcmp(&rhs, this, Size()) == 0; |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxwell3D& maxwell3d_, | 262 | PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device_, |
| 263 | Tegra::Engines::KeplerCompute& kepler_compute_, | ||
| 264 | Tegra::MemoryManager& gpu_memory_, const Device& device_, | ||
| 265 | Scheduler& scheduler_, DescriptorPool& descriptor_pool_, | 263 | Scheduler& scheduler_, DescriptorPool& descriptor_pool_, |
| 266 | UpdateDescriptorQueue& update_descriptor_queue_, | 264 | UpdateDescriptorQueue& update_descriptor_queue_, |
| 267 | RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, | 265 | RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, |
| 268 | TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_) | 266 | TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_) |
| 269 | : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, | 267 | : VideoCommon::ShaderCache{rasterizer_}, device{device_}, scheduler{scheduler_}, |
| 270 | device{device_}, scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, | 268 | descriptor_pool{descriptor_pool_}, update_descriptor_queue{update_descriptor_queue_}, |
| 271 | update_descriptor_queue{update_descriptor_queue_}, render_pass_cache{render_pass_cache_}, | 269 | render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_}, |
| 272 | buffer_cache{buffer_cache_}, texture_cache{texture_cache_}, shader_notify{shader_notify_}, | 270 | texture_cache{texture_cache_}, shader_notify{shader_notify_}, |
| 273 | use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, | 271 | use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, |
| 274 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"), | 272 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"), |
| 275 | serialization_thread(1, "VkPipelineSerialization") { | 273 | serialization_thread(1, "VkPipelineSerialization") { |
| @@ -337,7 +335,7 @@ GraphicsPipeline* PipelineCache::CurrentGraphicsPipeline() { | |||
| 337 | current_pipeline = nullptr; | 335 | current_pipeline = nullptr; |
| 338 | return nullptr; | 336 | return nullptr; |
| 339 | } | 337 | } |
| 340 | graphics_key.state.Refresh(maxwell3d, device.IsExtExtendedDynamicStateSupported(), | 338 | graphics_key.state.Refresh(*maxwell3d, device.IsExtExtendedDynamicStateSupported(), |
| 341 | device.IsExtVertexInputDynamicStateSupported()); | 339 | device.IsExtVertexInputDynamicStateSupported()); |
| 342 | 340 | ||
| 343 | if (current_pipeline) { | 341 | if (current_pipeline) { |
| @@ -357,7 +355,7 @@ ComputePipeline* PipelineCache::CurrentComputePipeline() { | |||
| 357 | if (!shader) { | 355 | if (!shader) { |
| 358 | return nullptr; | 356 | return nullptr; |
| 359 | } | 357 | } |
| 360 | const auto& qmd{kepler_compute.launch_description}; | 358 | const auto& qmd{kepler_compute->launch_description}; |
| 361 | const ComputePipelineCacheKey key{ | 359 | const ComputePipelineCacheKey key{ |
| 362 | .unique_hash = shader->unique_hash, | 360 | .unique_hash = shader->unique_hash, |
| 363 | .shared_memory_size = qmd.shared_alloc, | 361 | .shared_memory_size = qmd.shared_alloc, |
| @@ -486,13 +484,13 @@ GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const | |||
| 486 | } | 484 | } |
| 487 | // If something is using depth, we can assume that games are not rendering anything which | 485 | // If something is using depth, we can assume that games are not rendering anything which |
| 488 | // will be used one time. | 486 | // will be used one time. |
| 489 | if (maxwell3d.regs.zeta_enable) { | 487 | if (maxwell3d->regs.zeta_enable) { |
| 490 | return nullptr; | 488 | return nullptr; |
| 491 | } | 489 | } |
| 492 | // If games are using a small index count, we can assume these are full screen quads. | 490 | // If games are using a small index count, we can assume these are full screen quads. |
| 493 | // Usually these shaders are only used once for building textures so we can assume they | 491 | // Usually these shaders are only used once for building textures so we can assume they |
| 494 | // can't be built async | 492 | // can't be built async |
| 495 | if (maxwell3d.regs.index_array.count <= 6 || maxwell3d.regs.vertex_buffer.count <= 6) { | 493 | if (maxwell3d->regs.index_array.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) { |
| 496 | return pipeline; | 494 | return pipeline; |
| 497 | } | 495 | } |
| 498 | return nullptr; | 496 | return nullptr; |
| @@ -557,10 +555,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 557 | previous_stage = &program; | 555 | previous_stage = &program; |
| 558 | } | 556 | } |
| 559 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; | 557 | Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; |
| 560 | return std::make_unique<GraphicsPipeline>( | 558 | return std::make_unique<GraphicsPipeline>(scheduler, buffer_cache, texture_cache, |
| 561 | maxwell3d, gpu_memory, scheduler, buffer_cache, texture_cache, &shader_notify, device, | 559 | &shader_notify, device, descriptor_pool, |
| 562 | descriptor_pool, update_descriptor_queue, thread_worker, statistics, render_pass_cache, key, | 560 | update_descriptor_queue, thread_worker, statistics, |
| 563 | std::move(modules), infos); | 561 | render_pass_cache, key, std::move(modules), infos); |
| 564 | 562 | ||
| 565 | } catch (const Shader::Exception& exception) { | 563 | } catch (const Shader::Exception& exception) { |
| 566 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); | 564 | LOG_ERROR(Render_Vulkan, "{}", exception.what()); |
| @@ -592,9 +590,9 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline() { | |||
| 592 | 590 | ||
| 593 | std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | 591 | std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( |
| 594 | const ComputePipelineCacheKey& key, const ShaderInfo* shader) { | 592 | const ComputePipelineCacheKey& key, const ShaderInfo* shader) { |
| 595 | const GPUVAddr program_base{kepler_compute.regs.code_loc.Address()}; | 593 | const GPUVAddr program_base{kepler_compute->regs.code_loc.Address()}; |
| 596 | const auto& qmd{kepler_compute.launch_description}; | 594 | const auto& qmd{kepler_compute->launch_description}; |
| 597 | ComputeEnvironment env{kepler_compute, gpu_memory, program_base, qmd.program_start}; | 595 | ComputeEnvironment env{*kepler_compute, *gpu_memory, program_base, qmd.program_start}; |
| 598 | env.SetCachedSize(shader->size_bytes); | 596 | env.SetCachedSize(shader->size_bytes); |
| 599 | 597 | ||
| 600 | main_pools.ReleaseContents(); | 598 | main_pools.ReleaseContents(); |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 127957dbf..61f9e9366 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -100,10 +100,8 @@ struct ShaderPools { | |||
| 100 | 100 | ||
| 101 | class PipelineCache : public VideoCommon::ShaderCache { | 101 | class PipelineCache : public VideoCommon::ShaderCache { |
| 102 | public: | 102 | public: |
| 103 | explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::Engines::Maxwell3D& maxwell3d, | 103 | explicit PipelineCache(RasterizerVulkan& rasterizer, const Device& device, Scheduler& scheduler, |
| 104 | Tegra::Engines::KeplerCompute& kepler_compute, | 104 | DescriptorPool& descriptor_pool, |
| 105 | Tegra::MemoryManager& gpu_memory, const Device& device, | ||
| 106 | Scheduler& scheduler, DescriptorPool& descriptor_pool, | ||
| 107 | UpdateDescriptorQueue& update_descriptor_queue, | 105 | UpdateDescriptorQueue& update_descriptor_queue, |
| 108 | RenderPassCache& render_pass_cache, BufferCache& buffer_cache, | 106 | RenderPassCache& render_pass_cache, BufferCache& buffer_cache, |
| 109 | TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_); | 107 | TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_); |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 2b859c6b8..7cb02631c 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp | |||
| @@ -65,10 +65,9 @@ void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) { | |||
| 65 | usage[pool_index * GROW_STEP + static_cast<std::ptrdiff_t>(query.second)] = false; | 65 | usage[pool_index * GROW_STEP + static_cast<std::ptrdiff_t>(query.second)] = false; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | QueryCache::QueryCache(VideoCore::RasterizerInterface& rasterizer_, | 68 | QueryCache::QueryCache(VideoCore::RasterizerInterface& rasterizer_, const Device& device_, |
| 69 | Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, | 69 | Scheduler& scheduler_) |
| 70 | const Device& device_, Scheduler& scheduler_) | 70 | : QueryCacheBase{rasterizer_}, device{device_}, scheduler{scheduler_}, |
| 71 | : QueryCacheBase{rasterizer_, maxwell3d_, gpu_memory_}, device{device_}, scheduler{scheduler_}, | ||
| 72 | query_pools{ | 71 | query_pools{ |
| 73 | QueryPool{device_, scheduler_, QueryType::SamplesPassed}, | 72 | QueryPool{device_, scheduler_, QueryType::SamplesPassed}, |
| 74 | } {} | 73 | } {} |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.h b/src/video_core/renderer_vulkan/vk_query_cache.h index b0d86c4f8..26762ee09 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.h +++ b/src/video_core/renderer_vulkan/vk_query_cache.h | |||
| @@ -52,9 +52,8 @@ private: | |||
| 52 | class QueryCache final | 52 | class QueryCache final |
| 53 | : public VideoCommon::QueryCacheBase<QueryCache, CachedQuery, CounterStream, HostCounter> { | 53 | : public VideoCommon::QueryCacheBase<QueryCache, CachedQuery, CounterStream, HostCounter> { |
| 54 | public: | 54 | public: |
| 55 | explicit QueryCache(VideoCore::RasterizerInterface& rasterizer_, | 55 | explicit QueryCache(VideoCore::RasterizerInterface& rasterizer_, const Device& device_, |
| 56 | Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, | 56 | Scheduler& scheduler_); |
| 57 | const Device& device_, Scheduler& scheduler_); | ||
| 58 | ~QueryCache(); | 57 | ~QueryCache(); |
| 59 | 58 | ||
| 60 | std::pair<VkQueryPool, u32> AllocateQuery(VideoCore::QueryType type); | 59 | std::pair<VkQueryPool, u32> AllocateQuery(VideoCore::QueryType type); |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 7e40c2df1..acfd5da7d 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "common/microprofile.h" | 11 | #include "common/microprofile.h" |
| 12 | #include "common/scope_exit.h" | 12 | #include "common/scope_exit.h" |
| 13 | #include "common/settings.h" | 13 | #include "common/settings.h" |
| 14 | #include "video_core/control/channel_state.h" | ||
| 14 | #include "video_core/engines/kepler_compute.h" | 15 | #include "video_core/engines/kepler_compute.h" |
| 15 | #include "video_core/engines/maxwell_3d.h" | 16 | #include "video_core/engines/maxwell_3d.h" |
| 16 | #include "video_core/renderer_vulkan/blit_image.h" | 17 | #include "video_core/renderer_vulkan/blit_image.h" |
| @@ -148,14 +149,11 @@ DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_instan | |||
| 148 | } // Anonymous namespace | 149 | } // Anonymous namespace |
| 149 | 150 | ||
| 150 | RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 151 | RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| 151 | Tegra::MemoryManager& gpu_memory_, | ||
| 152 | Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_, | 152 | Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_, |
| 153 | const Device& device_, MemoryAllocator& memory_allocator_, | 153 | const Device& device_, MemoryAllocator& memory_allocator_, |
| 154 | StateTracker& state_tracker_, Scheduler& scheduler_) | 154 | StateTracker& state_tracker_, Scheduler& scheduler_) |
| 155 | : RasterizerAccelerated{cpu_memory_}, gpu{gpu_}, | 155 | : RasterizerAccelerated{cpu_memory_}, gpu{gpu_}, screen_info{screen_info_}, device{device_}, |
| 156 | gpu_memory{gpu_memory_}, maxwell3d{gpu.Maxwell3D()}, kepler_compute{gpu.KeplerCompute()}, | 156 | memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_}, |
| 157 | screen_info{screen_info_}, device{device_}, memory_allocator{memory_allocator_}, | ||
| 158 | state_tracker{state_tracker_}, scheduler{scheduler_}, | ||
| 159 | staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), | 157 | staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), |
| 160 | update_descriptor_queue(device, scheduler), | 158 | update_descriptor_queue(device, scheduler), |
| 161 | blit_image(device, scheduler, state_tracker, descriptor_pool), | 159 | blit_image(device, scheduler, state_tracker, descriptor_pool), |
| @@ -165,14 +163,13 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 165 | memory_allocator, staging_pool, | 163 | memory_allocator, staging_pool, |
| 166 | blit_image, astc_decoder_pass, | 164 | blit_image, astc_decoder_pass, |
| 167 | render_pass_cache}, | 165 | render_pass_cache}, |
| 168 | texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory), | 166 | texture_cache(texture_cache_runtime, *this), |
| 169 | buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, | 167 | buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, |
| 170 | update_descriptor_queue, descriptor_pool), | 168 | update_descriptor_queue, descriptor_pool), |
| 171 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), | 169 | buffer_cache(*this, cpu_memory_, buffer_cache_runtime), |
| 172 | pipeline_cache(*this, maxwell3d, kepler_compute, gpu_memory, device, scheduler, | 170 | pipeline_cache(*this, device, scheduler, descriptor_pool, update_descriptor_queue, |
| 173 | descriptor_pool, update_descriptor_queue, render_pass_cache, buffer_cache, | 171 | render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()), |
| 174 | texture_cache, gpu.ShaderNotify()), | 172 | query_cache{*this, device, scheduler}, accelerate_dma{buffer_cache}, |
| 175 | query_cache{*this, maxwell3d, gpu_memory, device, scheduler}, accelerate_dma{buffer_cache}, | ||
| 176 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), | 173 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), |
| 177 | wfi_event(device.GetLogical().CreateEvent()) { | 174 | wfi_event(device.GetLogical().CreateEvent()) { |
| 178 | scheduler.SetQueryCache(query_cache); | 175 | scheduler.SetQueryCache(query_cache); |
| @@ -193,14 +190,16 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 193 | return; | 190 | return; |
| 194 | } | 191 | } |
| 195 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; | 192 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; |
| 193 | // update engine as channel may be different. | ||
| 194 | pipeline->SetEngine(maxwell3d, gpu_memory); | ||
| 196 | pipeline->Configure(is_indexed); | 195 | pipeline->Configure(is_indexed); |
| 197 | 196 | ||
| 198 | BeginTransformFeedback(); | 197 | BeginTransformFeedback(); |
| 199 | 198 | ||
| 200 | UpdateDynamicStates(); | 199 | UpdateDynamicStates(); |
| 201 | 200 | ||
| 202 | const auto& regs{maxwell3d.regs}; | 201 | const auto& regs{maxwell3d->regs}; |
| 203 | const u32 num_instances{maxwell3d.mme_draw.instance_count}; | 202 | const u32 num_instances{maxwell3d->mme_draw.instance_count}; |
| 204 | const DrawParams draw_params{MakeDrawParams(regs, num_instances, is_instanced, is_indexed)}; | 203 | const DrawParams draw_params{MakeDrawParams(regs, num_instances, is_instanced, is_indexed)}; |
| 205 | scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) { | 204 | scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) { |
| 206 | if (draw_params.is_indexed) { | 205 | if (draw_params.is_indexed) { |
| @@ -218,14 +217,14 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 218 | void RasterizerVulkan::Clear() { | 217 | void RasterizerVulkan::Clear() { |
| 219 | MICROPROFILE_SCOPE(Vulkan_Clearing); | 218 | MICROPROFILE_SCOPE(Vulkan_Clearing); |
| 220 | 219 | ||
| 221 | if (!maxwell3d.ShouldExecute()) { | 220 | if (!maxwell3d->ShouldExecute()) { |
| 222 | return; | 221 | return; |
| 223 | } | 222 | } |
| 224 | FlushWork(); | 223 | FlushWork(); |
| 225 | 224 | ||
| 226 | query_cache.UpdateCounters(); | 225 | query_cache.UpdateCounters(); |
| 227 | 226 | ||
| 228 | auto& regs = maxwell3d.regs; | 227 | auto& regs = maxwell3d->regs; |
| 229 | const bool use_color = regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || | 228 | const bool use_color = regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || |
| 230 | regs.clear_buffers.A; | 229 | regs.clear_buffers.A; |
| 231 | const bool use_depth = regs.clear_buffers.Z; | 230 | const bool use_depth = regs.clear_buffers.Z; |
| @@ -248,8 +247,15 @@ void RasterizerVulkan::Clear() { | |||
| 248 | } | 247 | } |
| 249 | UpdateViewportsState(regs); | 248 | UpdateViewportsState(regs); |
| 250 | 249 | ||
| 250 | VkRect2D default_scissor; | ||
| 251 | default_scissor.offset.x = 0; | ||
| 252 | default_scissor.offset.y = 0; | ||
| 253 | default_scissor.extent.width = std::numeric_limits<s32>::max(); | ||
| 254 | default_scissor.extent.height = std::numeric_limits<s32>::max(); | ||
| 255 | |||
| 251 | VkClearRect clear_rect{ | 256 | VkClearRect clear_rect{ |
| 252 | .rect = GetScissorState(regs, 0, up_scale, down_shift), | 257 | .rect = regs.clear_flags.scissor ? GetScissorState(regs, 0, up_scale, down_shift) |
| 258 | : default_scissor, | ||
| 253 | .baseArrayLayer = regs.clear_buffers.layer, | 259 | .baseArrayLayer = regs.clear_buffers.layer, |
| 254 | .layerCount = 1, | 260 | .layerCount = 1, |
| 255 | }; | 261 | }; |
| @@ -339,9 +345,9 @@ void RasterizerVulkan::DispatchCompute() { | |||
| 339 | return; | 345 | return; |
| 340 | } | 346 | } |
| 341 | std::scoped_lock lock{texture_cache.mutex, buffer_cache.mutex}; | 347 | std::scoped_lock lock{texture_cache.mutex, buffer_cache.mutex}; |
| 342 | pipeline->Configure(kepler_compute, gpu_memory, scheduler, buffer_cache, texture_cache); | 348 | pipeline->Configure(*kepler_compute, *gpu_memory, scheduler, buffer_cache, texture_cache); |
| 343 | 349 | ||
| 344 | const auto& qmd{kepler_compute.launch_description}; | 350 | const auto& qmd{kepler_compute->launch_description}; |
| 345 | const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z}; | 351 | const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z}; |
| 346 | scheduler.RequestOutsideRenderPassOperationContext(); | 352 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 347 | scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); }); | 353 | scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); }); |
| @@ -422,7 +428,7 @@ void RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) { | |||
| 422 | } | 428 | } |
| 423 | } | 429 | } |
| 424 | 430 | ||
| 425 | void RasterizerVulkan::SyncGuestHost() { | 431 | void RasterizerVulkan::InvalidateGPUCache() { |
| 426 | pipeline_cache.SyncGuestHost(); | 432 | pipeline_cache.SyncGuestHost(); |
| 427 | { | 433 | { |
| 428 | std::scoped_lock lock{buffer_cache.mutex}; | 434 | std::scoped_lock lock{buffer_cache.mutex}; |
| @@ -442,40 +448,30 @@ void RasterizerVulkan::UnmapMemory(VAddr addr, u64 size) { | |||
| 442 | pipeline_cache.OnCPUWrite(addr, size); | 448 | pipeline_cache.OnCPUWrite(addr, size); |
| 443 | } | 449 | } |
| 444 | 450 | ||
| 445 | void RasterizerVulkan::ModifyGPUMemory(GPUVAddr addr, u64 size) { | 451 | void RasterizerVulkan::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) { |
| 446 | { | 452 | { |
| 447 | std::scoped_lock lock{texture_cache.mutex}; | 453 | std::scoped_lock lock{texture_cache.mutex}; |
| 448 | texture_cache.UnmapGPUMemory(addr, size); | 454 | texture_cache.UnmapGPUMemory(as_id, addr, size); |
| 449 | } | 455 | } |
| 450 | } | 456 | } |
| 451 | 457 | ||
| 452 | void RasterizerVulkan::SignalSemaphore(GPUVAddr addr, u32 value) { | 458 | void RasterizerVulkan::SignalFence(std::function<void()>&& func) { |
| 453 | if (!gpu.IsAsync()) { | 459 | fence_manager.SignalFence(std::move(func)); |
| 454 | gpu_memory.Write<u32>(addr, value); | 460 | } |
| 455 | return; | 461 | |
| 456 | } | 462 | void RasterizerVulkan::SyncOperation(std::function<void()>&& func) { |
| 457 | fence_manager.SignalSemaphore(addr, value); | 463 | fence_manager.SyncOperation(std::move(func)); |
| 458 | } | 464 | } |
| 459 | 465 | ||
| 460 | void RasterizerVulkan::SignalSyncPoint(u32 value) { | 466 | void RasterizerVulkan::SignalSyncPoint(u32 value) { |
| 461 | if (!gpu.IsAsync()) { | ||
| 462 | gpu.IncrementSyncPoint(value); | ||
| 463 | return; | ||
| 464 | } | ||
| 465 | fence_manager.SignalSyncPoint(value); | 467 | fence_manager.SignalSyncPoint(value); |
| 466 | } | 468 | } |
| 467 | 469 | ||
| 468 | void RasterizerVulkan::SignalReference() { | 470 | void RasterizerVulkan::SignalReference() { |
| 469 | if (!gpu.IsAsync()) { | ||
| 470 | return; | ||
| 471 | } | ||
| 472 | fence_manager.SignalOrdering(); | 471 | fence_manager.SignalOrdering(); |
| 473 | } | 472 | } |
| 474 | 473 | ||
| 475 | void RasterizerVulkan::ReleaseFences() { | 474 | void RasterizerVulkan::ReleaseFences() { |
| 476 | if (!gpu.IsAsync()) { | ||
| 477 | return; | ||
| 478 | } | ||
| 479 | fence_manager.WaitPendingFences(); | 475 | fence_manager.WaitPendingFences(); |
| 480 | } | 476 | } |
| 481 | 477 | ||
| @@ -552,13 +548,13 @@ Tegra::Engines::AccelerateDMAInterface& RasterizerVulkan::AccessAccelerateDMA() | |||
| 552 | } | 548 | } |
| 553 | 549 | ||
| 554 | void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | 550 | void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, |
| 555 | std::span<u8> memory) { | 551 | std::span<const u8> memory) { |
| 556 | auto cpu_addr = gpu_memory.GpuToCpuAddress(address); | 552 | auto cpu_addr = gpu_memory->GpuToCpuAddress(address); |
| 557 | if (!cpu_addr) [[unlikely]] { | 553 | if (!cpu_addr) [[unlikely]] { |
| 558 | gpu_memory.WriteBlock(address, memory.data(), copy_size); | 554 | gpu_memory->WriteBlock(address, memory.data(), copy_size); |
| 559 | return; | 555 | return; |
| 560 | } | 556 | } |
| 561 | gpu_memory.WriteBlockUnsafe(address, memory.data(), copy_size); | 557 | gpu_memory->WriteBlockUnsafe(address, memory.data(), copy_size); |
| 562 | { | 558 | { |
| 563 | std::unique_lock<std::mutex> lock{buffer_cache.mutex}; | 559 | std::unique_lock<std::mutex> lock{buffer_cache.mutex}; |
| 564 | if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) { | 560 | if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) { |
| @@ -627,7 +623,7 @@ bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 | |||
| 627 | } | 623 | } |
| 628 | 624 | ||
| 629 | void RasterizerVulkan::UpdateDynamicStates() { | 625 | void RasterizerVulkan::UpdateDynamicStates() { |
| 630 | auto& regs = maxwell3d.regs; | 626 | auto& regs = maxwell3d->regs; |
| 631 | UpdateViewportsState(regs); | 627 | UpdateViewportsState(regs); |
| 632 | UpdateScissorsState(regs); | 628 | UpdateScissorsState(regs); |
| 633 | UpdateDepthBias(regs); | 629 | UpdateDepthBias(regs); |
| @@ -651,7 +647,7 @@ void RasterizerVulkan::UpdateDynamicStates() { | |||
| 651 | } | 647 | } |
| 652 | 648 | ||
| 653 | void RasterizerVulkan::BeginTransformFeedback() { | 649 | void RasterizerVulkan::BeginTransformFeedback() { |
| 654 | const auto& regs = maxwell3d.regs; | 650 | const auto& regs = maxwell3d->regs; |
| 655 | if (regs.tfb_enabled == 0) { | 651 | if (regs.tfb_enabled == 0) { |
| 656 | return; | 652 | return; |
| 657 | } | 653 | } |
| @@ -667,7 +663,7 @@ void RasterizerVulkan::BeginTransformFeedback() { | |||
| 667 | } | 663 | } |
| 668 | 664 | ||
| 669 | void RasterizerVulkan::EndTransformFeedback() { | 665 | void RasterizerVulkan::EndTransformFeedback() { |
| 670 | const auto& regs = maxwell3d.regs; | 666 | const auto& regs = maxwell3d->regs; |
| 671 | if (regs.tfb_enabled == 0) { | 667 | if (regs.tfb_enabled == 0) { |
| 672 | return; | 668 | return; |
| 673 | } | 669 | } |
| @@ -917,7 +913,7 @@ void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& | |||
| 917 | } | 913 | } |
| 918 | 914 | ||
| 919 | void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) { | 915 | void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) { |
| 920 | auto& dirty{maxwell3d.dirty.flags}; | 916 | auto& dirty{maxwell3d->dirty.flags}; |
| 921 | if (!dirty[Dirty::VertexInput]) { | 917 | if (!dirty[Dirty::VertexInput]) { |
| 922 | return; | 918 | return; |
| 923 | } | 919 | } |
| @@ -974,4 +970,41 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) | |||
| 974 | }); | 970 | }); |
| 975 | } | 971 | } |
| 976 | 972 | ||
| 973 | void RasterizerVulkan::InitializeChannel(Tegra::Control::ChannelState& channel) { | ||
| 974 | CreateChannel(channel); | ||
| 975 | { | ||
| 976 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; | ||
| 977 | texture_cache.CreateChannel(channel); | ||
| 978 | buffer_cache.CreateChannel(channel); | ||
| 979 | } | ||
| 980 | pipeline_cache.CreateChannel(channel); | ||
| 981 | query_cache.CreateChannel(channel); | ||
| 982 | state_tracker.SetupTables(channel); | ||
| 983 | } | ||
| 984 | |||
| 985 | void RasterizerVulkan::BindChannel(Tegra::Control::ChannelState& channel) { | ||
| 986 | const s32 channel_id = channel.bind_id; | ||
| 987 | BindToChannel(channel_id); | ||
| 988 | { | ||
| 989 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; | ||
| 990 | texture_cache.BindToChannel(channel_id); | ||
| 991 | buffer_cache.BindToChannel(channel_id); | ||
| 992 | } | ||
| 993 | pipeline_cache.BindToChannel(channel_id); | ||
| 994 | query_cache.BindToChannel(channel_id); | ||
| 995 | state_tracker.ChangeChannel(channel); | ||
| 996 | state_tracker.InvalidateState(); | ||
| 997 | } | ||
| 998 | |||
| 999 | void RasterizerVulkan::ReleaseChannel(s32 channel_id) { | ||
| 1000 | EraseChannel(channel_id); | ||
| 1001 | { | ||
| 1002 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; | ||
| 1003 | texture_cache.EraseChannel(channel_id); | ||
| 1004 | buffer_cache.EraseChannel(channel_id); | ||
| 1005 | } | ||
| 1006 | pipeline_cache.EraseChannel(channel_id); | ||
| 1007 | query_cache.EraseChannel(channel_id); | ||
| 1008 | } | ||
| 1009 | |||
| 977 | } // namespace Vulkan | 1010 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 0370ea39b..4cde3c983 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <boost/container/static_vector.hpp> | 8 | #include <boost/container/static_vector.hpp> |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "video_core/control/channel_state_cache.h" | ||
| 11 | #include "video_core/engines/maxwell_dma.h" | 12 | #include "video_core/engines/maxwell_dma.h" |
| 12 | #include "video_core/rasterizer_accelerated.h" | 13 | #include "video_core/rasterizer_accelerated.h" |
| 13 | #include "video_core/rasterizer_interface.h" | 14 | #include "video_core/rasterizer_interface.h" |
| @@ -54,13 +55,13 @@ private: | |||
| 54 | BufferCache& buffer_cache; | 55 | BufferCache& buffer_cache; |
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| 57 | class RasterizerVulkan final : public VideoCore::RasterizerAccelerated { | 58 | class RasterizerVulkan final : public VideoCore::RasterizerAccelerated, |
| 59 | protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { | ||
| 58 | public: | 60 | public: |
| 59 | explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 61 | explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| 60 | Tegra::MemoryManager& gpu_memory_, Core::Memory::Memory& cpu_memory_, | 62 | Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_, |
| 61 | ScreenInfo& screen_info_, const Device& device_, | 63 | const Device& device_, MemoryAllocator& memory_allocator_, |
| 62 | MemoryAllocator& memory_allocator_, StateTracker& state_tracker_, | 64 | StateTracker& state_tracker_, Scheduler& scheduler_); |
| 63 | Scheduler& scheduler_); | ||
| 64 | ~RasterizerVulkan() override; | 65 | ~RasterizerVulkan() override; |
| 65 | 66 | ||
| 66 | void Draw(bool is_indexed, bool is_instanced) override; | 67 | void Draw(bool is_indexed, bool is_instanced) override; |
| @@ -75,10 +76,11 @@ public: | |||
| 75 | bool MustFlushRegion(VAddr addr, u64 size) override; | 76 | bool MustFlushRegion(VAddr addr, u64 size) override; |
| 76 | void InvalidateRegion(VAddr addr, u64 size) override; | 77 | void InvalidateRegion(VAddr addr, u64 size) override; |
| 77 | void OnCPUWrite(VAddr addr, u64 size) override; | 78 | void OnCPUWrite(VAddr addr, u64 size) override; |
| 78 | void SyncGuestHost() override; | 79 | void InvalidateGPUCache() override; |
| 79 | void UnmapMemory(VAddr addr, u64 size) override; | 80 | void UnmapMemory(VAddr addr, u64 size) override; |
| 80 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; | 81 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; |
| 81 | void SignalSemaphore(GPUVAddr addr, u32 value) override; | 82 | void SignalFence(std::function<void()>&& func) override; |
| 83 | void SyncOperation(std::function<void()>&& func) override; | ||
| 82 | void SignalSyncPoint(u32 value) override; | 84 | void SignalSyncPoint(u32 value) override; |
| 83 | void SignalReference() override; | 85 | void SignalReference() override; |
| 84 | void ReleaseFences() override; | 86 | void ReleaseFences() override; |
| @@ -93,12 +95,18 @@ public: | |||
| 93 | const Tegra::Engines::Fermi2D::Config& copy_config) override; | 95 | const Tegra::Engines::Fermi2D::Config& copy_config) override; |
| 94 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | 96 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; |
| 95 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | 97 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, |
| 96 | std::span<u8> memory) override; | 98 | std::span<const u8> memory) override; |
| 97 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | 99 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, |
| 98 | u32 pixel_stride) override; | 100 | u32 pixel_stride) override; |
| 99 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 101 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
| 100 | const VideoCore::DiskResourceLoadCallback& callback) override; | 102 | const VideoCore::DiskResourceLoadCallback& callback) override; |
| 101 | 103 | ||
| 104 | void InitializeChannel(Tegra::Control::ChannelState& channel) override; | ||
| 105 | |||
| 106 | void BindChannel(Tegra::Control::ChannelState& channel) override; | ||
| 107 | |||
| 108 | void ReleaseChannel(s32 channel_id) override; | ||
| 109 | |||
| 102 | private: | 110 | private: |
| 103 | static constexpr size_t MAX_TEXTURES = 192; | 111 | static constexpr size_t MAX_TEXTURES = 192; |
| 104 | static constexpr size_t MAX_IMAGES = 48; | 112 | static constexpr size_t MAX_IMAGES = 48; |
| @@ -134,9 +142,6 @@ private: | |||
| 134 | void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); | 142 | void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); |
| 135 | 143 | ||
| 136 | Tegra::GPU& gpu; | 144 | Tegra::GPU& gpu; |
| 137 | Tegra::MemoryManager& gpu_memory; | ||
| 138 | Tegra::Engines::Maxwell3D& maxwell3d; | ||
| 139 | Tegra::Engines::KeplerCompute& kepler_compute; | ||
| 140 | 145 | ||
| 141 | ScreenInfo& screen_info; | 146 | ScreenInfo& screen_info; |
| 142 | const Device& device; | 147 | const Device& device; |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index 9ad096431..f234e1a31 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | 7 | ||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "video_core/control/channel_state.h" | ||
| 10 | #include "video_core/dirty_flags.h" | 11 | #include "video_core/dirty_flags.h" |
| 11 | #include "video_core/engines/maxwell_3d.h" | 12 | #include "video_core/engines/maxwell_3d.h" |
| 12 | #include "video_core/gpu.h" | ||
| 13 | #include "video_core/renderer_vulkan/vk_state_tracker.h" | 13 | #include "video_core/renderer_vulkan/vk_state_tracker.h" |
| 14 | 14 | ||
| 15 | #define OFF(field_name) MAXWELL3D_REG_INDEX(field_name) | 15 | #define OFF(field_name) MAXWELL3D_REG_INDEX(field_name) |
| @@ -174,9 +174,8 @@ void SetupDirtyVertexBindings(Tables& tables) { | |||
| 174 | } | 174 | } |
| 175 | } // Anonymous namespace | 175 | } // Anonymous namespace |
| 176 | 176 | ||
| 177 | StateTracker::StateTracker(Tegra::GPU& gpu) | 177 | void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { |
| 178 | : flags{gpu.Maxwell3D().dirty.flags}, invalidation_flags{MakeInvalidationFlags()} { | 178 | auto& tables{channel_state.maxwell_3d->dirty.tables}; |
| 179 | auto& tables{gpu.Maxwell3D().dirty.tables}; | ||
| 180 | SetupDirtyFlags(tables); | 179 | SetupDirtyFlags(tables); |
| 181 | SetupDirtyViewports(tables); | 180 | SetupDirtyViewports(tables); |
| 182 | SetupDirtyScissors(tables); | 181 | SetupDirtyScissors(tables); |
| @@ -199,4 +198,15 @@ StateTracker::StateTracker(Tegra::GPU& gpu) | |||
| 199 | SetupDirtyVertexBindings(tables); | 198 | SetupDirtyVertexBindings(tables); |
| 200 | } | 199 | } |
| 201 | 200 | ||
| 201 | void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) { | ||
| 202 | flags = &channel_state.maxwell_3d->dirty.flags; | ||
| 203 | } | ||
| 204 | |||
| 205 | void StateTracker::InvalidateState() { | ||
| 206 | flags->set(); | ||
| 207 | } | ||
| 208 | |||
| 209 | StateTracker::StateTracker() | ||
| 210 | : flags{&default_flags}, default_flags{}, invalidation_flags{MakeInvalidationFlags()} {} | ||
| 211 | |||
| 202 | } // namespace Vulkan | 212 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index a85bc1c10..2296dea60 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h | |||
| @@ -10,6 +10,12 @@ | |||
| 10 | #include "video_core/dirty_flags.h" | 10 | #include "video_core/dirty_flags.h" |
| 11 | #include "video_core/engines/maxwell_3d.h" | 11 | #include "video_core/engines/maxwell_3d.h" |
| 12 | 12 | ||
| 13 | namespace Tegra { | ||
| 14 | namespace Control { | ||
| 15 | struct ChannelState; | ||
| 16 | } | ||
| 17 | } // namespace Tegra | ||
| 18 | |||
| 13 | namespace Vulkan { | 19 | namespace Vulkan { |
| 14 | 20 | ||
| 15 | namespace Dirty { | 21 | namespace Dirty { |
| @@ -53,19 +59,19 @@ class StateTracker { | |||
| 53 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 59 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 54 | 60 | ||
| 55 | public: | 61 | public: |
| 56 | explicit StateTracker(Tegra::GPU& gpu); | 62 | explicit StateTracker(); |
| 57 | 63 | ||
| 58 | void InvalidateCommandBufferState() { | 64 | void InvalidateCommandBufferState() { |
| 59 | flags |= invalidation_flags; | 65 | (*flags) |= invalidation_flags; |
| 60 | current_topology = INVALID_TOPOLOGY; | 66 | current_topology = INVALID_TOPOLOGY; |
| 61 | } | 67 | } |
| 62 | 68 | ||
| 63 | void InvalidateViewports() { | 69 | void InvalidateViewports() { |
| 64 | flags[Dirty::Viewports] = true; | 70 | (*flags)[Dirty::Viewports] = true; |
| 65 | } | 71 | } |
| 66 | 72 | ||
| 67 | void InvalidateScissors() { | 73 | void InvalidateScissors() { |
| 68 | flags[Dirty::Scissors] = true; | 74 | (*flags)[Dirty::Scissors] = true; |
| 69 | } | 75 | } |
| 70 | 76 | ||
| 71 | bool TouchViewports() { | 77 | bool TouchViewports() { |
| @@ -139,16 +145,23 @@ public: | |||
| 139 | return has_changed; | 145 | return has_changed; |
| 140 | } | 146 | } |
| 141 | 147 | ||
| 148 | void SetupTables(Tegra::Control::ChannelState& channel_state); | ||
| 149 | |||
| 150 | void ChangeChannel(Tegra::Control::ChannelState& channel_state); | ||
| 151 | |||
| 152 | void InvalidateState(); | ||
| 153 | |||
| 142 | private: | 154 | private: |
| 143 | static constexpr auto INVALID_TOPOLOGY = static_cast<Maxwell::PrimitiveTopology>(~0u); | 155 | static constexpr auto INVALID_TOPOLOGY = static_cast<Maxwell::PrimitiveTopology>(~0u); |
| 144 | 156 | ||
| 145 | bool Exchange(std::size_t id, bool new_value) const noexcept { | 157 | bool Exchange(std::size_t id, bool new_value) const noexcept { |
| 146 | const bool is_dirty = flags[id]; | 158 | const bool is_dirty = (*flags)[id]; |
| 147 | flags[id] = new_value; | 159 | (*flags)[id] = new_value; |
| 148 | return is_dirty; | 160 | return is_dirty; |
| 149 | } | 161 | } |
| 150 | 162 | ||
| 151 | Tegra::Engines::Maxwell3D::DirtyState::Flags& flags; | 163 | Tegra::Engines::Maxwell3D::DirtyState::Flags* flags; |
| 164 | Tegra::Engines::Maxwell3D::DirtyState::Flags default_flags; | ||
| 152 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; | 165 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; |
| 153 | Maxwell::PrimitiveTopology current_topology = INVALID_TOPOLOGY; | 166 | Maxwell::PrimitiveTopology current_topology = INVALID_TOPOLOGY; |
| 154 | }; | 167 | }; |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index a69ae7725..706d9ba74 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -36,7 +36,8 @@ VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) { | |||
| 36 | // Mailbox (triple buffering) doesn't lock the application like fifo (vsync), | 36 | // Mailbox (triple buffering) doesn't lock the application like fifo (vsync), |
| 37 | // prefer it if vsync option is not selected | 37 | // prefer it if vsync option is not selected |
| 38 | const auto found_mailbox = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR); | 38 | const auto found_mailbox = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR); |
| 39 | if (found_mailbox != modes.end() && !Settings::values.use_vsync.GetValue()) { | 39 | if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Borderless && |
| 40 | found_mailbox != modes.end() && !Settings::values.use_vsync.GetValue()) { | ||
| 40 | return VK_PRESENT_MODE_MAILBOX_KHR; | 41 | return VK_PRESENT_MODE_MAILBOX_KHR; |
| 41 | } | 42 | } |
| 42 | if (!Settings::values.use_speed_limit.GetValue()) { | 43 | if (!Settings::values.use_speed_limit.GetValue()) { |
| @@ -156,8 +157,16 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u3 | |||
| 156 | present_mode = ChooseSwapPresentMode(present_modes); | 157 | present_mode = ChooseSwapPresentMode(present_modes); |
| 157 | 158 | ||
| 158 | u32 requested_image_count{capabilities.minImageCount + 1}; | 159 | u32 requested_image_count{capabilities.minImageCount + 1}; |
| 159 | if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) { | 160 | // Ensure Tripple buffering if possible. |
| 160 | requested_image_count = capabilities.maxImageCount; | 161 | if (capabilities.maxImageCount > 0) { |
| 162 | if (requested_image_count > capabilities.maxImageCount) { | ||
| 163 | requested_image_count = capabilities.maxImageCount; | ||
| 164 | } else { | ||
| 165 | requested_image_count = | ||
| 166 | std::max(requested_image_count, std::min(3U, capabilities.maxImageCount)); | ||
| 167 | } | ||
| 168 | } else { | ||
| 169 | requested_image_count = std::max(requested_image_count, 3U); | ||
| 161 | } | 170 | } |
| 162 | VkSwapchainCreateInfoKHR swapchain_ci{ | 171 | VkSwapchainCreateInfoKHR swapchain_ci{ |
| 163 | .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, | 172 | .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index caca79d79..305ad8aee 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -592,7 +592,7 @@ void TryTransformSwizzleIfNeeded(PixelFormat format, std::array<SwizzleSource, 4 | |||
| 592 | case PixelFormat::A5B5G5R1_UNORM: | 592 | case PixelFormat::A5B5G5R1_UNORM: |
| 593 | std::ranges::transform(swizzle, swizzle.begin(), SwapSpecial); | 593 | std::ranges::transform(swizzle, swizzle.begin(), SwapSpecial); |
| 594 | break; | 594 | break; |
| 595 | case PixelFormat::R4G4_UNORM: | 595 | case PixelFormat::G4R4_UNORM: |
| 596 | std::ranges::transform(swizzle, swizzle.begin(), SwapGreenRed); | 596 | std::ranges::transform(swizzle, swizzle.begin(), SwapGreenRed); |
| 597 | break; | 597 | break; |
| 598 | default: | 598 | default: |
| @@ -1474,13 +1474,14 @@ bool Image::BlitScaleHelper(bool scale_up) { | |||
| 1474 | }; | 1474 | }; |
| 1475 | const VkExtent2D extent{ | 1475 | const VkExtent2D extent{ |
| 1476 | .width = std::max(scaled_width, info.size.width), | 1476 | .width = std::max(scaled_width, info.size.width), |
| 1477 | .height = std::max(scaled_height, info.size.width), | 1477 | .height = std::max(scaled_height, info.size.height), |
| 1478 | }; | 1478 | }; |
| 1479 | 1479 | ||
| 1480 | auto* view_ptr = blit_view.get(); | 1480 | auto* view_ptr = blit_view.get(); |
| 1481 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { | 1481 | if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) { |
| 1482 | if (!blit_framebuffer) { | 1482 | if (!blit_framebuffer) { |
| 1483 | blit_framebuffer = std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent); | 1483 | blit_framebuffer = |
| 1484 | std::make_unique<Framebuffer>(*runtime, view_ptr, nullptr, extent, scale_up); | ||
| 1484 | } | 1485 | } |
| 1485 | const auto color_view = blit_view->Handle(Shader::TextureType::Color2D); | 1486 | const auto color_view = blit_view->Handle(Shader::TextureType::Color2D); |
| 1486 | 1487 | ||
| @@ -1488,7 +1489,8 @@ bool Image::BlitScaleHelper(bool scale_up) { | |||
| 1488 | src_region, operation, BLIT_OPERATION); | 1489 | src_region, operation, BLIT_OPERATION); |
| 1489 | } else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { | 1490 | } else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { |
| 1490 | if (!blit_framebuffer) { | 1491 | if (!blit_framebuffer) { |
| 1491 | blit_framebuffer = std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent); | 1492 | blit_framebuffer = |
| 1493 | std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent, scale_up); | ||
| 1492 | } | 1494 | } |
| 1493 | runtime->blit_image_helper.BlitDepthStencil(blit_framebuffer.get(), blit_view->DepthView(), | 1495 | runtime->blit_image_helper.BlitDepthStencil(blit_framebuffer.get(), blit_view->DepthView(), |
| 1494 | blit_view->StencilView(), dst_region, | 1496 | blit_view->StencilView(), dst_region, |
| @@ -1756,34 +1758,42 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM | |||
| 1756 | .width = key.size.width, | 1758 | .width = key.size.width, |
| 1757 | .height = key.size.height, | 1759 | .height = key.size.height, |
| 1758 | }} { | 1760 | }} { |
| 1759 | CreateFramebuffer(runtime, color_buffers, depth_buffer); | 1761 | CreateFramebuffer(runtime, color_buffers, depth_buffer, key.is_rescaled); |
| 1760 | if (runtime.device.HasDebuggingToolAttached()) { | 1762 | if (runtime.device.HasDebuggingToolAttached()) { |
| 1761 | framebuffer.SetObjectNameEXT(VideoCommon::Name(key).c_str()); | 1763 | framebuffer.SetObjectNameEXT(VideoCommon::Name(key).c_str()); |
| 1762 | } | 1764 | } |
| 1763 | } | 1765 | } |
| 1764 | 1766 | ||
| 1765 | Framebuffer::Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, | 1767 | Framebuffer::Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, |
| 1766 | ImageView* depth_buffer, VkExtent2D extent) | 1768 | ImageView* depth_buffer, VkExtent2D extent, bool is_rescaled) |
| 1767 | : render_area{extent} { | 1769 | : render_area{extent} { |
| 1768 | std::array<ImageView*, NUM_RT> color_buffers{color_buffer}; | 1770 | std::array<ImageView*, NUM_RT> color_buffers{color_buffer}; |
| 1769 | CreateFramebuffer(runtime, color_buffers, depth_buffer); | 1771 | CreateFramebuffer(runtime, color_buffers, depth_buffer, is_rescaled); |
| 1770 | } | 1772 | } |
| 1771 | 1773 | ||
| 1772 | Framebuffer::~Framebuffer() = default; | 1774 | Framebuffer::~Framebuffer() = default; |
| 1773 | 1775 | ||
| 1774 | void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, | 1776 | void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, |
| 1775 | std::span<ImageView*, NUM_RT> color_buffers, | 1777 | std::span<ImageView*, NUM_RT> color_buffers, |
| 1776 | ImageView* depth_buffer) { | 1778 | ImageView* depth_buffer, bool is_rescaled) { |
| 1777 | std::vector<VkImageView> attachments; | 1779 | std::vector<VkImageView> attachments; |
| 1778 | RenderPassKey renderpass_key{}; | 1780 | RenderPassKey renderpass_key{}; |
| 1779 | s32 num_layers = 1; | 1781 | s32 num_layers = 1; |
| 1780 | 1782 | ||
| 1783 | const auto& resolution = runtime.resolution; | ||
| 1784 | |||
| 1785 | u32 width = 0; | ||
| 1786 | u32 height = 0; | ||
| 1781 | for (size_t index = 0; index < NUM_RT; ++index) { | 1787 | for (size_t index = 0; index < NUM_RT; ++index) { |
| 1782 | const ImageView* const color_buffer = color_buffers[index]; | 1788 | const ImageView* const color_buffer = color_buffers[index]; |
| 1783 | if (!color_buffer) { | 1789 | if (!color_buffer) { |
| 1784 | renderpass_key.color_formats[index] = PixelFormat::Invalid; | 1790 | renderpass_key.color_formats[index] = PixelFormat::Invalid; |
| 1785 | continue; | 1791 | continue; |
| 1786 | } | 1792 | } |
| 1793 | width = std::max(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width) | ||
| 1794 | : color_buffer->size.width); | ||
| 1795 | height = std::max(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height) | ||
| 1796 | : color_buffer->size.height); | ||
| 1787 | attachments.push_back(color_buffer->RenderTarget()); | 1797 | attachments.push_back(color_buffer->RenderTarget()); |
| 1788 | renderpass_key.color_formats[index] = color_buffer->format; | 1798 | renderpass_key.color_formats[index] = color_buffer->format; |
| 1789 | num_layers = std::max(num_layers, color_buffer->range.extent.layers); | 1799 | num_layers = std::max(num_layers, color_buffer->range.extent.layers); |
| @@ -1794,6 +1804,10 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, | |||
| 1794 | } | 1804 | } |
| 1795 | const size_t num_colors = attachments.size(); | 1805 | const size_t num_colors = attachments.size(); |
| 1796 | if (depth_buffer) { | 1806 | if (depth_buffer) { |
| 1807 | width = std::max(width, is_rescaled ? resolution.ScaleUp(depth_buffer->size.width) | ||
| 1808 | : depth_buffer->size.width); | ||
| 1809 | height = std::max(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height) | ||
| 1810 | : depth_buffer->size.height); | ||
| 1797 | attachments.push_back(depth_buffer->RenderTarget()); | 1811 | attachments.push_back(depth_buffer->RenderTarget()); |
| 1798 | renderpass_key.depth_format = depth_buffer->format; | 1812 | renderpass_key.depth_format = depth_buffer->format; |
| 1799 | num_layers = std::max(num_layers, depth_buffer->range.extent.layers); | 1813 | num_layers = std::max(num_layers, depth_buffer->range.extent.layers); |
| @@ -1810,6 +1824,8 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, | |||
| 1810 | renderpass_key.samples = samples; | 1824 | renderpass_key.samples = samples; |
| 1811 | 1825 | ||
| 1812 | renderpass = runtime.render_pass_cache.Get(renderpass_key); | 1826 | renderpass = runtime.render_pass_cache.Get(renderpass_key); |
| 1827 | render_area.width = std::min(render_area.width, width); | ||
| 1828 | render_area.height = std::min(render_area.height, height); | ||
| 1813 | 1829 | ||
| 1814 | num_color_buffers = static_cast<u32>(num_colors); | 1830 | num_color_buffers = static_cast<u32>(num_colors); |
| 1815 | framebuffer = runtime.device.GetLogical().CreateFramebuffer({ | 1831 | framebuffer = runtime.device.GetLogical().CreateFramebuffer({ |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 69f06ee7b..0b7ac0df1 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -268,7 +268,7 @@ public: | |||
| 268 | ImageView* depth_buffer, const VideoCommon::RenderTargets& key); | 268 | ImageView* depth_buffer, const VideoCommon::RenderTargets& key); |
| 269 | 269 | ||
| 270 | explicit Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, | 270 | explicit Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, |
| 271 | ImageView* depth_buffer, VkExtent2D extent); | 271 | ImageView* depth_buffer, VkExtent2D extent, bool is_rescaled); |
| 272 | 272 | ||
| 273 | ~Framebuffer(); | 273 | ~Framebuffer(); |
| 274 | 274 | ||
| @@ -279,7 +279,8 @@ public: | |||
| 279 | Framebuffer& operator=(Framebuffer&&) = default; | 279 | Framebuffer& operator=(Framebuffer&&) = default; |
| 280 | 280 | ||
| 281 | void CreateFramebuffer(TextureCacheRuntime& runtime, | 281 | void CreateFramebuffer(TextureCacheRuntime& runtime, |
| 282 | std::span<ImageView*, NUM_RT> color_buffers, ImageView* depth_buffer); | 282 | std::span<ImageView*, NUM_RT> color_buffers, ImageView* depth_buffer, |
| 283 | bool is_rescaled = false); | ||
| 283 | 284 | ||
| 284 | [[nodiscard]] VkFramebuffer Handle() const noexcept { | 285 | [[nodiscard]] VkFramebuffer Handle() const noexcept { |
| 285 | return *framebuffer; | 286 | return *framebuffer; |