Merge pull request #3301 from ReinUsesLisp/state-tracker
video_core: Remove gl_state and use a state tracker based on dirty flags
This commit is contained in:
commit
22e825a3bc
50 changed files with 1583 additions and 1896 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
101
src/video_core/renderer_vulkan/vk_state_tracker.cpp
Normal file
101
src/video_core/renderer_vulkan/vk_state_tracker.cpp
Normal file
|
@ -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
|
79
src/video_core/renderer_vulkan/vk_state_tracker.h
Normal file
79
src/video_core/renderer_vulkan/vk_state_tracker.h
Normal file
|
@ -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
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue