summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorGravatar Rodrigo Locatti2020-03-09 18:34:37 -0300
committerGravatar GitHub2020-03-09 18:34:37 -0300
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.gz
yuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.tar.xz
yuzu-22e825a3bc0d9bfb5f8c29a50724c2887014dc02.zip
Merge pull request #3301 from ReinUsesLisp/state-tracker
video_core: Remove gl_state and use a state tracker based on dirty flags
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)
112 const auto& clip = regs.view_volume_clip_control; 112 const auto& clip = regs.view_volume_clip_control;
113 const bool depth_clamp_enabled = clip.depth_clamp_near == 1 || clip.depth_clamp_far == 1; 113 const bool depth_clamp_enabled = clip.depth_clamp_near == 1 || clip.depth_clamp_far == 1;
114 114
115 Maxwell::Cull::FrontFace front_face = regs.cull.front_face; 115 Maxwell::FrontFace front_face = regs.front_face;
116 if (regs.screen_y_control.triangle_rast_flip != 0 && 116 if (regs.screen_y_control.triangle_rast_flip != 0 &&
117 regs.viewport_transform[0].scale_y > 0.0f) { 117 regs.viewport_transform[0].scale_y > 0.0f) {
118 if (front_face == Maxwell::Cull::FrontFace::CounterClockWise) 118 if (front_face == Maxwell::FrontFace::CounterClockWise)
119 front_face = Maxwell::Cull::FrontFace::ClockWise; 119 front_face = Maxwell::FrontFace::ClockWise;
120 else if (front_face == Maxwell::Cull::FrontFace::ClockWise) 120 else if (front_face == Maxwell::FrontFace::ClockWise)
121 front_face = Maxwell::Cull::FrontFace::CounterClockWise; 121 front_face = Maxwell::FrontFace::CounterClockWise;
122 } 122 }
123 123
124 const bool gl_ndc = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; 124 const bool gl_ndc = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
125 return FixedPipelineState::Rasterizer(regs.cull.enabled, depth_bias_enabled, 125 return FixedPipelineState::Rasterizer(regs.cull_test_enabled, depth_bias_enabled,
126 depth_clamp_enabled, gl_ndc, regs.cull.cull_face, 126 depth_clamp_enabled, gl_ndc, regs.cull_face, front_face);
127 front_face);
128} 127}
129 128
130} // Anonymous namespace 129} // 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 {
171 171
172 struct Rasterizer { 172 struct Rasterizer {
173 constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool depth_clamp_enable, 173 constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool depth_clamp_enable,
174 bool ndc_minus_one_to_one, Maxwell::Cull::CullFace cull_face, 174 bool ndc_minus_one_to_one, Maxwell::CullFace cull_face,
175 Maxwell::Cull::FrontFace front_face) 175 Maxwell::FrontFace front_face)
176 : cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable}, 176 : cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable},
177 depth_clamp_enable{depth_clamp_enable}, ndc_minus_one_to_one{ndc_minus_one_to_one}, 177 depth_clamp_enable{depth_clamp_enable}, ndc_minus_one_to_one{ndc_minus_one_to_one},
178 cull_face{cull_face}, front_face{front_face} {} 178 cull_face{cull_face}, front_face{front_face} {}
@@ -182,8 +182,8 @@ struct FixedPipelineState {
182 bool depth_bias_enable; 182 bool depth_bias_enable;
183 bool depth_clamp_enable; 183 bool depth_clamp_enable;
184 bool ndc_minus_one_to_one; 184 bool ndc_minus_one_to_one;
185 Maxwell::Cull::CullFace cull_face; 185 Maxwell::CullFace cull_face;
186 Maxwell::Cull::FrontFace front_face; 186 Maxwell::FrontFace front_face;
187 187
188 std::size_t Hash() const noexcept; 188 std::size_t Hash() const noexcept;
189 189
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) {
586 return {}; 586 return {};
587} 587}
588 588
589vk::FrontFace FrontFace(Maxwell::Cull::FrontFace front_face) { 589vk::FrontFace FrontFace(Maxwell::FrontFace front_face) {
590 switch (front_face) { 590 switch (front_face) {
591 case Maxwell::Cull::FrontFace::ClockWise: 591 case Maxwell::FrontFace::ClockWise:
592 return vk::FrontFace::eClockwise; 592 return vk::FrontFace::eClockwise;
593 case Maxwell::Cull::FrontFace::CounterClockWise: 593 case Maxwell::FrontFace::CounterClockWise:
594 return vk::FrontFace::eCounterClockwise; 594 return vk::FrontFace::eCounterClockwise;
595 } 595 }
596 UNIMPLEMENTED_MSG("Unimplemented front face={}", static_cast<u32>(front_face)); 596 UNIMPLEMENTED_MSG("Unimplemented front face={}", static_cast<u32>(front_face));
597 return {}; 597 return {};
598} 598}
599 599
600vk::CullModeFlags CullFace(Maxwell::Cull::CullFace cull_face) { 600vk::CullModeFlags CullFace(Maxwell::CullFace cull_face) {
601 switch (cull_face) { 601 switch (cull_face) {
602 case Maxwell::Cull::CullFace::Front: 602 case Maxwell::CullFace::Front:
603 return vk::CullModeFlagBits::eFront; 603 return vk::CullModeFlagBits::eFront;
604 case Maxwell::Cull::CullFace::Back: 604 case Maxwell::CullFace::Back:
605 return vk::CullModeFlagBits::eBack; 605 return vk::CullModeFlagBits::eBack;
606 case Maxwell::Cull::CullFace::FrontAndBack: 606 case Maxwell::CullFace::FrontAndBack:
607 return vk::CullModeFlagBits::eFrontAndBack; 607 return vk::CullModeFlagBits::eFrontAndBack;
608 } 608 }
609 UNIMPLEMENTED_MSG("Unimplemented cull face={}", static_cast<u32>(cull_face)); 609 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);
54 54
55vk::BlendFactor BlendFactor(Maxwell::Blend::Factor factor); 55vk::BlendFactor BlendFactor(Maxwell::Blend::Factor factor);
56 56
57vk::FrontFace FrontFace(Maxwell::Cull::FrontFace front_face); 57vk::FrontFace FrontFace(Maxwell::FrontFace front_face);
58 58
59vk::CullModeFlags CullFace(Maxwell::Cull::CullFace cull_face); 59vk::CullModeFlags CullFace(Maxwell::CullFace cull_face);
60 60
61vk::ComponentSwizzle SwizzleSource(Tegra::Texture::SwizzleSource swizzle); 61vk::ComponentSwizzle SwizzleSource(Tegra::Texture::SwizzleSource swizzle);
62 62
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 @@
27#include "video_core/renderer_vulkan/vk_rasterizer.h" 27#include "video_core/renderer_vulkan/vk_rasterizer.h"
28#include "video_core/renderer_vulkan/vk_resource_manager.h" 28#include "video_core/renderer_vulkan/vk_resource_manager.h"
29#include "video_core/renderer_vulkan/vk_scheduler.h" 29#include "video_core/renderer_vulkan/vk_scheduler.h"
30#include "video_core/renderer_vulkan/vk_state_tracker.h"
30#include "video_core/renderer_vulkan/vk_swapchain.h" 31#include "video_core/renderer_vulkan/vk_swapchain.h"
31 32
32namespace Vulkan { 33namespace Vulkan {
@@ -177,10 +178,13 @@ bool RendererVulkan::Init() {
177 swapchain = std::make_unique<VKSwapchain>(surface, *device); 178 swapchain = std::make_unique<VKSwapchain>(surface, *device);
178 swapchain->Create(framebuffer.width, framebuffer.height, false); 179 swapchain->Create(framebuffer.width, framebuffer.height, false);
179 180
180 scheduler = std::make_unique<VKScheduler>(*device, *resource_manager); 181 state_tracker = std::make_unique<StateTracker>(system);
182
183 scheduler = std::make_unique<VKScheduler>(*device, *resource_manager, *state_tracker);
181 184
182 rasterizer = std::make_unique<RasterizerVulkan>(system, render_window, screen_info, *device, 185 rasterizer = std::make_unique<RasterizerVulkan>(system, render_window, screen_info, *device,
183 *resource_manager, *memory_manager, *scheduler); 186 *resource_manager, *memory_manager,
187 *state_tracker, *scheduler);
184 188
185 blit_screen = std::make_unique<VKBlitScreen>(system, render_window, *rasterizer, *device, 189 blit_screen = std::make_unique<VKBlitScreen>(system, render_window, *rasterizer, *device,
186 *resource_manager, *memory_manager, *swapchain, 190 *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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <memory>
7#include <optional> 8#include <optional>
8#include <vector> 9#include <vector>
10
9#include "video_core/renderer_base.h" 11#include "video_core/renderer_base.h"
10#include "video_core/renderer_vulkan/declarations.h" 12#include "video_core/renderer_vulkan/declarations.h"
11 13
@@ -15,6 +17,7 @@ class System;
15 17
16namespace Vulkan { 18namespace Vulkan {
17 19
20class StateTracker;
18class VKBlitScreen; 21class VKBlitScreen;
19class VKDevice; 22class VKDevice;
20class VKFence; 23class VKFence;
@@ -61,6 +64,7 @@ private:
61 std::unique_ptr<VKSwapchain> swapchain; 64 std::unique_ptr<VKSwapchain> swapchain;
62 std::unique_ptr<VKMemoryManager> memory_manager; 65 std::unique_ptr<VKMemoryManager> memory_manager;
63 std::unique_ptr<VKResourceManager> resource_manager; 66 std::unique_ptr<VKResourceManager> resource_manager;
67 std::unique_ptr<StateTracker> state_tracker;
64 std::unique_ptr<VKScheduler> scheduler; 68 std::unique_ptr<VKScheduler> scheduler;
65 std::unique_ptr<VKBlitScreen> blit_screen; 69 std::unique_ptr<VKBlitScreen> blit_screen;
66}; 70};
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;
188 188
189std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() { 189std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() {
190 const auto& gpu = system.GPU().Maxwell3D(); 190 const auto& gpu = system.GPU().Maxwell3D();
191 auto& dirty = system.GPU().Maxwell3D().dirty.shaders;
192 if (!dirty) {
193 return last_shaders;
194 }
195 dirty = false;
196 191
197 std::array<Shader, Maxwell::MaxShaderProgram> shaders; 192 std::array<Shader, Maxwell::MaxShaderProgram> shaders;
198 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { 193 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 @@
36#include "video_core/renderer_vulkan/vk_sampler_cache.h" 36#include "video_core/renderer_vulkan/vk_sampler_cache.h"
37#include "video_core/renderer_vulkan/vk_scheduler.h" 37#include "video_core/renderer_vulkan/vk_scheduler.h"
38#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" 38#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
39#include "video_core/renderer_vulkan/vk_state_tracker.h"
39#include "video_core/renderer_vulkan/vk_texture_cache.h" 40#include "video_core/renderer_vulkan/vk_texture_cache.h"
40#include "video_core/renderer_vulkan/vk_update_descriptor.h" 41#include "video_core/renderer_vulkan/vk_update_descriptor.h"
41 42
@@ -280,10 +281,11 @@ void RasterizerVulkan::DrawParameters::Draw(vk::CommandBuffer cmdbuf,
280RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWindow& renderer, 281RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWindow& renderer,
281 VKScreenInfo& screen_info, const VKDevice& device, 282 VKScreenInfo& screen_info, const VKDevice& device,
282 VKResourceManager& resource_manager, 283 VKResourceManager& resource_manager,
283 VKMemoryManager& memory_manager, VKScheduler& scheduler) 284 VKMemoryManager& memory_manager, StateTracker& state_tracker,
285 VKScheduler& scheduler)
284 : RasterizerAccelerated{system.Memory()}, system{system}, render_window{renderer}, 286 : RasterizerAccelerated{system.Memory()}, system{system}, render_window{renderer},
285 screen_info{screen_info}, device{device}, resource_manager{resource_manager}, 287 screen_info{screen_info}, device{device}, resource_manager{resource_manager},
286 memory_manager{memory_manager}, scheduler{scheduler}, 288 memory_manager{memory_manager}, state_tracker{state_tracker}, scheduler{scheduler},
287 staging_pool(device, memory_manager, scheduler), descriptor_pool(device), 289 staging_pool(device, memory_manager, scheduler), descriptor_pool(device),
288 update_descriptor_queue(device, scheduler), 290 update_descriptor_queue(device, scheduler),
289 quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), 291 quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
@@ -548,6 +550,10 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
548 return true; 550 return true;
549} 551}
550 552
553void RasterizerVulkan::SetupDirtyFlags() {
554 state_tracker.Initialize();
555}
556
551void RasterizerVulkan::FlushWork() { 557void RasterizerVulkan::FlushWork() {
552 static constexpr u32 DRAWS_TO_DISPATCH = 4096; 558 static constexpr u32 DRAWS_TO_DISPATCH = 4096;
553 559
@@ -571,9 +577,9 @@ void RasterizerVulkan::FlushWork() {
571 577
572RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { 578RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() {
573 MICROPROFILE_SCOPE(Vulkan_RenderTargets); 579 MICROPROFILE_SCOPE(Vulkan_RenderTargets);
574 auto& dirty = system.GPU().Maxwell3D().dirty; 580 auto& dirty = system.GPU().Maxwell3D().dirty.flags;
575 const bool update_rendertargets = dirty.render_settings; 581 const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets];
576 dirty.render_settings = false; 582 dirty[VideoCommon::Dirty::RenderTargets] = false;
577 583
578 texture_cache.GuardRenderTargets(true); 584 texture_cache.GuardRenderTargets(true);
579 585
@@ -723,13 +729,13 @@ void RasterizerVulkan::SetupImageTransitions(
723} 729}
724 730
725void RasterizerVulkan::UpdateDynamicStates() { 731void RasterizerVulkan::UpdateDynamicStates() {
726 auto& gpu = system.GPU().Maxwell3D(); 732 auto& regs = system.GPU().Maxwell3D().regs;
727 UpdateViewportsState(gpu); 733 UpdateViewportsState(regs);
728 UpdateScissorsState(gpu); 734 UpdateScissorsState(regs);
729 UpdateDepthBias(gpu); 735 UpdateDepthBias(regs);
730 UpdateBlendConstants(gpu); 736 UpdateBlendConstants(regs);
731 UpdateDepthBounds(gpu); 737 UpdateDepthBounds(regs);
732 UpdateStencilFaces(gpu); 738 UpdateStencilFaces(regs);
733} 739}
734 740
735void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex_input, 741void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex_input,
@@ -979,12 +985,10 @@ void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const Ima
979 image_views.push_back(ImageView{std::move(view), image_layout}); 985 image_views.push_back(ImageView{std::move(view), image_layout});
980} 986}
981 987
982void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D& gpu) { 988void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs) {
983 if (!gpu.dirty.viewport_transform && scheduler.TouchViewports()) { 989 if (!state_tracker.TouchViewports()) {
984 return; 990 return;
985 } 991 }
986 gpu.dirty.viewport_transform = false;
987 const auto& regs = gpu.regs;
988 const std::array viewports{ 992 const std::array viewports{
989 GetViewportState(device, regs, 0), GetViewportState(device, regs, 1), 993 GetViewportState(device, regs, 0), GetViewportState(device, regs, 1),
990 GetViewportState(device, regs, 2), GetViewportState(device, regs, 3), 994 GetViewportState(device, regs, 2), GetViewportState(device, regs, 3),
@@ -999,12 +1003,10 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D& gpu) {
999 }); 1003 });
1000} 1004}
1001 1005
1002void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D& gpu) { 1006void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs) {
1003 if (!gpu.dirty.scissor_test && scheduler.TouchScissors()) { 1007 if (!state_tracker.TouchScissors()) {
1004 return; 1008 return;
1005 } 1009 }
1006 gpu.dirty.scissor_test = false;
1007 const auto& regs = gpu.regs;
1008 const std::array scissors = { 1010 const std::array scissors = {
1009 GetScissorState(regs, 0), GetScissorState(regs, 1), GetScissorState(regs, 2), 1011 GetScissorState(regs, 0), GetScissorState(regs, 1), GetScissorState(regs, 2),
1010 GetScissorState(regs, 3), GetScissorState(regs, 4), GetScissorState(regs, 5), 1012 GetScissorState(regs, 3), GetScissorState(regs, 4), GetScissorState(regs, 5),
@@ -1017,46 +1019,39 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D& gpu) {
1017 }); 1019 });
1018} 1020}
1019 1021
1020void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D& gpu) { 1022void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
1021 if (!gpu.dirty.polygon_offset && scheduler.TouchDepthBias()) { 1023 if (!state_tracker.TouchDepthBias()) {
1022 return; 1024 return;
1023 } 1025 }
1024 gpu.dirty.polygon_offset = false;
1025 const auto& regs = gpu.regs;
1026 scheduler.Record([constant = regs.polygon_offset_units, clamp = regs.polygon_offset_clamp, 1026 scheduler.Record([constant = regs.polygon_offset_units, clamp = regs.polygon_offset_clamp,
1027 factor = regs.polygon_offset_factor](auto cmdbuf, auto& dld) { 1027 factor = regs.polygon_offset_factor](auto cmdbuf, auto& dld) {
1028 cmdbuf.setDepthBias(constant, clamp, factor / 2.0f, dld); 1028 cmdbuf.setDepthBias(constant, clamp, factor / 2.0f, dld);
1029 }); 1029 });
1030} 1030}
1031 1031
1032void RasterizerVulkan::UpdateBlendConstants(Tegra::Engines::Maxwell3D& gpu) { 1032void RasterizerVulkan::UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs) {
1033 if (!gpu.dirty.blend_state && scheduler.TouchBlendConstants()) { 1033 if (!state_tracker.TouchBlendConstants()) {
1034 return; 1034 return;
1035 } 1035 }
1036 gpu.dirty.blend_state = false; 1036 const std::array blend_color = {regs.blend_color.r, regs.blend_color.g, regs.blend_color.b,
1037 const std::array blend_color = {gpu.regs.blend_color.r, gpu.regs.blend_color.g, 1037 regs.blend_color.a};
1038 gpu.regs.blend_color.b, gpu.regs.blend_color.a};
1039 scheduler.Record([blend_color](auto cmdbuf, auto& dld) { 1038 scheduler.Record([blend_color](auto cmdbuf, auto& dld) {
1040 cmdbuf.setBlendConstants(blend_color.data(), dld); 1039 cmdbuf.setBlendConstants(blend_color.data(), dld);
1041 }); 1040 });
1042} 1041}
1043 1042
1044void RasterizerVulkan::UpdateDepthBounds(Tegra::Engines::Maxwell3D& gpu) { 1043void RasterizerVulkan::UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs) {
1045 if (!gpu.dirty.depth_bounds_values && scheduler.TouchDepthBounds()) { 1044 if (!state_tracker.TouchDepthBounds()) {
1046 return; 1045 return;
1047 } 1046 }
1048 gpu.dirty.depth_bounds_values = false;
1049 const auto& regs = gpu.regs;
1050 scheduler.Record([min = regs.depth_bounds[0], max = regs.depth_bounds[1]]( 1047 scheduler.Record([min = regs.depth_bounds[0], max = regs.depth_bounds[1]](
1051 auto cmdbuf, auto& dld) { cmdbuf.setDepthBounds(min, max, dld); }); 1048 auto cmdbuf, auto& dld) { cmdbuf.setDepthBounds(min, max, dld); });
1052} 1049}
1053 1050
1054void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D& gpu) { 1051void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs) {
1055 if (!gpu.dirty.stencil_test && scheduler.TouchStencilValues()) { 1052 if (!state_tracker.TouchStencilProperties()) {
1056 return; 1053 return;
1057 } 1054 }
1058 gpu.dirty.stencil_test = false;
1059 const auto& regs = gpu.regs;
1060 if (regs.stencil_two_side_enable) { 1055 if (regs.stencil_two_side_enable) {
1061 // Separate values per face 1056 // Separate values per face
1062 scheduler.Record( 1057 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> {
96 96
97namespace Vulkan { 97namespace Vulkan {
98 98
99class StateTracker;
99class BufferBindings; 100class BufferBindings;
100 101
101struct ImageView { 102struct ImageView {
@@ -108,7 +109,7 @@ public:
108 explicit RasterizerVulkan(Core::System& system, Core::Frontend::EmuWindow& render_window, 109 explicit RasterizerVulkan(Core::System& system, Core::Frontend::EmuWindow& render_window,
109 VKScreenInfo& screen_info, const VKDevice& device, 110 VKScreenInfo& screen_info, const VKDevice& device,
110 VKResourceManager& resource_manager, VKMemoryManager& memory_manager, 111 VKResourceManager& resource_manager, VKMemoryManager& memory_manager,
111 VKScheduler& scheduler); 112 StateTracker& state_tracker, VKScheduler& scheduler);
112 ~RasterizerVulkan() override; 113 ~RasterizerVulkan() override;
113 114
114 void Draw(bool is_indexed, bool is_instanced) override; 115 void Draw(bool is_indexed, bool is_instanced) override;
@@ -127,6 +128,7 @@ public:
127 const Tegra::Engines::Fermi2D::Config& copy_config) override; 128 const Tegra::Engines::Fermi2D::Config& copy_config) override;
128 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 129 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
129 u32 pixel_stride) override; 130 u32 pixel_stride) override;
131 void SetupDirtyFlags() override;
130 132
131 /// Maximum supported size that a constbuffer can have in bytes. 133 /// Maximum supported size that a constbuffer can have in bytes.
132 static constexpr std::size_t MaxConstbufferSize = 0x10000; 134 static constexpr std::size_t MaxConstbufferSize = 0x10000;
@@ -215,12 +217,12 @@ private:
215 217
216 void SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry); 218 void SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry);
217 219
218 void UpdateViewportsState(Tegra::Engines::Maxwell3D& gpu); 220 void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs);
219 void UpdateScissorsState(Tegra::Engines::Maxwell3D& gpu); 221 void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs);
220 void UpdateDepthBias(Tegra::Engines::Maxwell3D& gpu); 222 void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs);
221 void UpdateBlendConstants(Tegra::Engines::Maxwell3D& gpu); 223 void UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs);
222 void UpdateDepthBounds(Tegra::Engines::Maxwell3D& gpu); 224 void UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs);
223 void UpdateStencilFaces(Tegra::Engines::Maxwell3D& gpu); 225 void UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs);
224 226
225 std::size_t CalculateGraphicsStreamBufferSize(bool is_indexed) const; 227 std::size_t CalculateGraphicsStreamBufferSize(bool is_indexed) const;
226 228
@@ -241,6 +243,7 @@ private:
241 const VKDevice& device; 243 const VKDevice& device;
242 VKResourceManager& resource_manager; 244 VKResourceManager& resource_manager;
243 VKMemoryManager& memory_manager; 245 VKMemoryManager& memory_manager;
246 StateTracker& state_tracker;
244 VKScheduler& scheduler; 247 VKScheduler& scheduler;
245 248
246 VKStagingBufferPool staging_pool; 249 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 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory>
6#include <mutex>
7#include <optional>
8#include <thread>
9#include <utility>
10
5#include "common/assert.h" 11#include "common/assert.h"
6#include "common/microprofile.h" 12#include "common/microprofile.h"
7#include "video_core/renderer_vulkan/declarations.h" 13#include "video_core/renderer_vulkan/declarations.h"
@@ -9,6 +15,7 @@
9#include "video_core/renderer_vulkan/vk_query_cache.h" 15#include "video_core/renderer_vulkan/vk_query_cache.h"
10#include "video_core/renderer_vulkan/vk_resource_manager.h" 16#include "video_core/renderer_vulkan/vk_resource_manager.h"
11#include "video_core/renderer_vulkan/vk_scheduler.h" 17#include "video_core/renderer_vulkan/vk_scheduler.h"
18#include "video_core/renderer_vulkan/vk_state_tracker.h"
12 19
13namespace Vulkan { 20namespace Vulkan {
14 21
@@ -29,9 +36,10 @@ void VKScheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf,
29 last = nullptr; 36 last = nullptr;
30} 37}
31 38
32VKScheduler::VKScheduler(const VKDevice& device, VKResourceManager& resource_manager) 39VKScheduler::VKScheduler(const VKDevice& device, VKResourceManager& resource_manager,
33 : device{device}, resource_manager{resource_manager}, next_fence{ 40 StateTracker& state_tracker)
34 &resource_manager.CommitFence()} { 41 : device{device}, resource_manager{resource_manager}, state_tracker{state_tracker},
42 next_fence{&resource_manager.CommitFence()} {
35 AcquireNewChunk(); 43 AcquireNewChunk();
36 AllocateNewContext(); 44 AllocateNewContext();
37 worker_thread = std::thread(&VKScheduler::WorkerThread, this); 45 worker_thread = std::thread(&VKScheduler::WorkerThread, this);
@@ -157,12 +165,7 @@ void VKScheduler::AllocateNewContext() {
157 165
158void VKScheduler::InvalidateState() { 166void VKScheduler::InvalidateState() {
159 state.graphics_pipeline = nullptr; 167 state.graphics_pipeline = nullptr;
160 state.viewports = false; 168 state_tracker.InvalidateCommandBufferState();
161 state.scissors = false;
162 state.depth_bias = false;
163 state.blend_constants = false;
164 state.depth_bounds = false;
165 state.stencil_values = false;
166} 169}
167 170
168void VKScheduler::EndPendingOperations() { 171void 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 @@
17 17
18namespace Vulkan { 18namespace Vulkan {
19 19
20class StateTracker;
20class VKDevice; 21class VKDevice;
21class VKFence; 22class VKFence;
22class VKQueryCache; 23class VKQueryCache;
@@ -43,7 +44,8 @@ private:
43/// OpenGL-like operations on Vulkan command buffers. 44/// OpenGL-like operations on Vulkan command buffers.
44class VKScheduler { 45class VKScheduler {
45public: 46public:
46 explicit VKScheduler(const VKDevice& device, VKResourceManager& resource_manager); 47 explicit VKScheduler(const VKDevice& device, VKResourceManager& resource_manager,
48 StateTracker& state_tracker);
47 ~VKScheduler(); 49 ~VKScheduler();
48 50
49 /// Sends the current execution context to the GPU. 51 /// Sends the current execution context to the GPU.
@@ -74,36 +76,6 @@ public:
74 query_cache = &query_cache_; 76 query_cache = &query_cache_;
75 } 77 }
76 78
77 /// Returns true when viewports have been set in the current command buffer.
78 bool TouchViewports() {
79 return std::exchange(state.viewports, true);
80 }
81
82 /// Returns true when scissors have been set in the current command buffer.
83 bool TouchScissors() {
84 return std::exchange(state.scissors, true);
85 }
86
87 /// Returns true when depth bias have been set in the current command buffer.
88 bool TouchDepthBias() {
89 return std::exchange(state.depth_bias, true);
90 }
91
92 /// Returns true when blend constants have been set in the current command buffer.
93 bool TouchBlendConstants() {
94 return std::exchange(state.blend_constants, true);
95 }
96
97 /// Returns true when depth bounds have been set in the current command buffer.
98 bool TouchDepthBounds() {
99 return std::exchange(state.depth_bounds, true);
100 }
101
102 /// Returns true when stencil values have been set in the current command buffer.
103 bool TouchStencilValues() {
104 return std::exchange(state.stencil_values, true);
105 }
106
107 /// Send work to a separate thread. 79 /// Send work to a separate thread.
108 template <typename T> 80 template <typename T>
109 void Record(T&& command) { 81 void Record(T&& command) {
@@ -217,6 +189,8 @@ private:
217 189
218 const VKDevice& device; 190 const VKDevice& device;
219 VKResourceManager& resource_manager; 191 VKResourceManager& resource_manager;
192 StateTracker& state_tracker;
193
220 VKQueryCache* query_cache = nullptr; 194 VKQueryCache* query_cache = nullptr;
221 195
222 vk::CommandBuffer current_cmdbuf; 196 vk::CommandBuffer current_cmdbuf;
@@ -226,12 +200,6 @@ private:
226 struct State { 200 struct State {
227 std::optional<vk::RenderPassBeginInfo> renderpass; 201 std::optional<vk::RenderPassBeginInfo> renderpass;
228 vk::Pipeline graphics_pipeline; 202 vk::Pipeline graphics_pipeline;
229 bool viewports = false;
230 bool scissors = false;
231 bool depth_bias = false;
232 bool blend_constants = false;
233 bool depth_bounds = false;
234 bool stencil_values = false;
235 } state; 203 } state;
236 204
237 std::unique_ptr<CommandChunk> chunk; 205 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 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <cstddef>
7#include <iterator>
8
9#include "common/common_types.h"
10#include "core/core.h"
11#include "video_core/dirty_flags.h"
12#include "video_core/engines/maxwell_3d.h"
13#include "video_core/gpu.h"
14#include "video_core/renderer_vulkan/vk_state_tracker.h"
15
16#define OFF(field_name) MAXWELL3D_REG_INDEX(field_name)
17#define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / sizeof(u32))
18
19namespace Vulkan {
20
21namespace {
22
23using namespace Dirty;
24using namespace VideoCommon::Dirty;
25using Tegra::Engines::Maxwell3D;
26using Regs = Maxwell3D::Regs;
27using Tables = Maxwell3D::DirtyState::Tables;
28using Table = Maxwell3D::DirtyState::Table;
29using Flags = Maxwell3D::DirtyState::Flags;
30
31Flags MakeInvalidationFlags() {
32 Flags flags{};
33 flags[Viewports] = true;
34 flags[Scissors] = true;
35 flags[DepthBias] = true;
36 flags[BlendConstants] = true;
37 flags[DepthBounds] = true;
38 flags[StencilProperties] = true;
39 return flags;
40}
41
42void SetupDirtyViewports(Tables& tables) {
43 FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
44 FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
45 tables[0][OFF(viewport_transform_enabled)] = Viewports;
46}
47
48void SetupDirtyScissors(Tables& tables) {
49 FillBlock(tables[0], OFF(scissor_test), NUM(scissor_test), Scissors);
50}
51
52void SetupDirtyDepthBias(Tables& tables) {
53 auto& table = tables[0];
54 table[OFF(polygon_offset_units)] = DepthBias;
55 table[OFF(polygon_offset_clamp)] = DepthBias;
56 table[OFF(polygon_offset_factor)] = DepthBias;
57}
58
59void SetupDirtyBlendConstants(Tables& tables) {
60 FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendConstants);
61}
62
63void SetupDirtyDepthBounds(Tables& tables) {
64 FillBlock(tables[0], OFF(depth_bounds), NUM(depth_bounds), DepthBounds);
65}
66
67void SetupDirtyStencilProperties(Tables& tables) {
68 auto& table = tables[0];
69 table[OFF(stencil_two_side_enable)] = StencilProperties;
70 table[OFF(stencil_front_func_ref)] = StencilProperties;
71 table[OFF(stencil_front_mask)] = StencilProperties;
72 table[OFF(stencil_front_func_mask)] = StencilProperties;
73 table[OFF(stencil_back_func_ref)] = StencilProperties;
74 table[OFF(stencil_back_mask)] = StencilProperties;
75 table[OFF(stencil_back_func_mask)] = StencilProperties;
76}
77
78} // Anonymous namespace
79
80StateTracker::StateTracker(Core::System& system)
81 : system{system}, invalidation_flags{MakeInvalidationFlags()} {}
82
83void StateTracker::Initialize() {
84 auto& dirty = system.GPU().Maxwell3D().dirty;
85 auto& tables = dirty.tables;
86 SetupDirtyRenderTargets(tables);
87 SetupDirtyViewports(tables);
88 SetupDirtyScissors(tables);
89 SetupDirtyDepthBias(tables);
90 SetupDirtyBlendConstants(tables);
91 SetupDirtyDepthBounds(tables);
92 SetupDirtyStencilProperties(tables);
93
94 SetupCommonOnWriteStores(dirty.on_write_stores);
95}
96
97void StateTracker::InvalidateCommandBufferState() {
98 system.GPU().Maxwell3D().dirty.flags |= invalidation_flags;
99}
100
101} // 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 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <cstddef>
8#include <limits>
9
10#include "common/common_types.h"
11#include "core/core.h"
12#include "video_core/dirty_flags.h"
13#include "video_core/engines/maxwell_3d.h"
14
15namespace Vulkan {
16
17namespace Dirty {
18
19enum : u8 {
20 First = VideoCommon::Dirty::LastCommonEntry,
21
22 Viewports,
23 Scissors,
24 DepthBias,
25 BlendConstants,
26 DepthBounds,
27 StencilProperties,
28
29 Last
30};
31static_assert(Last <= std::numeric_limits<u8>::max());
32
33} // namespace Dirty
34
35class StateTracker {
36public:
37 explicit StateTracker(Core::System& system);
38
39 void Initialize();
40
41 void InvalidateCommandBufferState();
42
43 bool TouchViewports() {
44 return Exchange(Dirty::Viewports, false);
45 }
46
47 bool TouchScissors() {
48 return Exchange(Dirty::Scissors, false);
49 }
50
51 bool TouchDepthBias() {
52 return Exchange(Dirty::DepthBias, false);
53 }
54
55 bool TouchBlendConstants() {
56 return Exchange(Dirty::BlendConstants, false);
57 }
58
59 bool TouchDepthBounds() {
60 return Exchange(Dirty::DepthBounds, false);
61 }
62
63 bool TouchStencilProperties() {
64 return Exchange(Dirty::StencilProperties, false);
65 }
66
67private:
68 bool Exchange(std::size_t id, bool new_value) const noexcept {
69 auto& flags = system.GPU().Maxwell3D().dirty.flags;
70 const bool is_dirty = flags[id];
71 flags[id] = new_value;
72 return is_dirty;
73 }
74
75 Core::System& system;
76 Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags;
77};
78
79} // 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 @@
22#include "video_core/renderer_vulkan/vk_device.h" 22#include "video_core/renderer_vulkan/vk_device.h"
23#include "video_core/renderer_vulkan/vk_memory_manager.h" 23#include "video_core/renderer_vulkan/vk_memory_manager.h"
24#include "video_core/renderer_vulkan/vk_rasterizer.h" 24#include "video_core/renderer_vulkan/vk_rasterizer.h"
25#include "video_core/renderer_vulkan/vk_scheduler.h"
25#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" 26#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
26#include "video_core/renderer_vulkan/vk_texture_cache.h" 27#include "video_core/renderer_vulkan/vk_texture_cache.h"
27#include "video_core/surface.h" 28#include "video_core/surface.h"