Implement AbstractGfx for Vulkan

This commit is contained in:
Scott Mansell 2023-01-28 15:12:28 +13:00
parent 58b70b2fb2
commit 2a2014af09
12 changed files with 109 additions and 161 deletions

View File

@ -610,7 +610,7 @@
<ClInclude Include="VideoBackends\Vulkan\VKBoundingBox.h" /> <ClInclude Include="VideoBackends\Vulkan\VKBoundingBox.h" />
<ClInclude Include="VideoBackends\Vulkan\VKPerfQuery.h" /> <ClInclude Include="VideoBackends\Vulkan\VKPerfQuery.h" />
<ClInclude Include="VideoBackends\Vulkan\VKPipeline.h" /> <ClInclude Include="VideoBackends\Vulkan\VKPipeline.h" />
<ClInclude Include="VideoBackends\Vulkan\VKRenderer.h" /> <ClInclude Include="VideoBackends\Vulkan\VKGfx.h" />
<ClInclude Include="VideoBackends\Vulkan\VKShader.h" /> <ClInclude Include="VideoBackends\Vulkan\VKShader.h" />
<ClInclude Include="VideoBackends\Vulkan\VKStreamBuffer.h" /> <ClInclude Include="VideoBackends\Vulkan\VKStreamBuffer.h" />
<ClInclude Include="VideoBackends\Vulkan\VKSwapChain.h" /> <ClInclude Include="VideoBackends\Vulkan\VKSwapChain.h" />
@ -1214,7 +1214,7 @@
<ClCompile Include="VideoBackends\Vulkan\VKMain.cpp" /> <ClCompile Include="VideoBackends\Vulkan\VKMain.cpp" />
<ClCompile Include="VideoBackends\Vulkan\VKPerfQuery.cpp" /> <ClCompile Include="VideoBackends\Vulkan\VKPerfQuery.cpp" />
<ClCompile Include="VideoBackends\Vulkan\VKPipeline.cpp" /> <ClCompile Include="VideoBackends\Vulkan\VKPipeline.cpp" />
<ClCompile Include="VideoBackends\Vulkan\VKRenderer.cpp" /> <ClCompile Include="VideoBackends\Vulkan\VKGfx.cpp" />
<ClCompile Include="VideoBackends\Vulkan\VKShader.cpp" /> <ClCompile Include="VideoBackends\Vulkan\VKShader.cpp" />
<ClCompile Include="VideoBackends\Vulkan\VKStreamBuffer.cpp" /> <ClCompile Include="VideoBackends\Vulkan\VKStreamBuffer.cpp" />
<ClCompile Include="VideoBackends\Vulkan\VKSwapChain.cpp" /> <ClCompile Include="VideoBackends\Vulkan\VKSwapChain.cpp" />

View File

@ -17,8 +17,8 @@ add_library(videovulkan
VKPerfQuery.h VKPerfQuery.h
VKPipeline.cpp VKPipeline.cpp
VKPipeline.h VKPipeline.h
VKRenderer.cpp VKGfx.cpp
VKRenderer.h VKGfx.h
VKShader.cpp VKShader.cpp
VKShader.h VKShader.h
VKStreamBuffer.cpp VKStreamBuffer.cpp

View File

@ -7,8 +7,8 @@
#include "VideoBackends/Vulkan/CommandBufferManager.h" #include "VideoBackends/Vulkan/CommandBufferManager.h"
#include "VideoBackends/Vulkan/ObjectCache.h" #include "VideoBackends/Vulkan/ObjectCache.h"
#include "VideoBackends/Vulkan/VKGfx.h"
#include "VideoBackends/Vulkan/VKPipeline.h" #include "VideoBackends/Vulkan/VKPipeline.h"
#include "VideoBackends/Vulkan/VKRenderer.h"
#include "VideoBackends/Vulkan/VKShader.h" #include "VideoBackends/Vulkan/VKShader.h"
#include "VideoBackends/Vulkan/VKTexture.h" #include "VideoBackends/Vulkan/VKTexture.h"
#include "VideoBackends/Vulkan/VKVertexFormat.h" #include "VideoBackends/Vulkan/VKVertexFormat.h"

View File

@ -11,7 +11,7 @@
#include "VideoBackends/Vulkan/ObjectCache.h" #include "VideoBackends/Vulkan/ObjectCache.h"
#include "VideoBackends/Vulkan/StagingBuffer.h" #include "VideoBackends/Vulkan/StagingBuffer.h"
#include "VideoBackends/Vulkan/StateTracker.h" #include "VideoBackends/Vulkan/StateTracker.h"
#include "VideoBackends/Vulkan/VKRenderer.h" #include "VideoBackends/Vulkan/VKGfx.h"
#include "VideoBackends/Vulkan/VulkanContext.h" #include "VideoBackends/Vulkan/VulkanContext.h"
namespace Vulkan namespace Vulkan
@ -65,7 +65,7 @@ std::vector<BBoxType> VKBoundingBox::Read(u32 index, u32 length)
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.
Renderer::GetInstance()->ExecuteCommandBuffer(false, true); VKGfx::GetInstance()->ExecuteCommandBuffer(false, true);
// Cache is now valid. // Cache is now valid.
m_readback_buffer->InvalidateCPUCache(); m_readback_buffer->InvalidateCPUCache();

View File

@ -8,6 +8,7 @@
#include <string> #include <string>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "VideoBackends/Vulkan/StagingBuffer.h"
#include "VideoBackends/Vulkan/VulkanLoader.h" #include "VideoBackends/Vulkan/VulkanLoader.h"
#include "VideoCommon/BoundingBox.h" #include "VideoCommon/BoundingBox.h"

View File

@ -1,7 +1,7 @@
// Copyright 2016 Dolphin Emulator Project // Copyright 2016 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "VideoBackends/Vulkan/VKRenderer.h" #include "VideoBackends/Vulkan/VKGfx.h"
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
@ -15,153 +15,99 @@
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/MsgHandler.h" #include "Common/MsgHandler.h"
#include "Core/Core.h"
#include "VideoBackends/Vulkan/CommandBufferManager.h" #include "VideoBackends/Vulkan/CommandBufferManager.h"
#include "VideoBackends/Vulkan/ObjectCache.h" #include "VideoBackends/Vulkan/ObjectCache.h"
#include "VideoBackends/Vulkan/StagingBuffer.h"
#include "VideoBackends/Vulkan/StateTracker.h" #include "VideoBackends/Vulkan/StateTracker.h"
#include "VideoBackends/Vulkan/VKBoundingBox.h"
#include "VideoBackends/Vulkan/VKPerfQuery.h"
#include "VideoBackends/Vulkan/VKPipeline.h" #include "VideoBackends/Vulkan/VKPipeline.h"
#include "VideoBackends/Vulkan/VKShader.h" #include "VideoBackends/Vulkan/VKShader.h"
#include "VideoBackends/Vulkan/VKStreamBuffer.h"
#include "VideoBackends/Vulkan/VKSwapChain.h" #include "VideoBackends/Vulkan/VKSwapChain.h"
#include "VideoBackends/Vulkan/VKTexture.h" #include "VideoBackends/Vulkan/VKTexture.h"
#include "VideoBackends/Vulkan/VKVertexFormat.h" #include "VideoBackends/Vulkan/VKVertexFormat.h"
#include "VideoBackends/Vulkan/VulkanContext.h"
#include "VideoCommon/DriverDetails.h" #include "VideoCommon/DriverDetails.h"
#include "VideoCommon/FramebufferManager.h" #include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/Present.h" #include "VideoCommon/Present.h"
#include "VideoCommon/RenderState.h" #include "VideoCommon/RenderState.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
#include "VideoCommon/XFMemory.h"
namespace Vulkan namespace Vulkan
{ {
Renderer::Renderer(std::unique_ptr<SwapChain> swap_chain, float backbuffer_scale) VKGfx::VKGfx(std::unique_ptr<SwapChain> swap_chain, float backbuffer_scale)
: ::Renderer(swap_chain ? static_cast<int>(swap_chain->GetWidth()) : 1, : m_swap_chain(std::move(swap_chain)), m_backbuffer_scale(backbuffer_scale)
swap_chain ? static_cast<int>(swap_chain->GetHeight()) : 0, backbuffer_scale,
swap_chain ? swap_chain->GetTextureFormat() : AbstractTextureFormat::Undefined),
m_swap_chain(std::move(swap_chain))
{ {
UpdateActiveConfig(); UpdateActiveConfig();
for (SamplerState& m_sampler_state : m_sampler_states) for (SamplerState& m_sampler_state : m_sampler_states)
m_sampler_state = RenderState::GetPointSamplerState(); m_sampler_state = RenderState::GetPointSamplerState();
}
Renderer::~Renderer() = default;
bool Renderer::IsHeadless() const
{
return m_swap_chain == nullptr;
}
bool Renderer::Initialize()
{
if (!::Renderer::Initialize())
return false;
// Various initialization routines will have executed commands on the command buffer. // Various initialization routines will have executed commands on the command buffer.
// Execute what we have done before beginning the first frame. // Execute what we have done before beginning the first frame.
ExecuteCommandBuffer(true, false); ExecuteCommandBuffer(true, false);
return true;
} }
void Renderer::Shutdown() VKGfx::~VKGfx() = default;
bool VKGfx::IsHeadless() const
{ {
::Renderer::Shutdown(); return m_swap_chain == nullptr;
m_swap_chain.reset();
} }
std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config, std::unique_ptr<AbstractTexture> VKGfx::CreateTexture(const TextureConfig& config,
std::string_view name) std::string_view name)
{ {
return VKTexture::Create(config, name); return VKTexture::Create(config, name);
} }
std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTextureType type, std::unique_ptr<AbstractStagingTexture> VKGfx::CreateStagingTexture(StagingTextureType type,
const TextureConfig& config) const TextureConfig& config)
{ {
return VKStagingTexture::Create(type, config); return VKStagingTexture::Create(type, config);
} }
std::unique_ptr<AbstractShader> std::unique_ptr<AbstractShader>
Renderer::CreateShaderFromSource(ShaderStage stage, std::string_view source, std::string_view name) VKGfx::CreateShaderFromSource(ShaderStage stage, std::string_view source, std::string_view name)
{ {
return VKShader::CreateFromSource(stage, source, name); return VKShader::CreateFromSource(stage, source, name);
} }
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage stage, std::unique_ptr<AbstractShader> VKGfx::CreateShaderFromBinary(ShaderStage stage, const void* data,
const void* data, size_t length, size_t length, std::string_view name)
std::string_view name)
{ {
return VKShader::CreateFromBinary(stage, data, length, name); return VKShader::CreateFromBinary(stage, data, length, name);
} }
std::unique_ptr<NativeVertexFormat> std::unique_ptr<NativeVertexFormat>
Renderer::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) VKGfx::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
{ {
return std::make_unique<VertexFormat>(vtx_decl); return std::make_unique<VertexFormat>(vtx_decl);
} }
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config, std::unique_ptr<AbstractPipeline> VKGfx::CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data, const void* cache_data,
size_t cache_data_length) size_t cache_data_length)
{ {
return VKPipeline::Create(config); return VKPipeline::Create(config);
} }
std::unique_ptr<AbstractFramebuffer> Renderer::CreateFramebuffer(AbstractTexture* color_attachment, std::unique_ptr<AbstractFramebuffer> VKGfx::CreateFramebuffer(AbstractTexture* color_attachment,
AbstractTexture* depth_attachment) AbstractTexture* depth_attachment)
{ {
return VKFramebuffer::Create(static_cast<VKTexture*>(color_attachment), return VKFramebuffer::Create(static_cast<VKTexture*>(color_attachment),
static_cast<VKTexture*>(depth_attachment)); static_cast<VKTexture*>(depth_attachment));
} }
void Renderer::SetPipeline(const AbstractPipeline* pipeline) void VKGfx::SetPipeline(const AbstractPipeline* pipeline)
{ {
StateTracker::GetInstance()->SetPipeline(static_cast<const VKPipeline*>(pipeline)); StateTracker::GetInstance()->SetPipeline(static_cast<const VKPipeline*>(pipeline));
} }
std::unique_ptr<BoundingBox> Renderer::CreateBoundingBox() const void VKGfx::ClearRegion(const MathUtil::Rectangle<int>& rc,
const MathUtil::Rectangle<int>& target_rc, bool color_enable,
bool alpha_enable, bool z_enable, u32 color, u32 z)
{ {
return std::make_unique<VKBoundingBox>();
}
void Renderer::ClearScreen(const MathUtil::Rectangle<int>& rc, bool color_enable, bool alpha_enable,
bool z_enable, u32 color, u32 z)
{
g_framebuffer_manager->FlushEFBPokes();
g_framebuffer_manager->FlagPeekCacheAsOutOfDate();
// Native -> EFB coordinates
MathUtil::Rectangle<int> target_rc = Renderer::ConvertEFBRectangle(rc);
// Size we pass this size to vkBeginRenderPass, it has to be clamped to the framebuffer
// dimensions. The other backends just silently ignore this case.
target_rc.ClampUL(0, 0, m_target_width, m_target_height);
VkRect2D target_vk_rc = { VkRect2D target_vk_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())}};
// Determine whether the EFB has an alpha channel. If it doesn't, we can clear the alpha
// channel to 0xFF. This hopefully allows us to use the fast path in most cases.
if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16 ||
bpmem.zcontrol.pixel_format == PixelFormat::RGB8_Z24 ||
bpmem.zcontrol.pixel_format == PixelFormat::Z24)
{
// Force alpha writes, and clear the alpha channel. This is different from the other backends,
// where the existing values of the alpha channel are preserved.
alpha_enable = true;
color &= 0x00FFFFFF;
}
// Convert RGBA8 -> floating-point values. // Convert RGBA8 -> floating-point values.
VkClearValue clear_color_value = {}; VkClearValue clear_color_value = {};
VkClearValue clear_depth_value = {}; VkClearValue clear_depth_value = {};
@ -248,17 +194,17 @@ void Renderer::ClearScreen(const MathUtil::Rectangle<int>& rc, bool color_enable
g_framebuffer_manager->ClearEFB(rc, color_enable, alpha_enable, z_enable, color, z); g_framebuffer_manager->ClearEFB(rc, color_enable, alpha_enable, z_enable, color, z);
} }
void Renderer::Flush() void VKGfx::Flush()
{ {
ExecuteCommandBuffer(true, false); ExecuteCommandBuffer(true, false);
} }
void Renderer::WaitForGPUIdle() void VKGfx::WaitForGPUIdle()
{ {
ExecuteCommandBuffer(false, true); ExecuteCommandBuffer(false, true);
} }
void Renderer::BindBackbuffer(const ClearColor& clear_color) void VKGfx::BindBackbuffer(const ClearColor& clear_color)
{ {
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
@ -335,7 +281,7 @@ void Renderer::BindBackbuffer(const ClearColor& clear_color)
ClearColor{{0.0f, 0.0f, 0.0f, 1.0f}}); ClearColor{{0.0f, 0.0f, 0.0f, 1.0f}});
} }
void Renderer::PresentBackbuffer() void VKGfx::PresentBackbuffer()
{ {
// End drawing to backbuffer // End drawing to backbuffer
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
@ -356,7 +302,7 @@ void Renderer::PresentBackbuffer()
StateTracker::GetInstance()->InvalidateCachedState(); StateTracker::GetInstance()->InvalidateCachedState();
} }
void Renderer::SetFullscreen(bool enable_fullscreen) void VKGfx::SetFullscreen(bool enable_fullscreen)
{ {
if (!m_swap_chain->IsFullscreenSupported()) if (!m_swap_chain->IsFullscreenSupported())
return; return;
@ -364,12 +310,12 @@ void Renderer::SetFullscreen(bool enable_fullscreen)
m_swap_chain->SetNextFullscreenState(enable_fullscreen); m_swap_chain->SetNextFullscreenState(enable_fullscreen);
} }
bool Renderer::IsFullscreen() const bool VKGfx::IsFullscreen() const
{ {
return m_swap_chain && m_swap_chain->GetCurrentFullscreenState(); return m_swap_chain && m_swap_chain->GetCurrentFullscreenState();
} }
void Renderer::ExecuteCommandBuffer(bool submit_off_thread, bool wait_for_completion) void VKGfx::ExecuteCommandBuffer(bool submit_off_thread, bool wait_for_completion)
{ {
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
@ -378,7 +324,7 @@ void Renderer::ExecuteCommandBuffer(bool submit_off_thread, bool wait_for_comple
StateTracker::GetInstance()->InvalidateCachedState(); StateTracker::GetInstance()->InvalidateCachedState();
} }
void Renderer::CheckForSurfaceChange() void VKGfx::CheckForSurfaceChange()
{ {
if (!g_presenter->SurfaceChangedTestAndClear() || !m_swap_chain) if (!g_presenter->SurfaceChangedTestAndClear() || !m_swap_chain)
return; return;
@ -397,7 +343,7 @@ void Renderer::CheckForSurfaceChange()
OnSwapChainResized(); OnSwapChainResized();
} }
void Renderer::CheckForSurfaceResize() void VKGfx::CheckForSurfaceResize()
{ {
if (!g_presenter->SurfaceResizedTestAndClear()) if (!g_presenter->SurfaceResizedTestAndClear())
return; return;
@ -421,7 +367,7 @@ void Renderer::CheckForSurfaceResize()
OnSwapChainResized(); OnSwapChainResized();
} }
void Renderer::OnConfigChanged(u32 bits) void VKGfx::OnConfigChanged(u32 bits)
{ {
if (bits & CONFIG_CHANGE_BIT_HOST_CONFIG) if (bits & CONFIG_CHANGE_BIT_HOST_CONFIG)
g_object_cache->ReloadPipelineCache(); g_object_cache->ReloadPipelineCache();
@ -448,12 +394,12 @@ void Renderer::OnConfigChanged(u32 bits)
} }
} }
void Renderer::OnSwapChainResized() void VKGfx::OnSwapChainResized()
{ {
g_presenter->SetBackbuffer(m_swap_chain->GetWidth(), m_swap_chain->GetHeight()); g_presenter->SetBackbuffer(m_swap_chain->GetWidth(), m_swap_chain->GetHeight());
} }
void Renderer::BindFramebuffer(VKFramebuffer* fb) void VKGfx::BindFramebuffer(VKFramebuffer* fb)
{ {
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
@ -474,7 +420,7 @@ void Renderer::BindFramebuffer(VKFramebuffer* fb)
m_current_framebuffer = fb; m_current_framebuffer = fb;
} }
void Renderer::SetFramebuffer(AbstractFramebuffer* framebuffer) void VKGfx::SetFramebuffer(AbstractFramebuffer* framebuffer)
{ {
if (m_current_framebuffer == framebuffer) if (m_current_framebuffer == framebuffer)
return; return;
@ -483,7 +429,7 @@ void Renderer::SetFramebuffer(AbstractFramebuffer* framebuffer)
BindFramebuffer(vkfb); BindFramebuffer(vkfb);
} }
void Renderer::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer) void VKGfx::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
{ {
if (m_current_framebuffer == framebuffer) if (m_current_framebuffer == framebuffer)
return; return;
@ -496,8 +442,8 @@ void Renderer::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
StateTracker::GetInstance()->BeginDiscardRenderPass(); StateTracker::GetInstance()->BeginDiscardRenderPass();
} }
void Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, void VKGfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const ClearColor& color_value,
const ClearColor& color_value, float depth_value) float depth_value)
{ {
VKFramebuffer* vkfb = static_cast<VKFramebuffer*>(framebuffer); VKFramebuffer* vkfb = static_cast<VKFramebuffer*>(framebuffer);
BindFramebuffer(vkfb); BindFramebuffer(vkfb);
@ -520,7 +466,7 @@ void Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer,
num_clear_values); num_clear_values);
} }
void Renderer::SetTexture(u32 index, const AbstractTexture* texture) void VKGfx::SetTexture(u32 index, const AbstractTexture* texture)
{ {
// Texture should always be in SHADER_READ_ONLY layout prior to use. // Texture should always be in SHADER_READ_ONLY layout prior to use.
// This is so we don't need to transition during render passes. // This is so we don't need to transition during render passes.
@ -531,7 +477,7 @@ void Renderer::SetTexture(u32 index, const AbstractTexture* texture)
{ {
if (StateTracker::GetInstance()->InRenderPass()) if (StateTracker::GetInstance()->InRenderPass())
{ {
WARN_LOG_FMT(VIDEO, "Transitioning image in render pass in Renderer::SetTexture()"); WARN_LOG_FMT(VIDEO, "Transitioning image in render pass in VKGfx::SetTexture()");
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
} }
@ -547,7 +493,7 @@ void Renderer::SetTexture(u32 index, const AbstractTexture* texture)
} }
} }
void Renderer::SetSamplerState(u32 index, const SamplerState& state) void VKGfx::SetSamplerState(u32 index, const SamplerState& state)
{ {
// Skip lookup if the state hasn't changed. // Skip lookup if the state hasn't changed.
if (m_sampler_states[index] == state) if (m_sampler_states[index] == state)
@ -565,7 +511,7 @@ void Renderer::SetSamplerState(u32 index, const SamplerState& state)
m_sampler_states[index] = state; m_sampler_states[index] = state;
} }
void Renderer::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) void VKGfx::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write)
{ {
VKTexture* vk_texture = static_cast<VKTexture*>(texture); VKTexture* vk_texture = static_cast<VKTexture*>(texture);
if (vk_texture) if (vk_texture)
@ -583,12 +529,12 @@ void Renderer::SetComputeImageTexture(AbstractTexture* texture, bool read, bool
} }
} }
void Renderer::UnbindTexture(const AbstractTexture* texture) void VKGfx::UnbindTexture(const AbstractTexture* texture)
{ {
StateTracker::GetInstance()->UnbindTexture(static_cast<const VKTexture*>(texture)->GetView()); StateTracker::GetInstance()->UnbindTexture(static_cast<const VKTexture*>(texture)->GetView());
} }
void Renderer::ResetSamplerStates() void VKGfx::ResetSamplerStates()
{ {
// Invalidate all sampler states, next draw will re-initialize them. // Invalidate all sampler states, next draw will re-initialize them.
for (u32 i = 0; i < m_sampler_states.size(); i++) for (u32 i = 0; i < m_sampler_states.size(); i++)
@ -601,7 +547,7 @@ void Renderer::ResetSamplerStates()
g_object_cache->ClearSamplerCache(); g_object_cache->ClearSamplerCache();
} }
void Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc) void VKGfx::SetScissorRect(const MathUtil::Rectangle<int>& rc)
{ {
VkRect2D scissor = {{rc.left, rc.top}, VkRect2D scissor = {{rc.left, rc.top},
{static_cast<u32>(rc.GetWidth()), static_cast<u32>(rc.GetHeight())}}; {static_cast<u32>(rc.GetWidth()), static_cast<u32>(rc.GetHeight())}};
@ -621,14 +567,14 @@ void Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc)
StateTracker::GetInstance()->SetScissor(scissor); StateTracker::GetInstance()->SetScissor(scissor);
} }
void Renderer::SetViewport(float x, float y, float width, float height, float near_depth, void VKGfx::SetViewport(float x, float y, float width, float height, float near_depth,
float far_depth) float far_depth)
{ {
VkViewport viewport = {x, y, width, height, near_depth, far_depth}; VkViewport viewport = {x, y, width, height, near_depth, far_depth};
StateTracker::GetInstance()->SetViewport(viewport); StateTracker::GetInstance()->SetViewport(viewport);
} }
void Renderer::Draw(u32 base_vertex, u32 num_vertices) void VKGfx::Draw(u32 base_vertex, u32 num_vertices)
{ {
if (!StateTracker::GetInstance()->Bind()) if (!StateTracker::GetInstance()->Bind())
return; return;
@ -636,7 +582,7 @@ void Renderer::Draw(u32 base_vertex, u32 num_vertices)
vkCmdDraw(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_vertices, 1, base_vertex, 0); vkCmdDraw(g_command_buffer_mgr->GetCurrentCommandBuffer(), num_vertices, 1, base_vertex, 0);
} }
void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) void VKGfx::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
{ {
if (!StateTracker::GetInstance()->Bind()) if (!StateTracker::GetInstance()->Bind())
return; return;
@ -645,12 +591,19 @@ void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
base_vertex, 0); base_vertex, 0);
} }
void Renderer::DispatchComputeShader(const AbstractShader* shader, u32 groupsize_x, u32 groupsize_y, void VKGfx::DispatchComputeShader(const AbstractShader* shader, u32 groupsize_x, u32 groupsize_y,
u32 groupsize_z, u32 groups_x, u32 groups_y, u32 groups_z) u32 groupsize_z, u32 groups_x, u32 groups_y, u32 groups_z)
{ {
StateTracker::GetInstance()->SetComputeShader(static_cast<const VKShader*>(shader)); StateTracker::GetInstance()->SetComputeShader(static_cast<const VKShader*>(shader));
if (StateTracker::GetInstance()->BindCompute()) if (StateTracker::GetInstance()->BindCompute())
vkCmdDispatch(g_command_buffer_mgr->GetCurrentCommandBuffer(), groups_x, groups_y, groups_z); vkCmdDispatch(g_command_buffer_mgr->GetCurrentCommandBuffer(), groups_x, groups_y, groups_z);
} }
SurfaceInfo VKGfx::GetSurfaceInfo() const
{
return {m_swap_chain ? m_swap_chain->GetWidth() : 1u,
m_swap_chain ? m_swap_chain->GetHeight() : 0u, m_backbuffer_scale,
m_swap_chain ? m_swap_chain->GetTextureFormat() : AbstractTextureFormat::Undefined};
}
} // namespace Vulkan } // namespace Vulkan

View File

@ -4,16 +4,12 @@
#pragma once #pragma once
#include <array> #include <array>
#include <cstddef>
#include <memory> #include <memory>
#include <string_view> #include <string_view>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "VideoBackends/Vulkan/Constants.h" #include "VideoBackends/Vulkan/Constants.h"
#include "VideoCommon/RenderBase.h" #include "VideoCommon/AbstractGfx.h"
class BoundingBox;
struct XFBSourceBase;
namespace Vulkan namespace Vulkan
{ {
@ -23,19 +19,16 @@ class VKFramebuffer;
class VKPipeline; class VKPipeline;
class VKTexture; class VKTexture;
class Renderer : public ::Renderer class VKGfx : public ::AbstractGfx
{ {
public: public:
Renderer(std::unique_ptr<SwapChain> swap_chain, float backbuffer_scale); VKGfx(std::unique_ptr<SwapChain> swap_chain, float backbuffer_scale);
~Renderer() override; ~VKGfx() override;
static Renderer* GetInstance() { return static_cast<Renderer*>(g_renderer.get()); } static VKGfx* GetInstance() { return static_cast<VKGfx*>(g_gfx.get()); }
bool IsHeadless() const override; bool IsHeadless() const override;
bool Initialize() override;
void Shutdown() override;
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config, std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config,
std::string_view name) override; std::string_view name) override;
std::unique_ptr<AbstractStagingTexture> std::unique_ptr<AbstractStagingTexture>
@ -60,8 +53,8 @@ public:
void WaitForGPUIdle() override; void WaitForGPUIdle() override;
void OnConfigChanged(u32 bits) override; void OnConfigChanged(u32 bits) override;
void ClearScreen(const MathUtil::Rectangle<int>& rc, bool color_enable, bool alpha_enable, void ClearRegion(const MathUtil::Rectangle<int>& rc, const MathUtil::Rectangle<int>& target_rc,
bool z_enable, u32 color, u32 z) override; bool color_enable, bool alpha_enable, bool z_enable, u32 color, u32 z) override;
void SetPipeline(const AbstractPipeline* pipeline) override; void SetPipeline(const AbstractPipeline* pipeline) override;
void SetFramebuffer(AbstractFramebuffer* framebuffer) override; void SetFramebuffer(AbstractFramebuffer* framebuffer) override;
@ -84,13 +77,13 @@ public:
void SetFullscreen(bool enable_fullscreen) override; void SetFullscreen(bool enable_fullscreen) override;
bool IsFullscreen() const override; bool IsFullscreen() const override;
// Returns info about the main surface (aka backbuffer)
virtual SurfaceInfo GetSurfaceInfo() const override;
// Completes the current render pass, executes the command buffer, and restores state ready for // 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. // next render. Use when you want to kick the current buffer to make room for new data.
void ExecuteCommandBuffer(bool execute_off_thread, bool wait_for_completion = false); void ExecuteCommandBuffer(bool execute_off_thread, bool wait_for_completion = false);
protected:
std::unique_ptr<BoundingBox> CreateBoundingBox() const override;
private: private:
void CheckForSurfaceChange(); void CheckForSurfaceChange();
void CheckForSurfaceResize(); void CheckForSurfaceResize();
@ -101,6 +94,7 @@ private:
void BindFramebuffer(VKFramebuffer* fb); void BindFramebuffer(VKFramebuffer* fb);
std::unique_ptr<SwapChain> m_swap_chain; std::unique_ptr<SwapChain> m_swap_chain;
float m_backbuffer_scale;
// Keep a copy of sampler states to avoid cache lookups every draw // Keep a copy of sampler states to avoid cache lookups every draw
std::array<SamplerState, NUM_PIXEL_SHADER_SAMPLERS> m_sampler_states = {}; std::array<SamplerState, NUM_PIXEL_SHADER_SAMPLERS> m_sampler_states = {};

View File

@ -12,8 +12,9 @@
#include "VideoBackends/Vulkan/Constants.h" #include "VideoBackends/Vulkan/Constants.h"
#include "VideoBackends/Vulkan/ObjectCache.h" #include "VideoBackends/Vulkan/ObjectCache.h"
#include "VideoBackends/Vulkan/StateTracker.h" #include "VideoBackends/Vulkan/StateTracker.h"
#include "VideoBackends/Vulkan/VKBoundingBox.h"
#include "VideoBackends/Vulkan/VKGfx.h"
#include "VideoBackends/Vulkan/VKPerfQuery.h" #include "VideoBackends/Vulkan/VKPerfQuery.h"
#include "VideoBackends/Vulkan/VKRenderer.h"
#include "VideoBackends/Vulkan/VKSwapChain.h" #include "VideoBackends/Vulkan/VKSwapChain.h"
#include "VideoBackends/Vulkan/VKVertexManager.h" #include "VideoBackends/Vulkan/VKVertexManager.h"
#include "VideoBackends/Vulkan/VulkanContext.h" #include "VideoBackends/Vulkan/VulkanContext.h"
@ -193,8 +194,7 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
g_Config.backend_info.bSupportsExclusiveFullscreen = g_Config.backend_info.bSupportsExclusiveFullscreen =
enable_surface && g_vulkan_context->SupportsExclusiveFullscreen(wsi, surface); enable_surface && g_vulkan_context->SupportsExclusiveFullscreen(wsi, surface);
// With the backend information populated, we can now initialize videocommon. UpdateActiveConfig();
InitializeShared();
// Create command buffers. We do this separately because the other classes depend on it. // Create command buffers. We do this separately because the other classes depend on it.
g_command_buffer_mgr = std::make_unique<CommandBufferManager>(g_Config.bBackendMultithreading); g_command_buffer_mgr = std::make_unique<CommandBufferManager>(g_Config.bBackendMultithreading);
@ -234,24 +234,23 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
return false; return false;
} }
// Create main wrapper instances. auto gfx = std::make_unique<VKGfx>(std::move(swap_chain), wsi.render_surface_scale);
g_renderer = std::make_unique<Renderer>(std::move(swap_chain), wsi.render_surface_scale); auto vertex_manager = std::make_unique<VertexManager>();
g_vertex_manager = std::make_unique<VertexManager>(); auto perf_query = std::make_unique<PerfQuery>();
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>(); auto bounding_box = std::make_unique<VKBoundingBox>();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_texture_cache = std::make_unique<TextureCacheBase>();
g_perf_query = std::make_unique<PerfQuery>();
if (!g_vertex_manager->Initialize() || !g_shader_cache->Initialize() || if (!InitializeShared(std::move(gfx), std::move(vertex_manager), std::move(perf_query),
!g_renderer->Initialize() || !g_framebuffer_manager->Initialize() || std::move(bounding_box)))
!g_texture_cache->Initialize() || !PerfQuery::GetInstance()->Initialize())
{ {
PanicAlertFmt("Failed to initialize renderer classes");
Shutdown();
return false; return false;
} }
g_shader_cache->InitializeShaderCache(); if (!PerfQuery::GetInstance()->Initialize())
{
PanicAlertFmt("Failed to initialize PerfQuery");
return false;
}
return true; return true;
} }

View File

@ -13,7 +13,7 @@
#include "VideoBackends/Vulkan/CommandBufferManager.h" #include "VideoBackends/Vulkan/CommandBufferManager.h"
#include "VideoBackends/Vulkan/StateTracker.h" #include "VideoBackends/Vulkan/StateTracker.h"
#include "VideoBackends/Vulkan/VKRenderer.h" #include "VideoBackends/Vulkan/VKGfx.h"
#include "VideoBackends/Vulkan/VulkanContext.h" #include "VideoBackends/Vulkan/VulkanContext.h"
#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoCommon.h"
@ -234,7 +234,7 @@ void PerfQuery::PartialFlush(bool blocking)
if (blocking || m_query_buffer[m_query_readback_pos].fence_counter == if (blocking || m_query_buffer[m_query_readback_pos].fence_counter ==
g_command_buffer_mgr->GetCurrentFenceCounter()) g_command_buffer_mgr->GetCurrentFenceCounter())
{ {
Renderer::GetInstance()->ExecuteCommandBuffer(true, blocking); VKGfx::GetInstance()->ExecuteCommandBuffer(true, blocking);
} }
ReadbackQueries(); ReadbackQueries();

View File

@ -17,7 +17,7 @@
#include "VideoBackends/Vulkan/ObjectCache.h" #include "VideoBackends/Vulkan/ObjectCache.h"
#include "VideoBackends/Vulkan/StagingBuffer.h" #include "VideoBackends/Vulkan/StagingBuffer.h"
#include "VideoBackends/Vulkan/StateTracker.h" #include "VideoBackends/Vulkan/StateTracker.h"
#include "VideoBackends/Vulkan/VKRenderer.h" #include "VideoBackends/Vulkan/VKGfx.h"
#include "VideoBackends/Vulkan/VKStreamBuffer.h" #include "VideoBackends/Vulkan/VKStreamBuffer.h"
#include "VideoBackends/Vulkan/VulkanContext.h" #include "VideoBackends/Vulkan/VulkanContext.h"
@ -367,7 +367,7 @@ void VKTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8*
// Execute the command buffer first. // Execute the command buffer first.
WARN_LOG_FMT(VIDEO, WARN_LOG_FMT(VIDEO,
"Executing command list while waiting for space in texture upload buffer"); "Executing command list while waiting for space in texture upload buffer");
Renderer::GetInstance()->ExecuteCommandBuffer(false); VKGfx::GetInstance()->ExecuteCommandBuffer(false);
// Try allocating again. This may cause a fence wait. // Try allocating again. This may cause a fence wait.
if (!stream_buffer->ReserveMemory(upload_size, upload_alignment)) if (!stream_buffer->ReserveMemory(upload_size, upload_alignment))
@ -967,7 +967,7 @@ void VKStagingTexture::Flush()
if (g_command_buffer_mgr->GetCurrentFenceCounter() == m_flush_fence_counter) if (g_command_buffer_mgr->GetCurrentFenceCounter() == m_flush_fence_counter)
{ {
// Execute the command buffer and wait for it to finish. // Execute the command buffer and wait for it to finish.
Renderer::GetInstance()->ExecuteCommandBuffer(false, true); VKGfx::GetInstance()->ExecuteCommandBuffer(false, true);
} }
else else
{ {

View File

@ -14,7 +14,7 @@
#include "VideoBackends/Vulkan/CommandBufferManager.h" #include "VideoBackends/Vulkan/CommandBufferManager.h"
#include "VideoBackends/Vulkan/StateTracker.h" #include "VideoBackends/Vulkan/StateTracker.h"
#include "VideoBackends/Vulkan/VKRenderer.h" #include "VideoBackends/Vulkan/VKGfx.h"
#include "VideoBackends/Vulkan/VKStreamBuffer.h" #include "VideoBackends/Vulkan/VKStreamBuffer.h"
#include "VideoBackends/Vulkan/VKVertexFormat.h" #include "VideoBackends/Vulkan/VKVertexFormat.h"
#include "VideoBackends/Vulkan/VulkanContext.h" #include "VideoBackends/Vulkan/VulkanContext.h"
@ -152,7 +152,7 @@ void VertexManager::ResetBuffer(u32 vertex_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_FMT(VIDEO, "Executing command list while waiting for space in vertex/index buffer"); WARN_LOG_FMT(VIDEO, "Executing command list while waiting for space in vertex/index buffer");
Renderer::GetInstance()->ExecuteCommandBuffer(false); VKGfx::GetInstance()->ExecuteCommandBuffer(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)
@ -266,7 +266,7 @@ bool VertexManager::ReserveConstantStorage()
// 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_FMT(VIDEO, "Executing command buffer while waiting for space in uniform buffer"); WARN_LOG_FMT(VIDEO, "Executing command buffer while waiting for space in uniform buffer");
Renderer::GetInstance()->ExecuteCommandBuffer(false); VKGfx::GetInstance()->ExecuteCommandBuffer(false);
// Since we are on a new command buffer, all constants have been invalidated, and we need // Since we are on a new command buffer, all constants have been invalidated, and we need
// to reupload them. We may as well do this now, since we're issuing a draw anyway. // to reupload them. We may as well do this now, since we're issuing a draw anyway.
@ -337,7 +337,7 @@ void VertexManager::UploadUtilityUniforms(const void* data, u32 data_size)
g_vulkan_context->GetUniformBufferAlignment())) g_vulkan_context->GetUniformBufferAlignment()))
{ {
WARN_LOG_FMT(VIDEO, "Executing command buffer while waiting for ext space in uniform buffer"); WARN_LOG_FMT(VIDEO, "Executing command buffer while waiting for ext space in uniform buffer");
Renderer::GetInstance()->ExecuteCommandBuffer(false); VKGfx::GetInstance()->ExecuteCommandBuffer(false);
} }
StateTracker::GetInstance()->SetUtilityUniformBuffer( StateTracker::GetInstance()->SetUtilityUniformBuffer(
@ -358,7 +358,7 @@ bool VertexManager::UploadTexelBuffer(const void* data, u32 data_size, TexelBuff
{ {
// Try submitting cmdbuffer. // Try submitting cmdbuffer.
WARN_LOG_FMT(VIDEO, "Submitting command buffer while waiting for space in texel buffer"); WARN_LOG_FMT(VIDEO, "Submitting command buffer while waiting for space in texel buffer");
Renderer::GetInstance()->ExecuteCommandBuffer(false, false); VKGfx::GetInstance()->ExecuteCommandBuffer(false, false);
if (!m_texel_stream_buffer->ReserveMemory(data_size, elem_size)) if (!m_texel_stream_buffer->ReserveMemory(data_size, elem_size))
{ {
PanicAlertFmt("Failed to allocate {} bytes from texel buffer", data_size); PanicAlertFmt("Failed to allocate {} bytes from texel buffer", data_size);
@ -388,7 +388,7 @@ bool VertexManager::UploadTexelBuffer(const void* data, u32 data_size, TexelBuff
{ {
// Try submitting cmdbuffer. // Try submitting cmdbuffer.
WARN_LOG_FMT(VIDEO, "Submitting command buffer while waiting for space in texel buffer"); WARN_LOG_FMT(VIDEO, "Submitting command buffer while waiting for space in texel buffer");
Renderer::GetInstance()->ExecuteCommandBuffer(false, false); VKGfx::GetInstance()->ExecuteCommandBuffer(false, false);
if (!m_texel_stream_buffer->ReserveMemory(reserve_size, elem_size)) if (!m_texel_stream_buffer->ReserveMemory(reserve_size, elem_size))
{ {
PanicAlertFmt("Failed to allocate {} bytes from texel buffer", reserve_size); PanicAlertFmt("Failed to allocate {} bytes from texel buffer", reserve_size);

View File

@ -370,9 +370,10 @@ bool VideoBackendBase::InitializeShared(std::unique_ptr<AbstractGfx> gfx,
system.GetPixelShaderManager().Init(); system.GetPixelShaderManager().Init();
TMEM::Init(); TMEM::Init();
if (!g_vertex_manager->Initialize() || !g_renderer->Initialize() || !g_presenter->Initialize() || if (!g_vertex_manager->Initialize() || !g_shader_cache->Initialize() ||
!g_shader_cache->Initialize() || !g_framebuffer_manager->Initialize() || !g_renderer->Initialize() || !g_presenter->Initialize() ||
!g_texture_cache->Initialize() || !g_bounding_box->Initialize()) !g_framebuffer_manager->Initialize() || !g_texture_cache->Initialize() ||
!g_bounding_box->Initialize())
{ {
PanicAlertFmtT("Failed to initialize renderer classes"); PanicAlertFmtT("Failed to initialize renderer classes");
Shutdown(); Shutdown();