Vulkan: Remove parameters/members of single-instance classes

There's not a lot of point in passing these around or storing them
(texture cache/state tracker mainly) as there will only ever be a single
instance of the class.

Also adds downcast helpers such as Vulkan::Renderer::GetInstance().
This commit is contained in:
Stenzek 2016-10-22 20:50:36 +10:00
parent ab9f539233
commit b066d51dfa
21 changed files with 336 additions and 303 deletions

View File

@ -10,6 +10,7 @@
#include "VideoBackends/Vulkan/BoundingBox.h" #include "VideoBackends/Vulkan/BoundingBox.h"
#include "VideoBackends/Vulkan/CommandBufferManager.h" #include "VideoBackends/Vulkan/CommandBufferManager.h"
#include "VideoBackends/Vulkan/ObjectCache.h" #include "VideoBackends/Vulkan/ObjectCache.h"
#include "VideoBackends/Vulkan/Renderer.h"
#include "VideoBackends/Vulkan/StagingBuffer.h" #include "VideoBackends/Vulkan/StagingBuffer.h"
#include "VideoBackends/Vulkan/StateTracker.h" #include "VideoBackends/Vulkan/StateTracker.h"
#include "VideoBackends/Vulkan/Util.h" #include "VideoBackends/Vulkan/Util.h"
@ -47,7 +48,7 @@ bool BoundingBox::Initialize()
return true; return true;
} }
void BoundingBox::Flush(StateTracker* state_tracker) void BoundingBox::Flush()
{ {
if (m_gpu_buffer == VK_NULL_HANDLE) if (m_gpu_buffer == VK_NULL_HANDLE)
return; return;
@ -75,7 +76,7 @@ void BoundingBox::Flush(StateTracker* state_tracker)
// However, the writes must be serialized, so we can't put it in the init buffer. // However, the writes must be serialized, so we can't put it in the init buffer.
if (!updated_buffer) if (!updated_buffer)
{ {
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
// Ensure GPU buffer is in a state where it can be transferred to. // Ensure GPU buffer is in a state where it can be transferred to.
Util::BufferMemoryBarrier( Util::BufferMemoryBarrier(
@ -104,7 +105,7 @@ void BoundingBox::Flush(StateTracker* state_tracker)
m_valid = true; m_valid = true;
} }
void BoundingBox::Invalidate(StateTracker* state_tracker) void BoundingBox::Invalidate()
{ {
if (m_gpu_buffer == VK_NULL_HANDLE) if (m_gpu_buffer == VK_NULL_HANDLE)
return; return;
@ -112,19 +113,19 @@ void BoundingBox::Invalidate(StateTracker* state_tracker)
m_valid = false; m_valid = false;
} }
s32 BoundingBox::Get(StateTracker* state_tracker, size_t index) s32 BoundingBox::Get(size_t index)
{ {
_assert_(index < NUM_VALUES); _assert_(index < NUM_VALUES);
if (!m_valid) if (!m_valid)
Readback(state_tracker); Readback();
s32 value; s32 value;
m_readback_buffer->Read(index * sizeof(s32), &value, sizeof(value), false); m_readback_buffer->Read(index * sizeof(s32), &value, sizeof(value), false);
return value; return value;
} }
void BoundingBox::Set(StateTracker* state_tracker, size_t index, s32 value) void BoundingBox::Set(size_t index, s32 value)
{ {
_assert_(index < NUM_VALUES); _assert_(index < NUM_VALUES);
@ -212,10 +213,10 @@ bool BoundingBox::CreateReadbackBuffer()
return true; return true;
} }
void BoundingBox::Readback(StateTracker* state_tracker) void BoundingBox::Readback()
{ {
// Can't be done within a render pass. // Can't be done within a render pass.
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
// Ensure all writes are completed to the GPU buffer prior to the transfer. // Ensure all writes are completed to the GPU buffer prior to the transfer.
Util::BufferMemoryBarrier( Util::BufferMemoryBarrier(
@ -240,7 +241,7 @@ void BoundingBox::Readback(StateTracker* state_tracker)
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
// Wait until these commands complete. // Wait until these commands complete.
Util::ExecuteCurrentCommandsAndRestoreState(state_tracker, false, true); Util::ExecuteCurrentCommandsAndRestoreState(false, true);
// Cache is now valid. // Cache is now valid.
m_readback_buffer->InvalidateCPUCache(); m_readback_buffer->InvalidateCPUCache();

View File

@ -15,7 +15,6 @@
namespace Vulkan namespace Vulkan
{ {
class StagingBuffer; class StagingBuffer;
class StateTracker;
class BoundingBox class BoundingBox
{ {
@ -28,16 +27,16 @@ public:
VkBuffer GetGPUBuffer() const { return m_gpu_buffer; } VkBuffer GetGPUBuffer() const { return m_gpu_buffer; }
VkDeviceSize GetGPUBufferOffset() const { return 0; } VkDeviceSize GetGPUBufferOffset() const { return 0; }
VkDeviceSize GetGPUBufferSize() const { return BUFFER_SIZE; } VkDeviceSize GetGPUBufferSize() const { return BUFFER_SIZE; }
s32 Get(StateTracker* state_tracker, size_t index); s32 Get(size_t index);
void Set(StateTracker* state_tracker, size_t index, s32 value); void Set(size_t index, s32 value);
void Invalidate(StateTracker* state_tracker); void Invalidate();
void Flush(StateTracker* state_tracker); void Flush();
private: private:
bool CreateGPUBuffer(); bool CreateGPUBuffer();
bool CreateReadbackBuffer(); bool CreateReadbackBuffer();
void Readback(StateTracker* state_tracker); void Readback();
VkBuffer m_gpu_buffer = VK_NULL_HANDLE; VkBuffer m_gpu_buffer = VK_NULL_HANDLE;
VkDeviceMemory m_gpu_memory = VK_NULL_HANDLE; VkDeviceMemory m_gpu_memory = VK_NULL_HANDLE;

View File

@ -49,6 +49,11 @@ FramebufferManager::~FramebufferManager()
DestroyPokeShaders(); DestroyPokeShaders();
} }
FramebufferManager* FramebufferManager::GetInstance()
{
return static_cast<FramebufferManager*>(g_framebuffer_manager.get());
}
bool FramebufferManager::Initialize() bool FramebufferManager::Initialize()
{ {
if (!CreateEFBRenderPass()) if (!CreateEFBRenderPass())
@ -450,15 +455,14 @@ void FramebufferManager::ReinterpretPixelData(int convtype)
std::swap(m_efb_framebuffer, m_efb_convert_framebuffer); std::swap(m_efb_framebuffer, m_efb_convert_framebuffer);
} }
Texture2D* FramebufferManager::ResolveEFBColorTexture(StateTracker* state_tracker, Texture2D* FramebufferManager::ResolveEFBColorTexture(const VkRect2D& region)
const VkRect2D& region)
{ {
// Return the normal EFB texture if multisampling is off. // Return the normal EFB texture if multisampling is off.
if (m_efb_samples == VK_SAMPLE_COUNT_1_BIT) if (m_efb_samples == VK_SAMPLE_COUNT_1_BIT)
return m_efb_color_texture.get(); return m_efb_color_texture.get();
// Can't resolve within a render pass. // Can't resolve within a render pass.
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
// Resolving is considered to be a transfer operation. // Resolving is considered to be a transfer operation.
m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
@ -485,15 +489,14 @@ Texture2D* FramebufferManager::ResolveEFBColorTexture(StateTracker* state_tracke
return m_efb_resolve_color_texture.get(); return m_efb_resolve_color_texture.get();
} }
Texture2D* FramebufferManager::ResolveEFBDepthTexture(StateTracker* state_tracker, Texture2D* FramebufferManager::ResolveEFBDepthTexture(const VkRect2D& region)
const VkRect2D& region)
{ {
// Return the normal EFB texture if multisampling is off. // Return the normal EFB texture if multisampling is off.
if (m_efb_samples == VK_SAMPLE_COUNT_1_BIT) if (m_efb_samples == VK_SAMPLE_COUNT_1_BIT)
return m_efb_depth_texture.get(); return m_efb_depth_texture.get();
// Can't resolve within a render pass. // Can't resolve within a render pass.
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
m_efb_depth_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_efb_depth_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
@ -659,9 +662,9 @@ void FramebufferManager::DestroyConversionShaders()
DestroyShader(m_ps_depth_resolve); DestroyShader(m_ps_depth_resolve);
} }
u32 FramebufferManager::PeekEFBColor(StateTracker* state_tracker, u32 x, u32 y) u32 FramebufferManager::PeekEFBColor(u32 x, u32 y)
{ {
if (!m_color_readback_texture_valid && !PopulateColorReadbackTexture(state_tracker)) if (!m_color_readback_texture_valid && !PopulateColorReadbackTexture())
return 0; return 0;
u32 value; u32 value;
@ -669,18 +672,18 @@ u32 FramebufferManager::PeekEFBColor(StateTracker* state_tracker, u32 x, u32 y)
return value; return value;
} }
bool FramebufferManager::PopulateColorReadbackTexture(StateTracker* state_tracker) bool FramebufferManager::PopulateColorReadbackTexture()
{ {
// Can't be in our normal render pass. // Can't be in our normal render pass.
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
state_tracker->OnReadback(); StateTracker::GetInstance()->OnReadback();
// Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on. // Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on.
VkRect2D src_region = {{0, 0}, {m_efb_width, m_efb_height}}; VkRect2D src_region = {{0, 0}, {m_efb_width, m_efb_height}};
Texture2D* src_texture = m_efb_color_texture.get(); Texture2D* src_texture = m_efb_color_texture.get();
VkImageAspectFlags src_aspect = VK_IMAGE_ASPECT_COLOR_BIT; VkImageAspectFlags src_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
if (m_efb_samples > 1) if (m_efb_samples > 1)
src_texture = ResolveEFBColorTexture(state_tracker, src_region); src_texture = ResolveEFBColorTexture(src_region);
if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT) if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT)
{ {
@ -728,8 +731,8 @@ bool FramebufferManager::PopulateColorReadbackTexture(StateTracker* state_tracke
// Wait until the copy is complete. // Wait until the copy is complete.
g_command_buffer_mgr->ExecuteCommandBuffer(false, true); g_command_buffer_mgr->ExecuteCommandBuffer(false, true);
state_tracker->InvalidateDescriptorSets(); StateTracker::GetInstance()->InvalidateDescriptorSets();
state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
// Map to host memory. // Map to host memory.
if (!m_color_readback_texture->IsMapped() && !m_color_readback_texture->Map()) if (!m_color_readback_texture->IsMapped() && !m_color_readback_texture->Map())
@ -739,9 +742,9 @@ bool FramebufferManager::PopulateColorReadbackTexture(StateTracker* state_tracke
return true; return true;
} }
float FramebufferManager::PeekEFBDepth(StateTracker* state_tracker, u32 x, u32 y) float FramebufferManager::PeekEFBDepth(u32 x, u32 y)
{ {
if (!m_depth_readback_texture_valid && !PopulateDepthReadbackTexture(state_tracker)) if (!m_depth_readback_texture_valid && !PopulateDepthReadbackTexture())
return 0.0f; return 0.0f;
float value; float value;
@ -749,11 +752,11 @@ float FramebufferManager::PeekEFBDepth(StateTracker* state_tracker, u32 x, u32 y
return value; return value;
} }
bool FramebufferManager::PopulateDepthReadbackTexture(StateTracker* state_tracker) bool FramebufferManager::PopulateDepthReadbackTexture()
{ {
// Can't be in our normal render pass. // Can't be in our normal render pass.
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
state_tracker->OnReadback(); StateTracker::GetInstance()->OnReadback();
// Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on. // Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on.
VkRect2D src_region = {{0, 0}, {m_efb_width, m_efb_height}}; VkRect2D src_region = {{0, 0}, {m_efb_width, m_efb_height}};
@ -762,7 +765,7 @@ bool FramebufferManager::PopulateDepthReadbackTexture(StateTracker* state_tracke
if (m_efb_samples > 1) if (m_efb_samples > 1)
{ {
// EFB depth resolves are written out as color textures // EFB depth resolves are written out as color textures
src_texture = ResolveEFBDepthTexture(state_tracker, src_region); src_texture = ResolveEFBDepthTexture(src_region);
src_aspect = VK_IMAGE_ASPECT_COLOR_BIT; src_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
} }
if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT) if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT)
@ -812,8 +815,8 @@ bool FramebufferManager::PopulateDepthReadbackTexture(StateTracker* state_tracke
// Wait until the copy is complete. // Wait until the copy is complete.
g_command_buffer_mgr->ExecuteCommandBuffer(false, true); g_command_buffer_mgr->ExecuteCommandBuffer(false, true);
state_tracker->InvalidateDescriptorSets(); StateTracker::GetInstance()->InvalidateDescriptorSets();
state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
// Map to host memory. // Map to host memory.
if (!m_depth_readback_texture->IsMapped() && !m_depth_readback_texture->Map()) if (!m_depth_readback_texture->IsMapped() && !m_depth_readback_texture->Map())
@ -1086,11 +1089,11 @@ void FramebufferManager::DestroyReadbackFramebuffer()
} }
} }
void FramebufferManager::PokeEFBColor(StateTracker* state_tracker, u32 x, u32 y, u32 color) void FramebufferManager::PokeEFBColor(u32 x, u32 y, u32 color)
{ {
// Flush if we exceeded the number of vertices per batch. // Flush if we exceeded the number of vertices per batch.
if ((m_color_poke_vertices.size() + 6) > MAX_POKE_VERTICES) if ((m_color_poke_vertices.size() + 6) > MAX_POKE_VERTICES)
FlushEFBPokes(state_tracker); FlushEFBPokes();
CreatePokeVertices(&m_color_poke_vertices, x, y, 0.0f, color); CreatePokeVertices(&m_color_poke_vertices, x, y, 0.0f, color);
@ -1099,11 +1102,11 @@ void FramebufferManager::PokeEFBColor(StateTracker* state_tracker, u32 x, u32 y,
m_color_readback_texture->WriteTexel(x, y, &color, sizeof(color)); m_color_readback_texture->WriteTexel(x, y, &color, sizeof(color));
} }
void FramebufferManager::PokeEFBDepth(StateTracker* state_tracker, u32 x, u32 y, float depth) void FramebufferManager::PokeEFBDepth(u32 x, u32 y, float depth)
{ {
// Flush if we exceeded the number of vertices per batch. // Flush if we exceeded the number of vertices per batch.
if ((m_color_poke_vertices.size() + 6) > MAX_POKE_VERTICES) if ((m_color_poke_vertices.size() + 6) > MAX_POKE_VERTICES)
FlushEFBPokes(state_tracker); FlushEFBPokes();
CreatePokeVertices(&m_depth_poke_vertices, x, y, depth, 0); CreatePokeVertices(&m_depth_poke_vertices, x, y, depth, 0);
@ -1140,27 +1143,22 @@ void FramebufferManager::CreatePokeVertices(std::vector<EFBPokeVertex>* destinat
} }
} }
void FramebufferManager::FlushEFBPokes(StateTracker* state_tracker) void FramebufferManager::FlushEFBPokes()
{ {
if (!m_color_poke_vertices.empty()) if (!m_color_poke_vertices.empty())
{ {
DrawPokeVertices(state_tracker, m_color_poke_vertices.data(), m_color_poke_vertices.size(), DrawPokeVertices(m_color_poke_vertices.data(), m_color_poke_vertices.size(), true, false);
true, false);
m_color_poke_vertices.clear(); m_color_poke_vertices.clear();
} }
if (!m_depth_poke_vertices.empty()) if (!m_depth_poke_vertices.empty())
{ {
DrawPokeVertices(state_tracker, m_depth_poke_vertices.data(), m_depth_poke_vertices.size(), DrawPokeVertices(m_depth_poke_vertices.data(), m_depth_poke_vertices.size(), false, true);
false, true);
m_depth_poke_vertices.clear(); m_depth_poke_vertices.clear();
} }
} }
void FramebufferManager::DrawPokeVertices(StateTracker* state_tracker, void FramebufferManager::DrawPokeVertices(const EFBPokeVertex* vertices, size_t vertex_count,
const EFBPokeVertex* vertices, size_t vertex_count,
bool write_color, bool write_depth) bool write_color, bool write_depth)
{ {
// Relatively simple since we don't have any bindings. // Relatively simple since we don't have any bindings.
@ -1205,7 +1203,7 @@ void FramebufferManager::DrawPokeVertices(StateTracker* state_tracker,
{ {
// Kick a command buffer first. // Kick a command buffer first.
WARN_LOG(VIDEO, "Kicking command buffer due to no EFB poke space."); WARN_LOG(VIDEO, "Kicking command buffer due to no EFB poke space.");
Util::ExecuteCurrentCommandsAndRestoreState(state_tracker, true); Util::ExecuteCurrentCommandsAndRestoreState(true);
command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
if (!m_poke_vertex_stream_buffer->ReserveMemory(vertices_size, sizeof(EfbPokeData), true, true, if (!m_poke_vertex_stream_buffer->ReserveMemory(vertices_size, sizeof(EfbPokeData), true, true,
@ -1221,9 +1219,9 @@ void FramebufferManager::DrawPokeVertices(StateTracker* state_tracker,
m_poke_vertex_stream_buffer->CommitMemory(vertices_size); m_poke_vertex_stream_buffer->CommitMemory(vertices_size);
// Set up state. // Set up state.
state_tracker->EndClearRenderPass(); StateTracker::GetInstance()->EndClearRenderPass();
state_tracker->BeginRenderPass(); StateTracker::GetInstance()->BeginRenderPass();
state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
Util::SetViewportAndScissor(command_buffer, 0, 0, m_efb_width, m_efb_height); Util::SetViewportAndScissor(command_buffer, 0, 0, m_efb_width, m_efb_height);
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdBindVertexBuffers(command_buffer, 0, 1, &vb_buffer, &vb_offset); vkCmdBindVertexBuffers(command_buffer, 0, 1, &vb_buffer, &vb_offset);

View File

@ -30,6 +30,8 @@ public:
FramebufferManager(); FramebufferManager();
~FramebufferManager(); ~FramebufferManager();
static FramebufferManager* GetInstance();
bool Initialize(); bool Initialize();
VkRenderPass GetEFBLoadRenderPass() const { return m_efb_load_render_pass; } VkRenderPass GetEFBLoadRenderPass() const { return m_efb_load_render_pass; }
@ -69,18 +71,18 @@ public:
// This render pass can be used for other readback operations. // This render pass can be used for other readback operations.
VkRenderPass GetColorCopyForReadbackRenderPass() const { return m_copy_color_render_pass; } VkRenderPass GetColorCopyForReadbackRenderPass() const { return m_copy_color_render_pass; }
// Resolve color/depth textures to a non-msaa texture, and return it. // Resolve color/depth textures to a non-msaa texture, and return it.
Texture2D* ResolveEFBColorTexture(StateTracker* state_tracker, const VkRect2D& region); Texture2D* ResolveEFBColorTexture(const VkRect2D& region);
Texture2D* ResolveEFBDepthTexture(StateTracker* state_tracker, const VkRect2D& region); Texture2D* ResolveEFBDepthTexture(const VkRect2D& region);
// Reads a framebuffer value back from the GPU. This may block if the cache is not current. // Reads a framebuffer value back from the GPU. This may block if the cache is not current.
u32 PeekEFBColor(StateTracker* state_tracker, u32 x, u32 y); u32 PeekEFBColor(u32 x, u32 y);
float PeekEFBDepth(StateTracker* state_tracker, u32 x, u32 y); float PeekEFBDepth(u32 x, u32 y);
void InvalidatePeekCache(); void InvalidatePeekCache();
// Writes a value to the framebuffer. This will never block, and writes will be batched. // Writes a value to the framebuffer. This will never block, and writes will be batched.
void PokeEFBColor(StateTracker* state_tracker, u32 x, u32 y, u32 color); void PokeEFBColor(u32 x, u32 y, u32 color);
void PokeEFBDepth(StateTracker* state_tracker, u32 x, u32 y, float depth); void PokeEFBDepth(u32 x, u32 y, float depth);
void FlushEFBPokes(StateTracker* state_tracker); void FlushEFBPokes();
private: private:
struct EFBPokeVertex struct EFBPokeVertex
@ -112,14 +114,14 @@ private:
bool CompilePokeShaders(); bool CompilePokeShaders();
void DestroyPokeShaders(); void DestroyPokeShaders();
bool PopulateColorReadbackTexture(StateTracker* state_tracker); bool PopulateColorReadbackTexture();
bool PopulateDepthReadbackTexture(StateTracker* state_tracker); bool PopulateDepthReadbackTexture();
void CreatePokeVertices(std::vector<EFBPokeVertex>* destination_list, u32 x, u32 y, float z, void CreatePokeVertices(std::vector<EFBPokeVertex>* destination_list, u32 x, u32 y, float z,
u32 color); u32 color);
void DrawPokeVertices(StateTracker* state_tracker, const EFBPokeVertex* vertices, void DrawPokeVertices(const EFBPokeVertex* vertices, size_t vertex_count, bool write_color,
size_t vertex_count, bool write_color, bool write_depth); bool write_depth);
VkRenderPass m_efb_load_render_pass = VK_NULL_HANDLE; VkRenderPass m_efb_load_render_pass = VK_NULL_HANDLE;
VkRenderPass m_efb_clear_render_pass = VK_NULL_HANDLE; VkRenderPass m_efb_clear_render_pass = VK_NULL_HANDLE;

View File

@ -62,8 +62,7 @@ bool PaletteTextureConverter::Initialize()
return true; return true;
} }
void PaletteTextureConverter::ConvertTexture(StateTracker* state_tracker, void PaletteTextureConverter::ConvertTexture(VkCommandBuffer command_buffer,
VkCommandBuffer command_buffer,
VkRenderPass render_pass, VkRenderPass render_pass,
VkFramebuffer dst_framebuffer, Texture2D* src_texture, VkFramebuffer dst_framebuffer, Texture2D* src_texture,
u32 width, u32 height, void* palette, u32 width, u32 height, void* palette,
@ -89,7 +88,7 @@ void PaletteTextureConverter::ConvertTexture(StateTracker* state_tracker,
g_command_buffer_mgr->AllocateDescriptorSet(m_palette_set_layout)) == VK_NULL_HANDLE) g_command_buffer_mgr->AllocateDescriptorSet(m_palette_set_layout)) == VK_NULL_HANDLE)
{ {
WARN_LOG(VIDEO, "Executing command list while waiting for space in palette buffer"); WARN_LOG(VIDEO, "Executing command list while waiting for space in palette buffer");
Util::ExecuteCurrentCommandsAndRestoreState(state_tracker, false); Util::ExecuteCurrentCommandsAndRestoreState(false);
if (!m_palette_stream_buffer->ReserveMemory(palette_size, if (!m_palette_stream_buffer->ReserveMemory(palette_size,
g_vulkan_context->GetTexelBufferAlignment()) || g_vulkan_context->GetTexelBufferAlignment()) ||

View File

@ -13,7 +13,6 @@
namespace Vulkan namespace Vulkan
{ {
class StateTracker;
class Texture2D; class Texture2D;
// Since this converter uses a uniform texel buffer, we can't use the general pipeline generators. // Since this converter uses a uniform texel buffer, we can't use the general pipeline generators.
@ -26,10 +25,9 @@ public:
bool Initialize(); bool Initialize();
void ConvertTexture(StateTracker* state_tracker, VkCommandBuffer command_buffer, void ConvertTexture(VkCommandBuffer command_buffer, VkRenderPass render_pass,
VkRenderPass render_pass, VkFramebuffer dst_framebuffer, VkFramebuffer dst_framebuffer, Texture2D* src_texture, u32 width, u32 height,
Texture2D* src_texture, u32 width, u32 height, void* palette, void* palette, TlutFormat format, u32 src_format);
TlutFormat format, u32 src_format);
private: private:
static const size_t NUM_PALETTE_CONVERSION_SHADERS = 3; static const size_t NUM_PALETTE_CONVERSION_SHADERS = 3;

View File

@ -32,10 +32,13 @@ PerfQuery::~PerfQuery()
vkDestroyQueryPool(g_vulkan_context->GetDevice(), m_query_pool, nullptr); vkDestroyQueryPool(g_vulkan_context->GetDevice(), m_query_pool, nullptr);
} }
bool PerfQuery::Initialize(StateTracker* state_tracker) Vulkan::PerfQuery* PerfQuery::GetInstance()
{ {
m_state_tracker = state_tracker; return static_cast<PerfQuery*>(g_perf_query.get());
}
bool PerfQuery::Initialize()
{
if (!CreateQueryPool()) if (!CreateQueryPool())
{ {
PanicAlert("Failed to create query pool"); PanicAlert("Failed to create query pool");
@ -86,11 +89,11 @@ void PerfQuery::EnableQuery(PerfQueryGroup type)
// Ensure the query starts within a render pass. // Ensure the query starts within a render pass.
// TODO: Is this needed? // TODO: Is this needed?
m_state_tracker->BeginRenderPass(); StateTracker::GetInstance()->BeginRenderPass();
vkCmdBeginQuery(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, index, flags); vkCmdBeginQuery(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, index, flags);
// Prevent background command buffer submission while the query is active. // Prevent background command buffer submission while the query is active.
m_state_tracker->SetBackgroundCommandBufferExecution(false); StateTracker::GetInstance()->SetBackgroundCommandBufferExecution(false);
} }
} }
@ -101,7 +104,7 @@ void PerfQuery::DisableQuery(PerfQueryGroup type)
// DisableQuery should be called for each EnableQuery, so subtract one to get the previous one. // DisableQuery should be called for each EnableQuery, so subtract one to get the previous one.
u32 index = (m_query_read_pos + m_query_count - 1) % PERF_QUERY_BUFFER_SIZE; u32 index = (m_query_read_pos + m_query_count - 1) % PERF_QUERY_BUFFER_SIZE;
vkCmdEndQuery(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, index); vkCmdEndQuery(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, index);
m_state_tracker->SetBackgroundCommandBufferExecution(true); StateTracker::GetInstance()->SetBackgroundCommandBufferExecution(true);
DEBUG_LOG(VIDEO, "end query %u", index); DEBUG_LOG(VIDEO, "end query %u", index);
} }
} }
@ -113,7 +116,7 @@ void PerfQuery::ResetQuery()
std::fill_n(m_results, ArraySize(m_results), 0); std::fill_n(m_results, ArraySize(m_results), 0);
// Reset entire query pool, ensuring all queries are ready to write to. // Reset entire query pool, ensuring all queries are ready to write to.
m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
vkCmdResetQueryPool(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, 0, vkCmdResetQueryPool(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_query_pool, 0,
PERF_QUERY_BUFFER_SIZE); PERF_QUERY_BUFFER_SIZE);
@ -346,7 +349,7 @@ void PerfQuery::NonBlockingPartialFlush()
// Submit a command buffer in the background if the front query is not bound to one. // Submit a command buffer in the background if the front query is not bound to one.
// Ideally this will complete before the buffer fills. // Ideally this will complete before the buffer fills.
if (m_query_buffer[m_query_read_pos].pending_fence == VK_NULL_HANDLE) if (m_query_buffer[m_query_read_pos].pending_fence == VK_NULL_HANDLE)
Util::ExecuteCurrentCommandsAndRestoreState(m_state_tracker, true, false); Util::ExecuteCurrentCommandsAndRestoreState(true, false);
} }
void PerfQuery::BlockingPartialFlush() void PerfQuery::BlockingPartialFlush()
@ -360,7 +363,7 @@ void PerfQuery::BlockingPartialFlush()
{ {
// This will callback OnCommandBufferQueued which will set the fence on the entry. // This will callback OnCommandBufferQueued which will set the fence on the entry.
// We wait for completion, which will also call OnCommandBufferExecuted, and clear the fence. // We wait for completion, which will also call OnCommandBufferExecuted, and clear the fence.
Util::ExecuteCurrentCommandsAndRestoreState(m_state_tracker, false, true); Util::ExecuteCurrentCommandsAndRestoreState(false, true);
} }
else else
{ {

View File

@ -14,7 +14,6 @@
namespace Vulkan namespace Vulkan
{ {
class StagingBuffer; class StagingBuffer;
class StateTracker;
class PerfQuery : public PerfQueryBase class PerfQuery : public PerfQueryBase
{ {
@ -22,7 +21,9 @@ public:
PerfQuery(); PerfQuery();
~PerfQuery(); ~PerfQuery();
bool Initialize(StateTracker* state_tracker); static PerfQuery* GetInstance();
bool Initialize();
void EnableQuery(PerfQueryGroup type) override; void EnableQuery(PerfQueryGroup type) override;
void DisableQuery(PerfQueryGroup type) override; void DisableQuery(PerfQueryGroup type) override;
@ -52,8 +53,6 @@ private:
void NonBlockingPartialFlush(); void NonBlockingPartialFlush();
void BlockingPartialFlush(); void BlockingPartialFlush();
StateTracker* m_state_tracker = nullptr;
// when testing in SMS: 64 was too small, 128 was ok // when testing in SMS: 64 was too small, 128 was ok
// TODO: This should be size_t, but the base class uses u32s // TODO: This should be size_t, but the base class uses u32s
using PerfQueryDataType = u32; using PerfQueryDataType = u32;

View File

@ -68,10 +68,13 @@ Renderer::~Renderer()
DestroySemaphores(); DestroySemaphores();
} }
bool Renderer::Initialize(FramebufferManager* framebuffer_mgr) Renderer* Renderer::GetInstance()
{
return static_cast<Renderer*>(g_renderer.get());
}
bool Renderer::Initialize()
{ {
m_framebuffer_mgr = framebuffer_mgr;
m_state_tracker = std::make_unique<StateTracker>();
BindEFBToStateTracker(); BindEFBToStateTracker();
if (!CreateSemaphores()) if (!CreateSemaphores())
@ -103,9 +106,9 @@ bool Renderer::Initialize(FramebufferManager* framebuffer_mgr)
if (g_vulkan_context->SupportsBoundingBox()) if (g_vulkan_context->SupportsBoundingBox())
{ {
// Bind bounding box to state tracker // Bind bounding box to state tracker
m_state_tracker->SetBBoxBuffer(m_bounding_box->GetGPUBuffer(), StateTracker::GetInstance()->SetBBoxBuffer(m_bounding_box->GetGPUBuffer(),
m_bounding_box->GetGPUBufferOffset(), m_bounding_box->GetGPUBufferOffset(),
m_bounding_box->GetGPUBufferSize()); m_bounding_box->GetGPUBufferSize());
} }
// Various initialization routines will have executed commands on the command buffer. // Various initialization routines will have executed commands on the command buffer.
@ -170,7 +173,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{ {
if (type == PEEK_COLOR) if (type == PEEK_COLOR)
{ {
u32 color = m_framebuffer_mgr->PeekEFBColor(m_state_tracker.get(), x, y); u32 color = FramebufferManager::GetInstance()->PeekEFBColor(x, y);
// a little-endian value is expected to be returned // a little-endian value is expected to be returned
color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000)); color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000));
@ -207,7 +210,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
else // if (type == PEEK_Z) else // if (type == PEEK_Z)
{ {
// Depth buffer is inverted for improved precision near far plane // Depth buffer is inverted for improved precision near far plane
float depth = 1.0f - m_framebuffer_mgr->PeekEFBDepth(m_state_tracker.get(), x, y); float depth = 1.0f - FramebufferManager::GetInstance()->PeekEFBDepth(x, y);
u32 ret = 0; u32 ret = 0;
if (bpmem.zcontrol.pixel_format == PEControl::RGB565_Z16) if (bpmem.zcontrol.pixel_format == PEControl::RGB565_Z16)
@ -235,7 +238,7 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num
const EfbPokeData& point = points[i]; const EfbPokeData& point = points[i];
u32 color = ((point.data & 0xFF00FF00) | ((point.data >> 16) & 0xFF) | u32 color = ((point.data & 0xFF00FF00) | ((point.data >> 16) & 0xFF) |
((point.data << 16) & 0xFF0000)); ((point.data << 16) & 0xFF0000));
m_framebuffer_mgr->PokeEFBColor(m_state_tracker.get(), point.x, point.y, color); FramebufferManager::GetInstance()->PokeEFBColor(point.x, point.y, color);
} }
} }
else // if (type == POKE_Z) else // if (type == POKE_Z)
@ -245,14 +248,14 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num
// Convert to floating-point depth. // Convert to floating-point depth.
const EfbPokeData& point = points[i]; const EfbPokeData& point = points[i];
float depth = (1.0f - float(point.data & 0xFFFFFF) / 16777216.0f); float depth = (1.0f - float(point.data & 0xFFFFFF) / 16777216.0f);
m_framebuffer_mgr->PokeEFBDepth(m_state_tracker.get(), point.x, point.y, depth); FramebufferManager::GetInstance()->PokeEFBDepth(point.x, point.y, depth);
} }
} }
} }
u16 Renderer::BBoxRead(int index) u16 Renderer::BBoxRead(int index)
{ {
s32 value = m_bounding_box->Get(m_state_tracker.get(), static_cast<size_t>(index)); s32 value = m_bounding_box->Get(static_cast<size_t>(index));
// Here we get the min/max value of the truncated position of the upscaled framebuffer. // Here we get the min/max value of the truncated position of the upscaled framebuffer.
// So we have to correct them to the unscaled EFB sizes. // So we have to correct them to the unscaled EFB sizes.
@ -294,7 +297,7 @@ void Renderer::BBoxWrite(int index, u16 value)
scaled_value = scaled_value * s_target_height / EFB_HEIGHT; scaled_value = scaled_value * s_target_height / EFB_HEIGHT;
} }
m_bounding_box->Set(m_state_tracker.get(), static_cast<size_t>(index), scaled_value); m_bounding_box->Set(static_cast<size_t>(index), scaled_value);
} }
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
@ -314,8 +317,8 @@ void Renderer::BeginFrame()
// Ensure that the state tracker rebinds everything, and allocates a new set // Ensure that the state tracker rebinds everything, and allocates a new set
// of descriptors out of the next pool. // of descriptors out of the next pool.
m_state_tracker->InvalidateDescriptorSets(); StateTracker::GetInstance()->InvalidateDescriptorSets();
m_state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
} }
void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable, void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable,
@ -350,7 +353,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
// If we're not in a render pass (start of the frame), we can use a clear render pass // If we're not in a render pass (start of the frame), we can use a clear render pass
// to discard the data, rather than loading and then clearing. // to discard the data, rather than loading and then clearing.
bool use_clear_render_pass = (color_enable && alpha_enable && z_enable); bool use_clear_render_pass = (color_enable && alpha_enable && z_enable);
if (m_state_tracker->InRenderPass()) if (StateTracker::GetInstance()->InRenderPass())
{ {
// Prefer not to end a render pass just to do a clear. // Prefer not to end a render pass just to do a clear.
use_clear_render_pass = false; use_clear_render_pass = false;
@ -360,7 +363,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
if (use_clear_render_pass) if (use_clear_render_pass)
{ {
VkClearValue clear_values[2] = {clear_color_value, clear_depth_value}; VkClearValue clear_values[2] = {clear_color_value, clear_depth_value};
m_state_tracker->BeginClearRenderPass(target_vk_rc, clear_values); StateTracker::GetInstance()->BeginClearRenderPass(target_vk_rc, clear_values);
return; return;
} }
@ -388,17 +391,17 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
} }
if (num_clear_attachments > 0) if (num_clear_attachments > 0)
{ {
VkClearRect clear_rect = {target_vk_rc, 0, m_framebuffer_mgr->GetEFBLayers()}; VkClearRect vk_rect = {target_vk_rc, 0, FramebufferManager::GetInstance()->GetEFBLayers()};
if (!m_state_tracker->IsWithinRenderArea(target_vk_rc.offset.x, target_vk_rc.offset.y, if (!StateTracker::GetInstance()->IsWithinRenderArea(
target_vk_rc.extent.width, target_vk_rc.offset.x, target_vk_rc.offset.y, target_vk_rc.extent.width,
target_vk_rc.extent.height)) target_vk_rc.extent.height))
{ {
m_state_tracker->EndClearRenderPass(); StateTracker::GetInstance()->EndClearRenderPass();
} }
m_state_tracker->BeginRenderPass(); StateTracker::GetInstance()->BeginRenderPass();
vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_clear_attachments, vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_clear_attachments,
clear_attachments, 1, &clear_rect); clear_attachments, 1, &vk_rect);
} }
} }
@ -407,13 +410,14 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
return; return;
// Clearing must occur within a render pass. // Clearing must occur within a render pass.
if (!m_state_tracker->IsWithinRenderArea(target_vk_rc.offset.x, target_vk_rc.offset.y, if (!StateTracker::GetInstance()->IsWithinRenderArea(target_vk_rc.offset.x, target_vk_rc.offset.y,
target_vk_rc.extent.width, target_vk_rc.extent.height)) target_vk_rc.extent.width,
target_vk_rc.extent.height))
{ {
m_state_tracker->EndClearRenderPass(); StateTracker::GetInstance()->EndClearRenderPass();
} }
m_state_tracker->BeginRenderPass(); StateTracker::GetInstance()->BeginRenderPass();
m_state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
// Mask away the appropriate colors and use a shader // Mask away the appropriate colors and use a shader
BlendState blend_state = Util::GetNoBlendingBlendState(); BlendState blend_state = Util::GetNoBlendingBlendState();
@ -431,13 +435,14 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
RasterizationState rs_state = Util::GetNoCullRasterizationState(); RasterizationState rs_state = Util::GetNoCullRasterizationState();
rs_state.per_sample_shading = g_ActiveConfig.bSSAA ? VK_TRUE : VK_FALSE; rs_state.per_sample_shading = g_ActiveConfig.bSSAA ? VK_TRUE : VK_FALSE;
rs_state.samples = m_framebuffer_mgr->GetEFBSamples(); rs_state.samples = FramebufferManager::GetInstance()->GetEFBSamples();
// No need to start a new render pass, but we do need to restore viewport state // No need to start a new render pass, but we do need to restore viewport state
UtilityShaderDraw draw( UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetStandardPipelineLayout(), g_object_cache->GetStandardPipelineLayout(),
m_framebuffer_mgr->GetEFBLoadRenderPass(), g_object_cache->GetPassthroughVertexShader(), FramebufferManager::GetInstance()->GetEFBLoadRenderPass(),
g_object_cache->GetPassthroughGeometryShader(), m_clear_fragment_shader); g_object_cache->GetPassthroughVertexShader(),
g_object_cache->GetPassthroughGeometryShader(), m_clear_fragment_shader);
draw.SetRasterizationState(rs_state); draw.SetRasterizationState(rs_state);
draw.SetDepthStencilState(depth_state); draw.SetDepthStencilState(depth_state);
@ -451,9 +456,9 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
void Renderer::ReinterpretPixelData(unsigned int convtype) void Renderer::ReinterpretPixelData(unsigned int convtype)
{ {
m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
m_state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
m_framebuffer_mgr->ReinterpretPixelData(convtype); FramebufferManager::GetInstance()->ReinterpretPixelData(convtype);
// EFB framebuffer has now changed, so update accordingly. // EFB framebuffer has now changed, so update accordingly.
BindEFBToStateTracker(); BindEFBToStateTracker();
@ -463,20 +468,21 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
const EFBRectangle& rc, u64 ticks, float gamma) const EFBRectangle& rc, u64 ticks, float gamma)
{ {
// Flush any pending EFB pokes. // Flush any pending EFB pokes.
m_framebuffer_mgr->FlushEFBPokes(m_state_tracker.get()); FramebufferManager::GetInstance()->FlushEFBPokes();
// End the current render pass. // End the current render pass.
m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
m_state_tracker->OnEndFrame(); StateTracker::GetInstance()->OnEndFrame();
// Scale the source rectangle to the selected internal resolution. // Scale the source rectangle to the selected internal resolution.
TargetRectangle source_rc = Renderer::ConvertEFBRectangle(rc); TargetRectangle source_rc = Renderer::ConvertEFBRectangle(rc);
// Transition the EFB render target to a shader resource. // Transition the EFB render target to a shader resource.
VkRect2D src_region = {{0, 0}, VkRect2D src_region = {{0, 0},
{m_framebuffer_mgr->GetEFBWidth(), m_framebuffer_mgr->GetEFBHeight()}}; {FramebufferManager::GetInstance()->GetEFBWidth(),
FramebufferManager::GetInstance()->GetEFBHeight()}};
Texture2D* efb_color_texture = Texture2D* efb_color_texture =
m_framebuffer_mgr->ResolveEFBColorTexture(m_state_tracker.get(), src_region); FramebufferManager::GetInstance()->ResolveEFBColorTexture(src_region);
efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
@ -491,7 +497,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
} }
// Restore the EFB color texture to color attachment ready for rendering the next frame. // Restore the EFB color texture to color attachment ready for rendering the next frame.
m_framebuffer_mgr->GetEFBColorTexture()->TransitionToLayout( FramebufferManager::GetInstance()->GetEFBColorTexture()->TransitionToLayout(
g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Ensure the worker thread is not still submitting a previous command buffer. // Ensure the worker thread is not still submitting a previous command buffer.
@ -613,19 +619,20 @@ bool Renderer::DrawScreenshot(const TargetRectangle& src_rect, const Texture2D*
VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
VkClearRect clear_rect = {{{0, 0}, {width, height}}, 0, 1}; VkClearRect clear_rect = {{{0, 0}, {width, height}}, 0, 1};
VkClearAttachment clear_attachment = {VK_IMAGE_ASPECT_COLOR_BIT, 0, clear_value}; VkClearAttachment clear_attachment = {VK_IMAGE_ASPECT_COLOR_BIT, 0, clear_value};
VkRenderPassBeginInfo info = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, VkRenderPassBeginInfo info = {
nullptr, VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
m_framebuffer_mgr->GetColorCopyForReadbackRenderPass(), nullptr,
m_screenshot_framebuffer, FramebufferManager::GetInstance()->GetColorCopyForReadbackRenderPass(),
{{0, 0}, {width, height}}, m_screenshot_framebuffer,
1, {{0, 0}, {width, height}},
&clear_value}; 1,
&clear_value};
vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &info, vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &info,
VK_SUBPASS_CONTENTS_INLINE); VK_SUBPASS_CONTENTS_INLINE);
vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(), 1, &clear_attachment, 1, vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(), 1, &clear_attachment, 1,
&clear_rect); &clear_rect);
BlitScreen(m_framebuffer_mgr->GetColorCopyForReadbackRenderPass(), target_rect, src_rect, src_tex, BlitScreen(FramebufferManager::GetInstance()->GetColorCopyForReadbackRenderPass(), target_rect,
true); src_rect, src_tex, true);
vkCmdEndRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer()); vkCmdEndRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer());
// Copy to the readback texture. // Copy to the readback texture.
@ -712,7 +719,7 @@ bool Renderer::ResizeScreenshotBuffer(u32 new_width, u32 new_height)
VkImageView attachment = m_screenshot_render_texture->GetView(); VkImageView attachment = m_screenshot_render_texture->GetView();
VkFramebufferCreateInfo info = {}; VkFramebufferCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
info.renderPass = m_framebuffer_mgr->GetColorCopyForReadbackRenderPass(); info.renderPass = FramebufferManager::GetInstance()->GetColorCopyForReadbackRenderPass();
info.attachmentCount = 1; info.attachmentCount = 1;
info.pAttachments = &attachment; info.pAttachments = &attachment;
info.width = new_width; info.width = new_width;
@ -889,8 +896,8 @@ void Renderer::CheckForConfigChanges()
if (msaa_changed || stereo_changed) if (msaa_changed || stereo_changed)
{ {
g_command_buffer_mgr->WaitForGPUIdle(); g_command_buffer_mgr->WaitForGPUIdle();
m_framebuffer_mgr->RecreateRenderPass(); FramebufferManager::GetInstance()->RecreateRenderPass();
m_framebuffer_mgr->ResizeEFBTextures(); FramebufferManager::GetInstance()->ResizeEFBTextures();
BindEFBToStateTracker(); BindEFBToStateTracker();
} }
@ -900,7 +907,7 @@ void Renderer::CheckForConfigChanges()
{ {
g_command_buffer_mgr->WaitForGPUIdle(); g_command_buffer_mgr->WaitForGPUIdle();
RecompileShaders(); RecompileShaders();
m_framebuffer_mgr->RecompileShaders(); FramebufferManager::GetInstance()->RecompileShaders();
g_object_cache->ClearPipelineCache(); g_object_cache->ClearPipelineCache();
} }
@ -931,25 +938,28 @@ void Renderer::OnSwapChainResized()
void Renderer::BindEFBToStateTracker() void Renderer::BindEFBToStateTracker()
{ {
// Update framebuffer in state tracker // Update framebuffer in state tracker
VkRect2D framebuffer_size = { VkRect2D framebuffer_size = {{0, 0},
{0, 0}, {m_framebuffer_mgr->GetEFBWidth(), m_framebuffer_mgr->GetEFBHeight()}}; {FramebufferManager::GetInstance()->GetEFBWidth(),
m_state_tracker->SetRenderPass(m_framebuffer_mgr->GetEFBLoadRenderPass(), FramebufferManager::GetInstance()->GetEFBHeight()}};
m_framebuffer_mgr->GetEFBClearRenderPass()); StateTracker::GetInstance()->SetRenderPass(
m_state_tracker->SetFramebuffer(m_framebuffer_mgr->GetEFBFramebuffer(), framebuffer_size); FramebufferManager::GetInstance()->GetEFBLoadRenderPass(),
FramebufferManager::GetInstance()->GetEFBClearRenderPass());
StateTracker::GetInstance()->SetFramebuffer(
FramebufferManager::GetInstance()->GetEFBFramebuffer(), framebuffer_size);
// Update rasterization state with MSAA info // Update rasterization state with MSAA info
RasterizationState rs_state = {}; RasterizationState rs_state = {};
rs_state.bits = m_state_tracker->GetRasterizationState().bits; rs_state.bits = StateTracker::GetInstance()->GetRasterizationState().bits;
rs_state.samples = m_framebuffer_mgr->GetEFBSamples(); rs_state.samples = FramebufferManager::GetInstance()->GetEFBSamples();
rs_state.per_sample_shading = g_ActiveConfig.bSSAA ? VK_TRUE : VK_FALSE; rs_state.per_sample_shading = g_ActiveConfig.bSSAA ? VK_TRUE : VK_FALSE;
m_state_tracker->SetRasterizationState(rs_state); StateTracker::GetInstance()->SetRasterizationState(rs_state);
} }
void Renderer::ResizeEFBTextures() void Renderer::ResizeEFBTextures()
{ {
// Ensure the GPU is finished with the current EFB textures. // Ensure the GPU is finished with the current EFB textures.
g_command_buffer_mgr->WaitForGPUIdle(); g_command_buffer_mgr->WaitForGPUIdle();
m_framebuffer_mgr->ResizeEFBTextures(); FramebufferManager::GetInstance()->ResizeEFBTextures();
BindEFBToStateTracker(); BindEFBToStateTracker();
// Viewport and scissor rect have to be reset since they will be scaled differently. // Viewport and scissor rect have to be reset since they will be scaled differently.
@ -976,19 +986,19 @@ void Renderer::ApplyState(bool bUseDstAlpha)
void Renderer::ResetAPIState() void Renderer::ResetAPIState()
{ {
// End the EFB render pass if active // End the EFB render pass if active
m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
} }
void Renderer::RestoreAPIState() void Renderer::RestoreAPIState()
{ {
// Instruct the state tracker to re-bind everything before the next draw // Instruct the state tracker to re-bind everything before the next draw
m_state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
} }
void Renderer::SetGenerationMode() void Renderer::SetGenerationMode()
{ {
RasterizationState new_rs_state = {}; RasterizationState new_rs_state = {};
new_rs_state.bits = m_state_tracker->GetRasterizationState().bits; new_rs_state.bits = StateTracker::GetInstance()->GetRasterizationState().bits;
switch (bpmem.genMode.cullmode) switch (bpmem.genMode.cullmode)
{ {
@ -1009,7 +1019,7 @@ void Renderer::SetGenerationMode()
break; break;
} }
m_state_tracker->SetRasterizationState(new_rs_state); StateTracker::GetInstance()->SetRasterizationState(new_rs_state);
} }
void Renderer::SetDepthMode() void Renderer::SetDepthMode()
@ -1050,7 +1060,7 @@ void Renderer::SetDepthMode()
break; break;
} }
m_state_tracker->SetDepthStencilState(new_ds_state); StateTracker::GetInstance()->SetDepthStencilState(new_ds_state);
} }
void Renderer::SetColorMask() void Renderer::SetColorMask()
@ -1066,16 +1076,16 @@ void Renderer::SetColorMask()
} }
BlendState new_blend_state = {}; BlendState new_blend_state = {};
new_blend_state.bits = m_state_tracker->GetBlendState().bits; new_blend_state.bits = StateTracker::GetInstance()->GetBlendState().bits;
new_blend_state.write_mask = color_mask; new_blend_state.write_mask = color_mask;
m_state_tracker->SetBlendState(new_blend_state); StateTracker::GetInstance()->SetBlendState(new_blend_state);
} }
void Renderer::SetBlendMode(bool force_update) void Renderer::SetBlendMode(bool force_update)
{ {
BlendState new_blend_state = {}; BlendState new_blend_state = {};
new_blend_state.bits = m_state_tracker->GetBlendState().bits; new_blend_state.bits = StateTracker::GetInstance()->GetBlendState().bits;
// Fast path for blending disabled // Fast path for blending disabled
if (!bpmem.blendmode.blendenable) if (!bpmem.blendmode.blendenable)
@ -1087,7 +1097,7 @@ void Renderer::SetBlendMode(bool force_update)
new_blend_state.alpha_blend_op = VK_BLEND_OP_ADD; new_blend_state.alpha_blend_op = VK_BLEND_OP_ADD;
new_blend_state.src_alpha_blend = VK_BLEND_FACTOR_ONE; new_blend_state.src_alpha_blend = VK_BLEND_FACTOR_ONE;
new_blend_state.dst_alpha_blend = VK_BLEND_FACTOR_ZERO; new_blend_state.dst_alpha_blend = VK_BLEND_FACTOR_ZERO;
m_state_tracker->SetBlendState(new_blend_state); StateTracker::GetInstance()->SetBlendState(new_blend_state);
return; return;
} }
// Fast path for subtract blending // Fast path for subtract blending
@ -1100,7 +1110,7 @@ void Renderer::SetBlendMode(bool force_update)
new_blend_state.alpha_blend_op = VK_BLEND_OP_REVERSE_SUBTRACT; new_blend_state.alpha_blend_op = VK_BLEND_OP_REVERSE_SUBTRACT;
new_blend_state.src_alpha_blend = VK_BLEND_FACTOR_ONE; new_blend_state.src_alpha_blend = VK_BLEND_FACTOR_ONE;
new_blend_state.dst_alpha_blend = VK_BLEND_FACTOR_ONE; new_blend_state.dst_alpha_blend = VK_BLEND_FACTOR_ONE;
m_state_tracker->SetBlendState(new_blend_state); StateTracker::GetInstance()->SetBlendState(new_blend_state);
return; return;
} }
@ -1195,13 +1205,13 @@ void Renderer::SetBlendMode(bool force_update)
new_blend_state.dst_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.dst_blend); new_blend_state.dst_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.dst_blend);
} }
m_state_tracker->SetBlendState(new_blend_state); StateTracker::GetInstance()->SetBlendState(new_blend_state);
} }
void Renderer::SetLogicOpMode() void Renderer::SetLogicOpMode()
{ {
BlendState new_blend_state = {}; BlendState new_blend_state = {};
new_blend_state.bits = m_state_tracker->GetBlendState().bits; new_blend_state.bits = StateTracker::GetInstance()->GetBlendState().bits;
// Does our device support logic ops? // Does our device support logic ops?
bool logic_op_enable = bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable; bool logic_op_enable = bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable;
@ -1224,7 +1234,7 @@ void Renderer::SetLogicOpMode()
new_blend_state.logic_op = VK_LOGIC_OP_CLEAR; new_blend_state.logic_op = VK_LOGIC_OP_CLEAR;
} }
m_state_tracker->SetBlendState(new_blend_state); StateTracker::GetInstance()->SetBlendState(new_blend_state);
} }
else else
{ {
@ -1269,7 +1279,7 @@ void Renderer::SetLogicOpMode()
new_blend_state.src_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.src_blend); new_blend_state.src_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.src_blend);
new_blend_state.dst_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.dst_blend); new_blend_state.dst_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.dst_blend);
m_state_tracker->SetBlendState(new_blend_state); StateTracker::GetInstance()->SetBlendState(new_blend_state);
} }
else else
{ {
@ -1338,7 +1348,7 @@ void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
sampler = g_object_cache->GetPointSampler(); sampler = g_object_cache->GetPointSampler();
} }
m_state_tracker->SetSampler(bind_index, sampler); StateTracker::GetInstance()->SetSampler(bind_index, sampler);
m_sampler_states[bind_index].bits = new_state.bits; m_sampler_states[bind_index].bits = new_state.bits;
} }
@ -1352,7 +1362,7 @@ void Renderer::ResetSamplerStates()
for (size_t i = 0; i < m_sampler_states.size(); i++) for (size_t i = 0; i < m_sampler_states.size(); i++)
{ {
m_sampler_states[i].bits = std::numeric_limits<decltype(m_sampler_states[i].bits)>::max(); m_sampler_states[i].bits = std::numeric_limits<decltype(m_sampler_states[i].bits)>::max();
m_state_tracker->SetSampler(i, g_object_cache->GetPointSampler()); StateTracker::GetInstance()->SetSampler(i, g_object_cache->GetPointSampler());
} }
// Invalidate all sampler objects (some will be unused now). // Invalidate all sampler objects (some will be unused now).
@ -1375,7 +1385,7 @@ void Renderer::SetScissorRect(const EFBRectangle& rc)
{target_rc.left, target_rc.top}, {target_rc.left, target_rc.top},
{static_cast<uint32_t>(target_rc.GetWidth()), static_cast<uint32_t>(target_rc.GetHeight())}}; {static_cast<uint32_t>(target_rc.GetWidth()), static_cast<uint32_t>(target_rc.GetHeight())}};
m_state_tracker->SetScissor(scissor); StateTracker::GetInstance()->SetScissor(scissor);
} }
void Renderer::SetViewport() void Renderer::SetViewport()
@ -1420,7 +1430,7 @@ void Renderer::SetViewport()
} }
VkViewport viewport = {x, y, width, height, min_depth, max_depth}; VkViewport viewport = {x, y, width, height, min_depth, max_depth};
m_state_tracker->SetViewport(viewport); StateTracker::GetInstance()->SetViewport(viewport);
} }
void Renderer::ChangeSurface(void* new_surface_handle) void Renderer::ChangeSurface(void* new_surface_handle)

View File

@ -18,7 +18,6 @@ class BoundingBox;
class FramebufferManager; class FramebufferManager;
class SwapChain; class SwapChain;
class StagingTexture2D; class StagingTexture2D;
class StateTracker;
class Texture2D; class Texture2D;
class RasterFont; class RasterFont;
@ -28,10 +27,11 @@ public:
Renderer(std::unique_ptr<SwapChain> swap_chain); Renderer(std::unique_ptr<SwapChain> swap_chain);
~Renderer(); ~Renderer();
static Renderer* GetInstance();
SwapChain* GetSwapChain() const { return m_swap_chain.get(); } SwapChain* GetSwapChain() const { return m_swap_chain.get(); }
StateTracker* GetStateTracker() const { return m_state_tracker.get(); }
BoundingBox* GetBoundingBox() const { return m_bounding_box.get(); } BoundingBox* GetBoundingBox() const { return m_bounding_box.get(); }
bool Initialize(FramebufferManager* framebuffer_mgr); bool Initialize();
void RenderText(const std::string& pstr, int left, int top, u32 color) override; void RenderText(const std::string& pstr, int left, int top, u32 color) override;
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override; u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
@ -94,13 +94,11 @@ private:
const TargetRectangle& src_rect, const Texture2D* src_tex, bool linear_filter); const TargetRectangle& src_rect, const Texture2D* src_tex, bool linear_filter);
bool ResizeScreenshotBuffer(u32 new_width, u32 new_height); bool ResizeScreenshotBuffer(u32 new_width, u32 new_height);
void DestroyScreenshotResources(); void DestroyScreenshotResources();
FramebufferManager* m_framebuffer_mgr = nullptr;
VkSemaphore m_image_available_semaphore = VK_NULL_HANDLE; VkSemaphore m_image_available_semaphore = VK_NULL_HANDLE;
VkSemaphore m_rendering_finished_semaphore = VK_NULL_HANDLE; VkSemaphore m_rendering_finished_semaphore = VK_NULL_HANDLE;
std::unique_ptr<SwapChain> m_swap_chain; std::unique_ptr<SwapChain> m_swap_chain;
std::unique_ptr<StateTracker> m_state_tracker;
std::unique_ptr<BoundingBox> m_bounding_box; std::unique_ptr<BoundingBox> m_bounding_box;
std::unique_ptr<RasterFont> m_raster_font; std::unique_ptr<RasterFont> m_raster_font;

View File

@ -24,10 +24,33 @@
namespace Vulkan namespace Vulkan
{ {
StateTracker::StateTracker() static std::unique_ptr<StateTracker> s_state_tracker;
StateTracker* StateTracker::GetInstance()
{
return s_state_tracker.get();
}
bool StateTracker::CreateInstance()
{
_assert_(!s_state_tracker);
s_state_tracker = std::make_unique<StateTracker>();
if (!s_state_tracker->Initialize())
{
s_state_tracker.reset();
return false;
}
return true;
}
void StateTracker::DestroyInstance()
{
s_state_tracker.reset();
}
bool StateTracker::Initialize()
{ {
// Set some sensible defaults // Set some sensible defaults
m_pipeline_state.pipeline_layout = g_object_cache->GetStandardPipelineLayout();
m_pipeline_state.rasterization_state.cull_mode = VK_CULL_MODE_NONE; m_pipeline_state.rasterization_state.cull_mode = VK_CULL_MODE_NONE;
m_pipeline_state.rasterization_state.per_sample_shading = VK_FALSE; m_pipeline_state.rasterization_state.per_sample_shading = VK_FALSE;
m_pipeline_state.rasterization_state.depth_clamp = VK_FALSE; m_pipeline_state.rasterization_state.depth_clamp = VK_FALSE;
@ -68,7 +91,10 @@ StateTracker::StateTracker()
StreamBuffer::Create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, INITIAL_UNIFORM_STREAM_BUFFER_SIZE, StreamBuffer::Create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, INITIAL_UNIFORM_STREAM_BUFFER_SIZE,
MAXIMUM_UNIFORM_STREAM_BUFFER_SIZE); MAXIMUM_UNIFORM_STREAM_BUFFER_SIZE);
if (!m_uniform_stream_buffer) if (!m_uniform_stream_buffer)
{
PanicAlert("Failed to create uniform stream buffer"); PanicAlert("Failed to create uniform stream buffer");
return false;
}
// The validation layer complains if max(offsets) + max(ubo_ranges) >= ubo_size. // The validation layer complains if max(offsets) + max(ubo_ranges) >= ubo_size.
// To work around this we reserve the maximum buffer size at all times, but only commit // To work around this we reserve the maximum buffer size at all times, but only commit
@ -87,10 +113,7 @@ StateTracker::StateTracker()
// Set default constants // Set default constants
UploadAllConstants(); UploadAllConstants();
} return true;
StateTracker::~StateTracker()
{
} }
void StateTracker::SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset) void StateTracker::SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset)
@ -372,7 +395,7 @@ void StateTracker::UploadAllConstants()
// If this fails, wait until the GPU has caught up. // If this fails, wait until the GPU has caught up.
// The only places that call constant updates are safe to have state restored. // The only places that call constant updates are safe to have state restored.
WARN_LOG(VIDEO, "Executing command list while waiting for space in uniform buffer"); WARN_LOG(VIDEO, "Executing command list while waiting for space in uniform buffer");
Util::ExecuteCurrentCommandsAndRestoreState(this, false); Util::ExecuteCurrentCommandsAndRestoreState(false);
if (!m_uniform_stream_buffer->ReserveMemory(total_allocation_size, if (!m_uniform_stream_buffer->ReserveMemory(total_allocation_size,
g_vulkan_context->GetUniformBufferAlignment(), true, g_vulkan_context->GetUniformBufferAlignment(), true,
true, false)) true, false))

View File

@ -24,8 +24,12 @@ class VertexFormat;
class StateTracker class StateTracker
{ {
public: public:
StateTracker(); StateTracker() = default;
~StateTracker(); ~StateTracker() = default;
static StateTracker* GetInstance();
static bool CreateInstance();
static void DestroyInstance();
const RasterizationState& GetRasterizationState() const const RasterizationState& GetRasterizationState() const
{ {
@ -108,6 +112,8 @@ public:
bool IsWithinRenderArea(s32 x, s32 y, u32 width, u32 height) const; bool IsWithinRenderArea(s32 x, s32 y, u32 width, u32 height) const;
private: private:
bool Initialize();
// Check that the specified viewport is within the render area. // Check that the specified viewport is within the render area.
// If not, ends the render pass if it is a clear render pass. // If not, ends the render pass if it is a clear render pass.
bool IsViewportWithinRenderArea() const; bool IsViewportWithinRenderArea() const;

View File

@ -44,9 +44,13 @@ TextureCache::~TextureCache()
TextureCache::DeleteShaders(); TextureCache::DeleteShaders();
} }
bool TextureCache::Initialize(StateTracker* state_tracker) TextureCache* TextureCache::GetInstance()
{
return static_cast<TextureCache*>(g_texture_cache.get());
}
bool TextureCache::Initialize()
{ {
m_state_tracker = state_tracker;
m_texture_upload_buffer = m_texture_upload_buffer =
StreamBuffer::Create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, INITIAL_TEXTURE_UPLOAD_BUFFER_SIZE, StreamBuffer::Create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, INITIAL_TEXTURE_UPLOAD_BUFFER_SIZE,
MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE); MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE);
@ -99,8 +103,8 @@ void TextureCache::ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase*
if (unconverted->IsEfbCopy()) if (unconverted->IsEfbCopy())
{ {
command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
m_state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
} }
else else
{ {
@ -109,9 +113,9 @@ void TextureCache::ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase*
} }
m_palette_texture_converter->ConvertTexture( m_palette_texture_converter->ConvertTexture(
m_state_tracker, command_buffer, GetRenderPassForTextureUpdate(entry->GetTexture()), command_buffer, GetRenderPassForTextureUpdate(entry->GetTexture()), entry->GetFramebuffer(),
entry->GetFramebuffer(), unconverted->GetTexture(), entry->config.width, entry->config.height, unconverted->GetTexture(), entry->config.width, entry->config.height, palette, format,
palette, format, unconverted->format); unconverted->format);
// Render pass transitions to SHADER_READ_ONLY. // Render pass transitions to SHADER_READ_ONLY.
entry->GetTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); entry->GetTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
@ -121,12 +125,8 @@ void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_
u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat src_format, u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat src_format,
const EFBRectangle& src_rect, bool is_intensity, bool scale_by_half) const EFBRectangle& src_rect, bool is_intensity, bool scale_by_half)
{ {
// A better way of doing this would be nice.
FramebufferManager* framebuffer_mgr =
static_cast<FramebufferManager*>(g_framebuffer_manager.get());
// Flush EFB pokes first, as they're expected to be included. // Flush EFB pokes first, as they're expected to be included.
framebuffer_mgr->FlushEFBPokes(m_state_tracker); FramebufferManager::GetInstance()->FlushEFBPokes();
// MSAA case where we need to resolve first. // MSAA case where we need to resolve first.
// TODO: Do in one pass. // TODO: Do in one pass.
@ -134,24 +134,26 @@ void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_
VkRect2D region = {{scaled_src_rect.left, scaled_src_rect.top}, VkRect2D region = {{scaled_src_rect.left, scaled_src_rect.top},
{static_cast<u32>(scaled_src_rect.GetWidth()), {static_cast<u32>(scaled_src_rect.GetWidth()),
static_cast<u32>(scaled_src_rect.GetHeight())}}; static_cast<u32>(scaled_src_rect.GetHeight())}};
Texture2D* src_texture = (src_format == PEControl::Z24) ? Texture2D* src_texture;
framebuffer_mgr->ResolveEFBDepthTexture(m_state_tracker, region) : if (src_format == PEControl::Z24)
framebuffer_mgr->ResolveEFBColorTexture(m_state_tracker, region); src_texture = FramebufferManager::GetInstance()->ResolveEFBDepthTexture(region);
else
src_texture = FramebufferManager::GetInstance()->ResolveEFBColorTexture(region);
// End render pass before barrier (since we have no self-dependencies) // End render pass before barrier (since we have no self-dependencies)
m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
m_state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
m_state_tracker->InvalidateDescriptorSets(); StateTracker::GetInstance()->InvalidateDescriptorSets();
m_state_tracker->OnReadback(); StateTracker::GetInstance()->OnReadback();
// Transition to shader resource before reading. // Transition to shader resource before reading.
VkImageLayout original_layout = src_texture->GetLayout(); VkImageLayout original_layout = src_texture->GetLayout();
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_texture_encoder->EncodeTextureToRam(m_state_tracker, src_texture->GetView(), dst, format, m_texture_encoder->EncodeTextureToRam(src_texture->GetView(), dst, format, native_width,
native_width, bytes_per_row, num_blocks_y, memory_stride, bytes_per_row, num_blocks_y, memory_stride, src_format,
src_format, is_intensity, scale_by_half, src_rect); is_intensity, scale_by_half, src_rect);
// Transition back to original state // Transition back to original state
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), original_layout); src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), original_layout);
@ -207,7 +209,7 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry
texture->GetLayout(), &clear_value, 1, &clear_range); texture->GetLayout(), &clear_value, 1, &clear_range);
} }
return new TCacheEntry(config, this, std::move(texture), framebuffer); return new TCacheEntry(config, std::move(texture), framebuffer);
} }
bool TextureCache::CreateRenderPasses() bool TextureCache::CreateRenderPasses()
@ -319,20 +321,17 @@ VkRenderPass TextureCache::GetRenderPassForTextureUpdate(const Texture2D* textur
return m_update_render_pass; return m_update_render_pass;
} }
TextureCache::TCacheEntry::TCacheEntry(const TCacheEntryConfig& config_, TextureCache* parent, TextureCache::TCacheEntry::TCacheEntry(const TCacheEntryConfig& config_,
std::unique_ptr<Texture2D> texture, std::unique_ptr<Texture2D> texture,
VkFramebuffer framebuffer) VkFramebuffer framebuffer)
: TCacheEntryBase(config_), m_parent(parent), m_texture(std::move(texture)), : TCacheEntryBase(config_), m_texture(std::move(texture)), m_framebuffer(framebuffer)
m_framebuffer(framebuffer)
{ {
} }
TextureCache::TCacheEntry::~TCacheEntry() TextureCache::TCacheEntry::~TCacheEntry()
{ {
// Texture is automatically cleaned up, however, we don't want to leave it bound to the state // Texture is automatically cleaned up, however, we don't want to leave it bound.
// tracker. StateTracker::GetInstance()->UnbindTexture(m_texture->GetView());
m_parent->m_state_tracker->UnbindTexture(m_texture->GetView());
if (m_framebuffer != VK_NULL_HANDLE) if (m_framebuffer != VK_NULL_HANDLE)
g_command_buffer_mgr->DeferFramebufferDestruction(m_framebuffer); g_command_buffer_mgr->DeferFramebufferDestruction(m_framebuffer);
} }
@ -376,14 +375,14 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
(upload_size + upload_alignment) <= MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE) (upload_size + upload_alignment) <= MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE)
{ {
// Assume tightly packed rows, with no padding as the buffer source. // Assume tightly packed rows, with no padding as the buffer source.
StreamBuffer* upload_buffer = m_parent->m_texture_upload_buffer.get(); StreamBuffer* upload_buffer = TextureCache::GetInstance()->m_texture_upload_buffer.get();
// Allocate memory from the streaming buffer for the texture data. // Allocate memory from the streaming buffer for the texture data.
if (!upload_buffer->ReserveMemory(upload_size, g_vulkan_context->GetBufferImageGranularity())) if (!upload_buffer->ReserveMemory(upload_size, g_vulkan_context->GetBufferImageGranularity()))
{ {
// Execute the command buffer first. // Execute the command buffer first.
WARN_LOG(VIDEO, "Executing command list while waiting for space in texture upload buffer"); WARN_LOG(VIDEO, "Executing command list while waiting for space in texture upload buffer");
Util::ExecuteCurrentCommandsAndRestoreState(m_parent->m_state_tracker, false); Util::ExecuteCurrentCommandsAndRestoreState(false);
// Try allocating again. This may cause a fence wait. // Try allocating again. This may cause a fence wait.
if (!upload_buffer->ReserveMemory(upload_size, g_vulkan_context->GetBufferImageGranularity())) if (!upload_buffer->ReserveMemory(upload_size, g_vulkan_context->GetBufferImageGranularity()))
@ -470,23 +469,25 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat
bool is_depth_copy = (src_format == PEControl::Z24); bool is_depth_copy = (src_format == PEControl::Z24);
// Flush EFB pokes first, as they're expected to be included. // Flush EFB pokes first, as they're expected to be included.
framebuffer_mgr->FlushEFBPokes(m_parent->m_state_tracker); framebuffer_mgr->FlushEFBPokes();
// Has to be flagged as a render target. // Has to be flagged as a render target.
_assert_(m_framebuffer != VK_NULL_HANDLE); _assert_(m_framebuffer != VK_NULL_HANDLE);
// Can't be done in a render pass, since we're doing our own render pass! // Can't be done in a render pass, since we're doing our own render pass!
StateTracker* state_tracker = m_parent->m_state_tracker;
VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
// Transition EFB to shader resource before binding // Transition EFB to shader resource before binding
VkRect2D region = {{scaled_src_rect.left, scaled_src_rect.top}, VkRect2D region = {{scaled_src_rect.left, scaled_src_rect.top},
{static_cast<u32>(scaled_src_rect.GetWidth()), {static_cast<u32>(scaled_src_rect.GetWidth()),
static_cast<u32>(scaled_src_rect.GetHeight())}}; static_cast<u32>(scaled_src_rect.GetHeight())}};
Texture2D* src_texture = is_depth_copy ? Texture2D* src_texture;
framebuffer_mgr->ResolveEFBDepthTexture(state_tracker, region) : if (is_depth_copy)
framebuffer_mgr->ResolveEFBColorTexture(state_tracker, region); src_texture = FramebufferManager::GetInstance()->ResolveEFBDepthTexture(region);
else
src_texture = FramebufferManager::GetInstance()->ResolveEFBColorTexture(region);
VkSampler src_sampler = VkSampler src_sampler =
scale_by_half ? g_object_cache->GetLinearSampler() : g_object_cache->GetPointSampler(); scale_by_half ? g_object_cache->GetLinearSampler() : g_object_cache->GetPointSampler();
VkImageLayout original_layout = src_texture->GetLayout(); VkImageLayout original_layout = src_texture->GetLayout();
@ -494,9 +495,10 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat
UtilityShaderDraw draw( UtilityShaderDraw draw(
command_buffer, g_object_cache->GetPushConstantPipelineLayout(), command_buffer, g_object_cache->GetPushConstantPipelineLayout(),
m_parent->GetRenderPassForTextureUpdate(m_texture.get()), TextureCache::GetInstance()->GetRenderPassForTextureUpdate(m_texture.get()),
g_object_cache->GetPassthroughVertexShader(), g_object_cache->GetPassthroughGeometryShader(), g_object_cache->GetPassthroughVertexShader(), g_object_cache->GetPassthroughGeometryShader(),
is_depth_copy ? m_parent->m_efb_depth_to_tex_shader : m_parent->m_efb_color_to_tex_shader); is_depth_copy ? TextureCache::GetInstance()->m_efb_depth_to_tex_shader :
TextureCache::GetInstance()->m_efb_color_to_tex_shader);
draw.SetPushConstants(colmat, (is_depth_copy ? sizeof(float) * 20 : sizeof(float) * 28)); draw.SetPushConstants(colmat, (is_depth_copy ? sizeof(float) * 20 : sizeof(float) * 28));
draw.SetPSSampler(0, src_texture->GetView(), src_sampler); draw.SetPSSampler(0, src_texture->GetView(), src_sampler);
@ -512,7 +514,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat
draw.EndRenderPass(); draw.EndRenderPass();
// We touched everything, so put it back. // We touched everything, so put it back.
state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
// Transition the EFB back to its original layout. // Transition the EFB back to its original layout.
src_texture->TransitionToLayout(command_buffer, original_layout); src_texture->TransitionToLayout(command_buffer, original_layout);
@ -553,7 +555,7 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
}; };
// Must be called outside of a render pass. // Must be called outside of a render pass.
m_parent->m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
source_vk->m_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); source_vk->m_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); m_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
@ -569,8 +571,8 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
} }
// Can't do this within a game render pass. // Can't do this within a game render pass.
m_parent->m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
m_parent->m_state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
// Can't render to a non-rendertarget (no framebuffer). // Can't render to a non-rendertarget (no framebuffer).
_assert_msg_(VIDEO, config.rendertarget, _assert_msg_(VIDEO, config.rendertarget,
@ -578,8 +580,9 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
UtilityShaderDraw draw( UtilityShaderDraw draw(
g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetStandardPipelineLayout(), g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetStandardPipelineLayout(),
m_parent->GetRenderPassForTextureUpdate(m_texture.get()), TextureCache::GetInstance()->GetRenderPassForTextureUpdate(m_texture.get()),
g_object_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE, m_parent->m_copy_shader); g_object_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE,
TextureCache::GetInstance()->m_copy_shader);
VkRect2D region = { VkRect2D region = {
{dst_rect.left, dst_rect.top}, {dst_rect.left, dst_rect.top},
@ -597,7 +600,7 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
void TextureCache::TCacheEntry::Bind(unsigned int stage) void TextureCache::TCacheEntry::Bind(unsigned int stage)
{ {
m_parent->m_state_tracker->SetTexture(stage, m_texture->GetView()); StateTracker::GetInstance()->SetTexture(stage, m_texture->GetView());
} }
bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level) bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level)
@ -617,7 +620,7 @@ bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int l
// since we'll be executing the command buffer. // since we'll be executing the command buffer.
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_parent->m_state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
// Copy to download buffer. // Copy to download buffer.
staging_texture->CopyFromImage(g_command_buffer_mgr->GetCurrentCommandBuffer(), staging_texture->CopyFromImage(g_command_buffer_mgr->GetCurrentCommandBuffer(),
@ -630,8 +633,8 @@ bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int l
// Block until the GPU has finished copying to the staging texture. // Block until the GPU has finished copying to the staging texture.
g_command_buffer_mgr->ExecuteCommandBuffer(false, true); g_command_buffer_mgr->ExecuteCommandBuffer(false, true);
m_parent->m_state_tracker->InvalidateDescriptorSets(); StateTracker::GetInstance()->InvalidateDescriptorSets();
m_parent->m_state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
// Map the staging texture so we can copy the contents out. // Map the staging texture so we can copy the contents out.
if (staging_texture->Map()) if (staging_texture->Map())

View File

@ -23,7 +23,9 @@ public:
TextureCache(); TextureCache();
~TextureCache(); ~TextureCache();
bool Initialize(StateTracker* state_tracker); static TextureCache* GetInstance();
bool Initialize();
bool CompileShaders() override; bool CompileShaders() override;
void DeleteShaders() override; void DeleteShaders() override;
@ -37,8 +39,8 @@ public:
private: private:
struct TCacheEntry : TCacheEntryBase struct TCacheEntry : TCacheEntryBase
{ {
TCacheEntry(const TCacheEntryConfig& config_, TextureCache* parent, TCacheEntry(const TCacheEntryConfig& config_, std::unique_ptr<Texture2D> texture,
std::unique_ptr<Texture2D> texture, VkFramebuffer framebuffer); VkFramebuffer framebuffer);
~TCacheEntry(); ~TCacheEntry();
Texture2D* GetTexture() const { return m_texture.get(); } Texture2D* GetTexture() const { return m_texture.get(); }
@ -55,7 +57,6 @@ private:
bool Save(const std::string& filename, unsigned int level) override; bool Save(const std::string& filename, unsigned int level) override;
private: private:
TextureCache* m_parent;
std::unique_ptr<Texture2D> m_texture; std::unique_ptr<Texture2D> m_texture;
// If we're an EFB copy, framebuffer for drawing into. // If we're an EFB copy, framebuffer for drawing into.
@ -68,8 +69,6 @@ private:
VkRenderPass GetRenderPassForTextureUpdate(const Texture2D* texture) const; VkRenderPass GetRenderPassForTextureUpdate(const Texture2D* texture) const;
StateTracker* m_state_tracker = nullptr;
VkRenderPass m_initialize_render_pass = VK_NULL_HANDLE; VkRenderPass m_initialize_render_pass = VK_NULL_HANDLE;
VkRenderPass m_update_render_pass = VK_NULL_HANDLE; VkRenderPass m_update_render_pass = VK_NULL_HANDLE;

View File

@ -73,11 +73,11 @@ bool TextureEncoder::Initialize()
return true; return true;
} }
void TextureEncoder::EncodeTextureToRam(StateTracker* state_tracker, VkImageView src_texture, void TextureEncoder::EncodeTextureToRam(VkImageView src_texture, u8* dest_ptr, u32 format,
u8* dest_ptr, u32 format, u32 native_width, u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, u32 memory_stride, PEControl::PixelFormat src_format,
PEControl::PixelFormat src_format, bool is_intensity, bool is_intensity, int scale_by_half,
int scale_by_half, const EFBRectangle& src_rect) const EFBRectangle& src_rect)
{ {
if (m_texture_encoding_shaders[format] == VK_NULL_HANDLE) if (m_texture_encoding_shaders[format] == VK_NULL_HANDLE)
{ {
@ -86,7 +86,7 @@ void TextureEncoder::EncodeTextureToRam(StateTracker* state_tracker, VkImageView
} }
// Can't do our own draw within a render pass. // Can't do our own draw within a render pass.
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetPushConstantPipelineLayout(), m_encoding_render_pass, g_object_cache->GetPushConstantPipelineLayout(), m_encoding_render_pass,
@ -122,8 +122,8 @@ void TextureEncoder::EncodeTextureToRam(StateTracker* state_tracker, VkImageView
// Block until the GPU has finished copying to the staging texture. // Block until the GPU has finished copying to the staging texture.
g_command_buffer_mgr->ExecuteCommandBuffer(false, true); g_command_buffer_mgr->ExecuteCommandBuffer(false, true);
state_tracker->InvalidateDescriptorSets(); StateTracker::GetInstance()->InvalidateDescriptorSets();
state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
// Copy from staging texture to the final destination, adjusting pitch if necessary. // Copy from staging texture to the final destination, adjusting pitch if necessary.
m_download_texture->ReadTexels(0, 0, render_width, render_height, dest_ptr, memory_stride); m_download_texture->ReadTexels(0, 0, render_width, render_height, dest_ptr, memory_stride);

View File

@ -15,7 +15,6 @@
namespace Vulkan namespace Vulkan
{ {
class StagingTexture2D; class StagingTexture2D;
class StateTracker;
class Texture2D; class Texture2D;
class TextureEncoder class TextureEncoder
@ -29,10 +28,10 @@ public:
// Uses an encoding shader to copy src_texture to dest_ptr. // Uses an encoding shader to copy src_texture to dest_ptr.
// Assumes that no render pass is currently in progress. // Assumes that no render pass is currently in progress.
// WARNING: Executes the current command buffer. // WARNING: Executes the current command buffer.
void EncodeTextureToRam(StateTracker* state_tracker, VkImageView src_texture, u8* dest_ptr, void EncodeTextureToRam(VkImageView src_texture, u8* dest_ptr, u32 format, u32 native_width,
u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
u32 memory_stride, PEControl::PixelFormat src_format, bool is_intensity, PEControl::PixelFormat src_format, bool is_intensity, int scale_by_half,
int scale_by_half, const EFBRectangle& source); const EFBRectangle& source);
private: private:
// From OGL. // From OGL.

View File

@ -195,13 +195,12 @@ void BufferMemoryBarrier(VkCommandBuffer command_buffer, VkBuffer buffer,
&buffer_info, 0, nullptr); &buffer_info, 0, nullptr);
} }
void ExecuteCurrentCommandsAndRestoreState(StateTracker* state_tracker, bool execute_off_thread, void ExecuteCurrentCommandsAndRestoreState(bool execute_off_thread, bool wait_for_completion)
bool wait_for_completion)
{ {
state_tracker->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
g_command_buffer_mgr->ExecuteCommandBuffer(execute_off_thread, wait_for_completion); g_command_buffer_mgr->ExecuteCommandBuffer(execute_off_thread, wait_for_completion);
state_tracker->InvalidateDescriptorSets(); StateTracker::GetInstance()->InvalidateDescriptorSets();
state_tracker->SetPendingRebind(); StateTracker::GetInstance()->SetPendingRebind();
} }
VkShaderModule CreateShaderModule(const u32* spv, size_t spv_word_count) VkShaderModule CreateShaderModule(const u32* spv, size_t spv_word_count)

View File

@ -47,7 +47,7 @@ void BufferMemoryBarrier(VkCommandBuffer command_buffer, VkBuffer buffer,
// Completes the current render pass, executes the command buffer, and restores state ready for next // Completes the current render pass, executes the command buffer, and restores state ready for next
// render. Use when you want to kick the current buffer to make room for new data. // render. Use when you want to kick the current buffer to make room for new data.
void ExecuteCurrentCommandsAndRestoreState(StateTracker* state_tracker, bool execute_off_thread, void ExecuteCurrentCommandsAndRestoreState(bool execute_off_thread,
bool wait_for_completion = false); bool wait_for_completion = false);
// Create a shader module from the specified SPIR-V. // Create a shader module from the specified SPIR-V.

View File

@ -36,10 +36,13 @@ VertexManager::~VertexManager()
{ {
} }
bool VertexManager::Initialize(StateTracker* state_tracker) VertexManager* VertexManager::GetInstance()
{ {
m_state_tracker = state_tracker; return static_cast<VertexManager*>(g_vertex_manager.get());
}
bool VertexManager::Initialize()
{
m_vertex_stream_buffer = StreamBuffer::Create(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, m_vertex_stream_buffer = StreamBuffer::Create(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
INITIAL_VERTEX_BUFFER_SIZE, MAX_VERTEX_BUFFER_SIZE); INITIAL_VERTEX_BUFFER_SIZE, MAX_VERTEX_BUFFER_SIZE);
@ -72,8 +75,9 @@ void VertexManager::PrepareDrawBuffers(u32 stride)
ADDSTAT(stats.thisFrame.bytesVertexStreamed, static_cast<int>(vertex_data_size)); ADDSTAT(stats.thisFrame.bytesVertexStreamed, static_cast<int>(vertex_data_size));
ADDSTAT(stats.thisFrame.bytesIndexStreamed, static_cast<int>(index_data_size)); ADDSTAT(stats.thisFrame.bytesIndexStreamed, static_cast<int>(index_data_size));
m_state_tracker->SetVertexBuffer(m_vertex_stream_buffer->GetBuffer(), 0); StateTracker::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer->GetBuffer(), 0);
m_state_tracker->SetIndexBuffer(m_index_stream_buffer->GetBuffer(), 0, VK_INDEX_TYPE_UINT16); StateTracker::GetInstance()->SetIndexBuffer(m_index_stream_buffer->GetBuffer(), 0,
VK_INDEX_TYPE_UINT16);
} }
void VertexManager::ResetBuffer(u32 stride) void VertexManager::ResetBuffer(u32 stride)
@ -94,7 +98,7 @@ void VertexManager::ResetBuffer(u32 stride)
{ {
// Flush any pending commands first, so that we can wait on the fences // Flush any pending commands first, so that we can wait on the fences
WARN_LOG(VIDEO, "Executing command list while waiting for space in vertex/index buffer"); WARN_LOG(VIDEO, "Executing command list while waiting for space in vertex/index buffer");
Util::ExecuteCurrentCommandsAndRestoreState(m_state_tracker, false); Util::ExecuteCurrentCommandsAndRestoreState(false);
// Attempt to allocate again, this may cause a fence wait // Attempt to allocate again, this may cause a fence wait
if (!has_vbuffer_allocation) if (!has_vbuffer_allocation)
@ -133,21 +137,21 @@ void VertexManager::vFlush(bool use_dst_alpha)
u32 index_count = IndexGenerator::GetIndexLen(); u32 index_count = IndexGenerator::GetIndexLen();
// Update assembly state // Update assembly state
m_state_tracker->SetVertexFormat(vertex_format); StateTracker::GetInstance()->SetVertexFormat(vertex_format);
switch (m_current_primitive_type) switch (m_current_primitive_type)
{ {
case PRIMITIVE_POINTS: case PRIMITIVE_POINTS:
m_state_tracker->SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_POINT_LIST); StateTracker::GetInstance()->SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
m_state_tracker->DisableBackFaceCulling(); StateTracker::GetInstance()->DisableBackFaceCulling();
break; break;
case PRIMITIVE_LINES: case PRIMITIVE_LINES:
m_state_tracker->SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_LINE_LIST); StateTracker::GetInstance()->SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
m_state_tracker->DisableBackFaceCulling(); StateTracker::GetInstance()->DisableBackFaceCulling();
break; break;
case PRIMITIVE_TRIANGLES: case PRIMITIVE_TRIANGLES:
m_state_tracker->SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); StateTracker::GetInstance()->SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
g_renderer->SetGenerationMode(); g_renderer->SetGenerationMode();
break; break;
} }
@ -158,37 +162,34 @@ void VertexManager::vFlush(bool use_dst_alpha)
dstalpha_mode = DSTALPHA_DUAL_SOURCE_BLEND; dstalpha_mode = DSTALPHA_DUAL_SOURCE_BLEND;
// Check for any shader stage changes // Check for any shader stage changes
m_state_tracker->CheckForShaderChanges(m_current_primitive_type, dstalpha_mode); StateTracker::GetInstance()->CheckForShaderChanges(m_current_primitive_type, dstalpha_mode);
// Update any changed constants // Update any changed constants
m_state_tracker->UpdateVertexShaderConstants(); StateTracker::GetInstance()->UpdateVertexShaderConstants();
m_state_tracker->UpdateGeometryShaderConstants(); StateTracker::GetInstance()->UpdateGeometryShaderConstants();
m_state_tracker->UpdatePixelShaderConstants(); StateTracker::GetInstance()->UpdatePixelShaderConstants();
// Flush all EFB pokes and invalidate the peek cache. // Flush all EFB pokes and invalidate the peek cache.
// TODO: Cleaner way without the cast. FramebufferManager::GetInstance()->InvalidatePeekCache();
FramebufferManager* framebuffer_mgr = FramebufferManager::GetInstance()->FlushEFBPokes();
static_cast<FramebufferManager*>(g_framebuffer_manager.get());
framebuffer_mgr->InvalidatePeekCache();
framebuffer_mgr->FlushEFBPokes(m_state_tracker);
// If bounding box is enabled, we need to flush any changes first, then invalidate what we have. // If bounding box is enabled, we need to flush any changes first, then invalidate what we have.
if (g_vulkan_context->SupportsBoundingBox()) if (g_vulkan_context->SupportsBoundingBox())
{ {
BoundingBox* bounding_box = static_cast<Renderer*>(g_renderer.get())->GetBoundingBox(); BoundingBox* bounding_box = Renderer::GetInstance()->GetBoundingBox();
bool bounding_box_enabled = (::BoundingBox::active && g_ActiveConfig.bBBoxEnable); bool bounding_box_enabled = (::BoundingBox::active && g_ActiveConfig.bBBoxEnable);
if (bounding_box_enabled) if (bounding_box_enabled)
{ {
bounding_box->Flush(m_state_tracker); bounding_box->Flush();
bounding_box->Invalidate(m_state_tracker); bounding_box->Invalidate();
} }
// Update which descriptor set/pipeline layout to use. // Update which descriptor set/pipeline layout to use.
m_state_tracker->SetBBoxEnable(bounding_box_enabled); StateTracker::GetInstance()->SetBBoxEnable(bounding_box_enabled);
} }
// Bind all pending state to the command buffer // Bind all pending state to the command buffer
if (!m_state_tracker->Bind()) if (!StateTracker::GetInstance()->Bind())
{ {
WARN_LOG(VIDEO, "Skipped draw of %u indices", index_count); WARN_LOG(VIDEO, "Skipped draw of %u indices", index_count);
return; return;
@ -207,8 +208,9 @@ void VertexManager::vFlush(bool use_dst_alpha)
bool logic_op_enabled = bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable; bool logic_op_enabled = bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable;
if (use_dst_alpha && (!g_vulkan_context->SupportsDualSourceBlend() || logic_op_enabled)) if (use_dst_alpha && (!g_vulkan_context->SupportsDualSourceBlend() || logic_op_enabled))
{ {
m_state_tracker->CheckForShaderChanges(m_current_primitive_type, DSTALPHA_ALPHA_PASS); StateTracker::GetInstance()->CheckForShaderChanges(m_current_primitive_type,
if (!m_state_tracker->Bind()) DSTALPHA_ALPHA_PASS);
if (!StateTracker::GetInstance()->Bind())
{ {
WARN_LOG(VIDEO, "Skipped draw of %u indices (alpha pass)", index_count); WARN_LOG(VIDEO, "Skipped draw of %u indices (alpha pass)", index_count);
return; return;
@ -218,7 +220,7 @@ void VertexManager::vFlush(bool use_dst_alpha)
m_current_draw_base_index, m_current_draw_base_vertex, 0); m_current_draw_base_index, m_current_draw_base_vertex, 0);
} }
m_state_tracker->OnDraw(); StateTracker::GetInstance()->OnDraw();
} }
} // namespace Vulkan } // namespace Vulkan

View File

@ -12,7 +12,6 @@
namespace Vulkan namespace Vulkan
{ {
class StateTracker;
class StreamBuffer; class StreamBuffer;
class VertexManager : public VertexManagerBase class VertexManager : public VertexManagerBase
@ -21,7 +20,9 @@ public:
VertexManager(); VertexManager();
~VertexManager(); ~VertexManager();
bool Initialize(StateTracker* state_tracker); static VertexManager* GetInstance();
bool Initialize();
NativeVertexFormat* CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override; NativeVertexFormat* CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
@ -32,8 +33,6 @@ protected:
private: private:
void vFlush(bool use_dst_alpha) override; void vFlush(bool use_dst_alpha) override;
StateTracker* m_state_tracker = nullptr;
std::vector<u8> m_cpu_vertex_buffer; std::vector<u8> m_cpu_vertex_buffer;
std::vector<u16> m_cpu_index_buffer; std::vector<u16> m_cpu_index_buffer;

View File

@ -194,19 +194,16 @@ bool VideoBackend::Initialize(void* window_handle)
g_framebuffer_manager = std::make_unique<FramebufferManager>(); g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_renderer = std::make_unique<Renderer>(std::move(swap_chain)); g_renderer = std::make_unique<Renderer>(std::move(swap_chain));
// Cast to our wrapper classes, so we can call the init methods.
Renderer* renderer = static_cast<Renderer*>(g_renderer.get());
FramebufferManager* framebuffer_mgr =
static_cast<FramebufferManager*>(g_framebuffer_manager.get());
// Invoke init methods on main wrapper classes. // Invoke init methods on main wrapper classes.
// These have to be done before the others because the destructors // These have to be done before the others because the destructors
// for the remaining classes may call methods on these. // for the remaining classes may call methods on these.
if (!g_object_cache->Initialize() || !framebuffer_mgr->Initialize() || if (!g_object_cache->Initialize() || !FramebufferManager::GetInstance()->Initialize() ||
!renderer->Initialize(framebuffer_mgr)) !StateTracker::CreateInstance() || !Renderer::GetInstance()->Initialize())
{ {
PanicAlert("Failed to initialize Vulkan classes."); PanicAlert("Failed to initialize Vulkan classes.");
g_renderer.reset(); g_renderer.reset();
StateTracker::DestroyInstance();
g_framebuffer_manager.reset();
g_object_cache.reset(); g_object_cache.reset();
g_command_buffer_mgr.reset(); g_command_buffer_mgr.reset();
g_vulkan_context.reset(); g_vulkan_context.reset();
@ -219,18 +216,16 @@ bool VideoBackend::Initialize(void* window_handle)
g_vertex_manager = std::make_unique<VertexManager>(); g_vertex_manager = std::make_unique<VertexManager>();
g_texture_cache = std::make_unique<TextureCache>(); g_texture_cache = std::make_unique<TextureCache>();
g_perf_query = std::make_unique<PerfQuery>(); g_perf_query = std::make_unique<PerfQuery>();
VertexManager* vertex_manager = static_cast<VertexManager*>(g_vertex_manager.get()); if (!VertexManager::GetInstance()->Initialize() || !TextureCache::GetInstance()->Initialize() ||
TextureCache* texture_cache = static_cast<TextureCache*>(g_texture_cache.get()); !PerfQuery::GetInstance()->Initialize())
PerfQuery* perf_query = static_cast<PerfQuery*>(g_perf_query.get());
if (!vertex_manager->Initialize(renderer->GetStateTracker()) ||
!texture_cache->Initialize(renderer->GetStateTracker()) ||
!perf_query->Initialize(renderer->GetStateTracker()))
{ {
PanicAlert("Failed to initialize Vulkan classes."); PanicAlert("Failed to initialize Vulkan classes.");
g_perf_query.reset(); g_perf_query.reset();
g_texture_cache.reset(); g_texture_cache.reset();
g_vertex_manager.reset(); g_vertex_manager.reset();
g_renderer.reset(); g_renderer.reset();
StateTracker::DestroyInstance();
g_framebuffer_manager.reset();
g_object_cache.reset(); g_object_cache.reset();
g_command_buffer_mgr.reset(); g_command_buffer_mgr.reset();
g_vulkan_context.reset(); g_vulkan_context.reset();
@ -273,11 +268,12 @@ void VideoBackend::Video_Cleanup()
// Save all cached pipelines out to disk for next time. // Save all cached pipelines out to disk for next time.
g_object_cache->SavePipelineCache(); g_object_cache->SavePipelineCache();
g_texture_cache.reset();
g_perf_query.reset(); g_perf_query.reset();
g_texture_cache.reset();
g_vertex_manager.reset(); g_vertex_manager.reset();
g_renderer.reset();
g_framebuffer_manager.reset(); g_framebuffer_manager.reset();
StateTracker::DestroyInstance();
g_renderer.reset();
CleanupShared(); CleanupShared();
} }