diff options
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r-- | src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | 15 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/fixed_pipeline_state.h | 8 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/maxwell_to_vk.cpp | 14 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/maxwell_to_vk.h | 4 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 8 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.h | 4 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 5 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 69 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.h | 17 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_scheduler.cpp | 21 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_scheduler.h | 42 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_state_tracker.cpp | 101 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_state_tracker.h | 79 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 1 |
14 files changed, 270 insertions, 118 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 4e3ff231e..2bb376555 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -112,19 +112,18 @@ constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs) const auto& clip = regs.view_volume_clip_control; const bool depth_clamp_enabled = clip.depth_clamp_near == 1 || clip.depth_clamp_far == 1; - Maxwell::Cull::FrontFace front_face = regs.cull.front_face; + Maxwell::FrontFace front_face = regs.front_face; if (regs.screen_y_control.triangle_rast_flip != 0 && regs.viewport_transform[0].scale_y > 0.0f) { - if (front_face == Maxwell::Cull::FrontFace::CounterClockWise) - front_face = Maxwell::Cull::FrontFace::ClockWise; - else if (front_face == Maxwell::Cull::FrontFace::ClockWise) - front_face = Maxwell::Cull::FrontFace::CounterClockWise; + if (front_face == Maxwell::FrontFace::CounterClockWise) + front_face = Maxwell::FrontFace::ClockWise; + else if (front_face == Maxwell::FrontFace::ClockWise) + front_face = Maxwell::FrontFace::CounterClockWise; } const bool gl_ndc = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; - return FixedPipelineState::Rasterizer(regs.cull.enabled, depth_bias_enabled, - depth_clamp_enabled, gl_ndc, regs.cull.cull_face, - front_face); + return FixedPipelineState::Rasterizer(regs.cull_test_enabled, depth_bias_enabled, + depth_clamp_enabled, gl_ndc, regs.cull_face, front_face); } } // Anonymous namespace diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 87056ef37..4c8ba7f90 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h @@ -171,8 +171,8 @@ struct FixedPipelineState { struct Rasterizer { constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool depth_clamp_enable, - bool ndc_minus_one_to_one, Maxwell::Cull::CullFace cull_face, - Maxwell::Cull::FrontFace front_face) + bool ndc_minus_one_to_one, Maxwell::CullFace cull_face, + Maxwell::FrontFace front_face) : cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable}, depth_clamp_enable{depth_clamp_enable}, ndc_minus_one_to_one{ndc_minus_one_to_one}, cull_face{cull_face}, front_face{front_face} {} @@ -182,8 +182,8 @@ struct FixedPipelineState { bool depth_bias_enable; bool depth_clamp_enable; bool ndc_minus_one_to_one; - Maxwell::Cull::CullFace cull_face; - Maxwell::Cull::FrontFace front_face; + Maxwell::CullFace cull_face; + Maxwell::FrontFace front_face; std::size_t Hash() const noexcept; diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 948d67d89..df3ac707c 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp @@ -586,24 +586,24 @@ vk::BlendFactor BlendFactor(Maxwell::Blend::Factor factor) { return {}; } -vk::FrontFace FrontFace(Maxwell::Cull::FrontFace front_face) { +vk::FrontFace FrontFace(Maxwell::FrontFace front_face) { switch (front_face) { - case Maxwell::Cull::FrontFace::ClockWise: + case Maxwell::FrontFace::ClockWise: return vk::FrontFace::eClockwise; - case Maxwell::Cull::FrontFace::CounterClockWise: + case Maxwell::FrontFace::CounterClockWise: return vk::FrontFace::eCounterClockwise; } UNIMPLEMENTED_MSG("Unimplemented front face={}", static_cast<u32>(front_face)); return {}; } -vk::CullModeFlags CullFace(Maxwell::Cull::CullFace cull_face) { +vk::CullModeFlags CullFace(Maxwell::CullFace cull_face) { switch (cull_face) { - case Maxwell::Cull::CullFace::Front: + case Maxwell::CullFace::Front: return vk::CullModeFlagBits::eFront; - case Maxwell::Cull::CullFace::Back: + case Maxwell::CullFace::Back: return vk::CullModeFlagBits::eBack; - case Maxwell::Cull::CullFace::FrontAndBack: + case Maxwell::CullFace::FrontAndBack: return vk::CullModeFlagBits::eFrontAndBack; } UNIMPLEMENTED_MSG("Unimplemented cull face={}", static_cast<u32>(cull_face)); diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.h b/src/video_core/renderer_vulkan/maxwell_to_vk.h index 7e9678b7b..24f6ab544 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.h +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.h @@ -54,9 +54,9 @@ vk::BlendOp BlendEquation(Maxwell::Blend::Equation equation); vk::BlendFactor BlendFactor(Maxwell::Blend::Factor factor); -vk::FrontFace FrontFace(Maxwell::Cull::FrontFace front_face); +vk::FrontFace FrontFace(Maxwell::FrontFace front_face); -vk::CullModeFlags CullFace(Maxwell::Cull::CullFace cull_face); +vk::CullModeFlags CullFace(Maxwell::CullFace cull_face); vk::ComponentSwizzle SwizzleSource(Tegra::Texture::SwizzleSource swizzle); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index ddc62bc97..42bb01418 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -27,6 +27,7 @@ #include "video_core/renderer_vulkan/vk_rasterizer.h" #include "video_core/renderer_vulkan/vk_resource_manager.h" #include "video_core/renderer_vulkan/vk_scheduler.h" +#include "video_core/renderer_vulkan/vk_state_tracker.h" #include "video_core/renderer_vulkan/vk_swapchain.h" namespace Vulkan { @@ -177,10 +178,13 @@ bool RendererVulkan::Init() { swapchain = std::make_unique<VKSwapchain>(surface, *device); swapchain->Create(framebuffer.width, framebuffer.height, false); - scheduler = std::make_unique<VKScheduler>(*device, *resource_manager); + state_tracker = std::make_unique<StateTracker>(system); + + scheduler = std::make_unique<VKScheduler>(*device, *resource_manager, *state_tracker); rasterizer = std::make_unique<RasterizerVulkan>(system, render_window, screen_info, *device, - *resource_manager, *memory_manager, *scheduler); + *resource_manager, *memory_manager, + *state_tracker, *scheduler); blit_screen = std::make_unique<VKBlitScreen>(system, render_window, *rasterizer, *device, *resource_manager, *memory_manager, *swapchain, diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index f513397f0..3da08d2e4 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -4,8 +4,10 @@ #pragma once +#include <memory> #include <optional> #include <vector> + #include "video_core/renderer_base.h" #include "video_core/renderer_vulkan/declarations.h" @@ -15,6 +17,7 @@ class System; namespace Vulkan { +class StateTracker; class VKBlitScreen; class VKDevice; class VKFence; @@ -61,6 +64,7 @@ private: std::unique_ptr<VKSwapchain> swapchain; std::unique_ptr<VKMemoryManager> memory_manager; std::unique_ptr<VKResourceManager> resource_manager; + std::unique_ptr<StateTracker> state_tracker; std::unique_ptr<VKScheduler> scheduler; std::unique_ptr<VKBlitScreen> blit_screen; }; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 696e4b291..144e1e007 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -188,11 +188,6 @@ VKPipelineCache::~VKPipelineCache() = default; std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() { const auto& gpu = system.GPU().Maxwell3D(); - auto& dirty = system.GPU().Maxwell3D().dirty.shaders; - if (!dirty) { - return last_shaders; - } - dirty = false; std::array<Shader, Maxwell::MaxShaderProgram> shaders; for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 3fe28c204..b402fb268 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -36,6 +36,7 @@ #include "video_core/renderer_vulkan/vk_sampler_cache.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" +#include "video_core/renderer_vulkan/vk_state_tracker.h" #include "video_core/renderer_vulkan/vk_texture_cache.h" #include "video_core/renderer_vulkan/vk_update_descriptor.h" @@ -280,10 +281,11 @@ void RasterizerVulkan::DrawParameters::Draw(vk::CommandBuffer cmdbuf, RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWindow& renderer, VKScreenInfo& screen_info, const VKDevice& device, VKResourceManager& resource_manager, - VKMemoryManager& memory_manager, VKScheduler& scheduler) + VKMemoryManager& memory_manager, StateTracker& state_tracker, + VKScheduler& scheduler) : RasterizerAccelerated{system.Memory()}, system{system}, render_window{renderer}, screen_info{screen_info}, device{device}, resource_manager{resource_manager}, - memory_manager{memory_manager}, scheduler{scheduler}, + memory_manager{memory_manager}, state_tracker{state_tracker}, scheduler{scheduler}, staging_pool(device, memory_manager, scheduler), descriptor_pool(device), update_descriptor_queue(device, scheduler), quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), @@ -548,6 +550,10 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, return true; } +void RasterizerVulkan::SetupDirtyFlags() { + state_tracker.Initialize(); +} + void RasterizerVulkan::FlushWork() { static constexpr u32 DRAWS_TO_DISPATCH = 4096; @@ -571,9 +577,9 @@ void RasterizerVulkan::FlushWork() { RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { MICROPROFILE_SCOPE(Vulkan_RenderTargets); - auto& dirty = system.GPU().Maxwell3D().dirty; - const bool update_rendertargets = dirty.render_settings; - dirty.render_settings = false; + auto& dirty = system.GPU().Maxwell3D().dirty.flags; + const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets]; + dirty[VideoCommon::Dirty::RenderTargets] = false; texture_cache.GuardRenderTargets(true); @@ -723,13 +729,13 @@ void RasterizerVulkan::SetupImageTransitions( } void RasterizerVulkan::UpdateDynamicStates() { - auto& gpu = system.GPU().Maxwell3D(); - UpdateViewportsState(gpu); - UpdateScissorsState(gpu); - UpdateDepthBias(gpu); - UpdateBlendConstants(gpu); - UpdateDepthBounds(gpu); - UpdateStencilFaces(gpu); + auto& regs = system.GPU().Maxwell3D().regs; + UpdateViewportsState(regs); + UpdateScissorsState(regs); + UpdateDepthBias(regs); + UpdateBlendConstants(regs); + UpdateDepthBounds(regs); + UpdateStencilFaces(regs); } void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex_input, @@ -979,12 +985,10 @@ void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const Ima image_views.push_back(ImageView{std::move(view), image_layout}); } -void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D& gpu) { - if (!gpu.dirty.viewport_transform && scheduler.TouchViewports()) { +void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs) { + if (!state_tracker.TouchViewports()) { return; } - gpu.dirty.viewport_transform = false; - const auto& regs = gpu.regs; const std::array viewports{ GetViewportState(device, regs, 0), GetViewportState(device, regs, 1), GetViewportState(device, regs, 2), GetViewportState(device, regs, 3), @@ -999,12 +1003,10 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D& gpu) { }); } -void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D& gpu) { - if (!gpu.dirty.scissor_test && scheduler.TouchScissors()) { +void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs) { + if (!state_tracker.TouchScissors()) { return; } - gpu.dirty.scissor_test = false; - const auto& regs = gpu.regs; const std::array scissors = { GetScissorState(regs, 0), GetScissorState(regs, 1), GetScissorState(regs, 2), GetScissorState(regs, 3), GetScissorState(regs, 4), GetScissorState(regs, 5), @@ -1017,46 +1019,39 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D& gpu) { }); } -void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D& gpu) { - if (!gpu.dirty.polygon_offset && scheduler.TouchDepthBias()) { +void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { + if (!state_tracker.TouchDepthBias()) { return; } - gpu.dirty.polygon_offset = false; - const auto& regs = gpu.regs; scheduler.Record([constant = regs.polygon_offset_units, clamp = regs.polygon_offset_clamp, factor = regs.polygon_offset_factor](auto cmdbuf, auto& dld) { cmdbuf.setDepthBias(constant, clamp, factor / 2.0f, dld); }); } -void RasterizerVulkan::UpdateBlendConstants(Tegra::Engines::Maxwell3D& gpu) { - if (!gpu.dirty.blend_state && scheduler.TouchBlendConstants()) { +void RasterizerVulkan::UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs) { + if (!state_tracker.TouchBlendConstants()) { return; } - gpu.dirty.blend_state = false; - const std::array blend_color = {gpu.regs.blend_color.r, gpu.regs.blend_color.g, - gpu.regs.blend_color.b, gpu.regs.blend_color.a}; + const std::array blend_color = {regs.blend_color.r, regs.blend_color.g, regs.blend_color.b, + regs.blend_color.a}; scheduler.Record([blend_color](auto cmdbuf, auto& dld) { cmdbuf.setBlendConstants(blend_color.data(), dld); }); } -void RasterizerVulkan::UpdateDepthBounds(Tegra::Engines::Maxwell3D& gpu) { - if (!gpu.dirty.depth_bounds_values && scheduler.TouchDepthBounds()) { +void RasterizerVulkan::UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs) { + if (!state_tracker.TouchDepthBounds()) { return; } - gpu.dirty.depth_bounds_values = false; - const auto& regs = gpu.regs; scheduler.Record([min = regs.depth_bounds[0], max = regs.depth_bounds[1]]( auto cmdbuf, auto& dld) { cmdbuf.setDepthBounds(min, max, dld); }); } -void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D& gpu) { - if (!gpu.dirty.stencil_test && scheduler.TouchStencilValues()) { +void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs) { + if (!state_tracker.TouchStencilProperties()) { return; } - gpu.dirty.stencil_test = false; - const auto& regs = gpu.regs; if (regs.stencil_two_side_enable) { // Separate values per face scheduler.Record( diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 4dc8af6e8..96ea05f0a 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -96,6 +96,7 @@ struct hash<Vulkan::FramebufferCacheKey> { namespace Vulkan { +class StateTracker; class BufferBindings; struct ImageView { @@ -108,7 +109,7 @@ public: explicit RasterizerVulkan(Core::System& system, Core::Frontend::EmuWindow& render_window, VKScreenInfo& screen_info, const VKDevice& device, VKResourceManager& resource_manager, VKMemoryManager& memory_manager, - VKScheduler& scheduler); + StateTracker& state_tracker, VKScheduler& scheduler); ~RasterizerVulkan() override; void Draw(bool is_indexed, bool is_instanced) override; @@ -127,6 +128,7 @@ public: const Tegra::Engines::Fermi2D::Config& copy_config) override; bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, u32 pixel_stride) override; + void SetupDirtyFlags() override; /// Maximum supported size that a constbuffer can have in bytes. static constexpr std::size_t MaxConstbufferSize = 0x10000; @@ -215,12 +217,12 @@ private: void SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry); - void UpdateViewportsState(Tegra::Engines::Maxwell3D& gpu); - void UpdateScissorsState(Tegra::Engines::Maxwell3D& gpu); - void UpdateDepthBias(Tegra::Engines::Maxwell3D& gpu); - void UpdateBlendConstants(Tegra::Engines::Maxwell3D& gpu); - void UpdateDepthBounds(Tegra::Engines::Maxwell3D& gpu); - void UpdateStencilFaces(Tegra::Engines::Maxwell3D& gpu); + void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs); std::size_t CalculateGraphicsStreamBufferSize(bool is_indexed) const; @@ -241,6 +243,7 @@ private: const VKDevice& device; VKResourceManager& resource_manager; VKMemoryManager& memory_manager; + StateTracker& state_tracker; VKScheduler& scheduler; VKStagingBufferPool staging_pool; diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 92bd6c344..b61d4fe63 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -2,6 +2,12 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <memory> +#include <mutex> +#include <optional> +#include <thread> +#include <utility> + #include "common/assert.h" #include "common/microprofile.h" #include "video_core/renderer_vulkan/declarations.h" @@ -9,6 +15,7 @@ #include "video_core/renderer_vulkan/vk_query_cache.h" #include "video_core/renderer_vulkan/vk_resource_manager.h" #include "video_core/renderer_vulkan/vk_scheduler.h" +#include "video_core/renderer_vulkan/vk_state_tracker.h" namespace Vulkan { @@ -29,9 +36,10 @@ void VKScheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf, last = nullptr; } -VKScheduler::VKScheduler(const VKDevice& device, VKResourceManager& resource_manager) - : device{device}, resource_manager{resource_manager}, next_fence{ - &resource_manager.CommitFence()} { +VKScheduler::VKScheduler(const VKDevice& device, VKResourceManager& resource_manager, + StateTracker& state_tracker) + : device{device}, resource_manager{resource_manager}, state_tracker{state_tracker}, + next_fence{&resource_manager.CommitFence()} { AcquireNewChunk(); AllocateNewContext(); worker_thread = std::thread(&VKScheduler::WorkerThread, this); @@ -157,12 +165,7 @@ void VKScheduler::AllocateNewContext() { void VKScheduler::InvalidateState() { state.graphics_pipeline = nullptr; - state.viewports = false; - state.scissors = false; - state.depth_bias = false; - state.blend_constants = false; - state.depth_bounds = false; - state.stencil_values = false; + state_tracker.InvalidateCommandBufferState(); } void VKScheduler::EndPendingOperations() { diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index 62fd7858b..c7cc291c3 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -17,6 +17,7 @@ namespace Vulkan { +class StateTracker; class VKDevice; class VKFence; class VKQueryCache; @@ -43,7 +44,8 @@ private: /// OpenGL-like operations on Vulkan command buffers. class VKScheduler { public: - explicit VKScheduler(const VKDevice& device, VKResourceManager& resource_manager); + explicit VKScheduler(const VKDevice& device, VKResourceManager& resource_manager, + StateTracker& state_tracker); ~VKScheduler(); /// Sends the current execution context to the GPU. @@ -74,36 +76,6 @@ public: query_cache = &query_cache_; } - /// Returns true when viewports have been set in the current command buffer. - bool TouchViewports() { - return std::exchange(state.viewports, true); - } - - /// Returns true when scissors have been set in the current command buffer. - bool TouchScissors() { - return std::exchange(state.scissors, true); - } - - /// Returns true when depth bias have been set in the current command buffer. - bool TouchDepthBias() { - return std::exchange(state.depth_bias, true); - } - - /// Returns true when blend constants have been set in the current command buffer. - bool TouchBlendConstants() { - return std::exchange(state.blend_constants, true); - } - - /// Returns true when depth bounds have been set in the current command buffer. - bool TouchDepthBounds() { - return std::exchange(state.depth_bounds, true); - } - - /// Returns true when stencil values have been set in the current command buffer. - bool TouchStencilValues() { - return std::exchange(state.stencil_values, true); - } - /// Send work to a separate thread. template <typename T> void Record(T&& command) { @@ -217,6 +189,8 @@ private: const VKDevice& device; VKResourceManager& resource_manager; + StateTracker& state_tracker; + VKQueryCache* query_cache = nullptr; vk::CommandBuffer current_cmdbuf; @@ -226,12 +200,6 @@ private: struct State { std::optional<vk::RenderPassBeginInfo> renderpass; vk::Pipeline graphics_pipeline; - bool viewports = false; - bool scissors = false; - bool depth_bias = false; - bool blend_constants = false; - bool depth_bounds = false; - bool stencil_values = false; } state; std::unique_ptr<CommandChunk> chunk; diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp new file mode 100644 index 000000000..d74e68b63 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp @@ -0,0 +1,101 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <algorithm> +#include <cstddef> +#include <iterator> + +#include "common/common_types.h" +#include "core/core.h" +#include "video_core/dirty_flags.h" +#include "video_core/engines/maxwell_3d.h" +#include "video_core/gpu.h" +#include "video_core/renderer_vulkan/vk_state_tracker.h" + +#define OFF(field_name) MAXWELL3D_REG_INDEX(field_name) +#define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / sizeof(u32)) + +namespace Vulkan { + +namespace { + +using namespace Dirty; +using namespace VideoCommon::Dirty; +using Tegra::Engines::Maxwell3D; +using Regs = Maxwell3D::Regs; +using Tables = Maxwell3D::DirtyState::Tables; +using Table = Maxwell3D::DirtyState::Table; +using Flags = Maxwell3D::DirtyState::Flags; + +Flags MakeInvalidationFlags() { + Flags flags{}; + flags[Viewports] = true; + flags[Scissors] = true; + flags[DepthBias] = true; + flags[BlendConstants] = true; + flags[DepthBounds] = true; + flags[StencilProperties] = true; + return flags; +} + +void SetupDirtyViewports(Tables& tables) { + FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports); + FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports); + tables[0][OFF(viewport_transform_enabled)] = Viewports; +} + +void SetupDirtyScissors(Tables& tables) { + FillBlock(tables[0], OFF(scissor_test), NUM(scissor_test), Scissors); +} + +void SetupDirtyDepthBias(Tables& tables) { + auto& table = tables[0]; + table[OFF(polygon_offset_units)] = DepthBias; + table[OFF(polygon_offset_clamp)] = DepthBias; + table[OFF(polygon_offset_factor)] = DepthBias; +} + +void SetupDirtyBlendConstants(Tables& tables) { + FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendConstants); +} + +void SetupDirtyDepthBounds(Tables& tables) { + FillBlock(tables[0], OFF(depth_bounds), NUM(depth_bounds), DepthBounds); +} + +void SetupDirtyStencilProperties(Tables& tables) { + auto& table = tables[0]; + table[OFF(stencil_two_side_enable)] = StencilProperties; + table[OFF(stencil_front_func_ref)] = StencilProperties; + table[OFF(stencil_front_mask)] = StencilProperties; + table[OFF(stencil_front_func_mask)] = StencilProperties; + table[OFF(stencil_back_func_ref)] = StencilProperties; + table[OFF(stencil_back_mask)] = StencilProperties; + table[OFF(stencil_back_func_mask)] = StencilProperties; +} + +} // Anonymous namespace + +StateTracker::StateTracker(Core::System& system) + : system{system}, invalidation_flags{MakeInvalidationFlags()} {} + +void StateTracker::Initialize() { + auto& dirty = system.GPU().Maxwell3D().dirty; + auto& tables = dirty.tables; + SetupDirtyRenderTargets(tables); + SetupDirtyViewports(tables); + SetupDirtyScissors(tables); + SetupDirtyDepthBias(tables); + SetupDirtyBlendConstants(tables); + SetupDirtyDepthBounds(tables); + SetupDirtyStencilProperties(tables); + + SetupCommonOnWriteStores(dirty.on_write_stores); +} + +void StateTracker::InvalidateCommandBufferState() { + system.GPU().Maxwell3D().dirty.flags |= invalidation_flags; +} + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h new file mode 100644 index 000000000..03bc415b2 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h @@ -0,0 +1,79 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <cstddef> +#include <limits> + +#include "common/common_types.h" +#include "core/core.h" +#include "video_core/dirty_flags.h" +#include "video_core/engines/maxwell_3d.h" + +namespace Vulkan { + +namespace Dirty { + +enum : u8 { + First = VideoCommon::Dirty::LastCommonEntry, + + Viewports, + Scissors, + DepthBias, + BlendConstants, + DepthBounds, + StencilProperties, + + Last +}; +static_assert(Last <= std::numeric_limits<u8>::max()); + +} // namespace Dirty + +class StateTracker { +public: + explicit StateTracker(Core::System& system); + + void Initialize(); + + void InvalidateCommandBufferState(); + + bool TouchViewports() { + return Exchange(Dirty::Viewports, false); + } + + bool TouchScissors() { + return Exchange(Dirty::Scissors, false); + } + + bool TouchDepthBias() { + return Exchange(Dirty::DepthBias, false); + } + + bool TouchBlendConstants() { + return Exchange(Dirty::BlendConstants, false); + } + + bool TouchDepthBounds() { + return Exchange(Dirty::DepthBounds, false); + } + + bool TouchStencilProperties() { + return Exchange(Dirty::StencilProperties, false); + } + +private: + bool Exchange(std::size_t id, bool new_value) const noexcept { + auto& flags = system.GPU().Maxwell3D().dirty.flags; + const bool is_dirty = flags[id]; + flags[id] = new_value; + return is_dirty; + } + + Core::System& system; + Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; +}; + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 51b0d38a6..73d92a5ae 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -22,6 +22,7 @@ #include "video_core/renderer_vulkan/vk_device.h" #include "video_core/renderer_vulkan/vk_memory_manager.h" #include "video_core/renderer_vulkan/vk_rasterizer.h" +#include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" #include "video_core/renderer_vulkan/vk_texture_cache.h" #include "video_core/surface.h" |