summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorRodrigo Locatti <reinuseslisp@airmail.cc>2020-03-09 22:34:37 +0100
committerGitHub <noreply@github.com>2020-03-09 22:34:37 +0100
commit22e825a3bc0d9bfb5f8c29a50724c2887014dc02 (patch)
treed68f0ace93ba44292e3017dcb219f3132b3314ef /src/video_core/renderer_vulkan
parentMerge pull request #3486 from ReinUsesLisp/fix-anisotropy-hack (diff)
parentvideo_core/dirty_flags: Address feedback (diff)
downloadyuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.tar
yuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.tar.gz
yuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.tar.bz2
yuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.tar.lz
yuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.tar.xz
yuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.tar.zst
yuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.zip
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp15
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h8
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp14
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.h4
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp8
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp5
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp69
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h17
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp21
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.h42
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp101
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.h79
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp1
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"