mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-20 19:22:47 +01:00
Merge pull request #6246 from stenzek/vulkan-readback-fixes
Vulkan: Fix MSAA regression from 5.0-5968
This commit is contained in:
commit
ce0c699b66
@ -40,14 +40,12 @@ FramebufferManager::FramebufferManager()
|
|||||||
FramebufferManager::~FramebufferManager()
|
FramebufferManager::~FramebufferManager()
|
||||||
{
|
{
|
||||||
DestroyEFBFramebuffer();
|
DestroyEFBFramebuffer();
|
||||||
DestroyEFBRenderPass();
|
|
||||||
|
|
||||||
DestroyConversionShaders();
|
DestroyConversionShaders();
|
||||||
|
|
||||||
DestroyReadbackFramebuffer();
|
DestroyReadbackFramebuffer();
|
||||||
DestroyReadbackTextures();
|
DestroyReadbackTextures();
|
||||||
DestroyReadbackShaders();
|
DestroyReadbackShaders();
|
||||||
DestroyReadbackRenderPasses();
|
|
||||||
|
|
||||||
DestroyPokeVertexBuffer();
|
DestroyPokeVertexBuffer();
|
||||||
DestroyPokeShaders();
|
DestroyPokeShaders();
|
||||||
@ -88,7 +86,7 @@ MultisamplingState FramebufferManager::GetEFBMultisamplingState() const
|
|||||||
|
|
||||||
bool FramebufferManager::Initialize()
|
bool FramebufferManager::Initialize()
|
||||||
{
|
{
|
||||||
if (!CreateEFBRenderPass())
|
if (!CreateEFBRenderPasses())
|
||||||
{
|
{
|
||||||
PanicAlert("Failed to create EFB render pass");
|
PanicAlert("Failed to create EFB render pass");
|
||||||
return false;
|
return false;
|
||||||
@ -142,108 +140,18 @@ bool FramebufferManager::Initialize()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManager::CreateEFBRenderPass()
|
bool FramebufferManager::CreateEFBRenderPasses()
|
||||||
{
|
{
|
||||||
VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(g_ActiveConfig.iMultisamples);
|
m_efb_load_render_pass =
|
||||||
|
g_object_cache->GetRenderPass(EFB_COLOR_TEXTURE_FORMAT, EFB_DEPTH_TEXTURE_FORMAT,
|
||||||
// render pass for rendering to the efb
|
g_ActiveConfig.iMultisamples, VK_ATTACHMENT_LOAD_OP_LOAD);
|
||||||
VkAttachmentDescription attachments[] = {
|
m_efb_clear_render_pass =
|
||||||
{0, EFB_COLOR_TEXTURE_FORMAT, samples, VK_ATTACHMENT_LOAD_OP_LOAD,
|
g_object_cache->GetRenderPass(EFB_COLOR_TEXTURE_FORMAT, EFB_DEPTH_TEXTURE_FORMAT,
|
||||||
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
g_ActiveConfig.iMultisamples, VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
m_depth_resolve_render_pass = g_object_cache->GetRenderPass(
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
|
EFB_DEPTH_AS_COLOR_TEXTURE_FORMAT, VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
{0, EFB_DEPTH_TEXTURE_FORMAT, samples, VK_ATTACHMENT_LOAD_OP_LOAD,
|
return m_efb_load_render_pass != VK_NULL_HANDLE && m_efb_clear_render_pass != VK_NULL_HANDLE &&
|
||||||
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
m_depth_resolve_render_pass != VK_NULL_HANDLE;
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}};
|
|
||||||
|
|
||||||
VkAttachmentReference color_attachment_references[] = {
|
|
||||||
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
|
||||||
|
|
||||||
VkAttachmentReference depth_attachment_reference = {
|
|
||||||
1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
|
|
||||||
|
|
||||||
VkSubpassDescription subpass_description = {
|
|
||||||
0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, color_attachment_references,
|
|
||||||
nullptr, &depth_attachment_reference, 0, nullptr};
|
|
||||||
|
|
||||||
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
|
||||||
nullptr,
|
|
||||||
0,
|
|
||||||
static_cast<u32>(ArraySize(attachments)),
|
|
||||||
attachments,
|
|
||||||
1,
|
|
||||||
&subpass_description,
|
|
||||||
0,
|
|
||||||
nullptr};
|
|
||||||
|
|
||||||
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
|
|
||||||
&m_efb_load_render_pass);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass (EFB) failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// render pass for clearing color/depth on load, as opposed to loading it
|
|
||||||
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
||||||
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
||||||
res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
|
|
||||||
&m_efb_clear_render_pass);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass (EFB) failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// render pass for resolving depth, since we can't do it with vkCmdResolveImage
|
|
||||||
if (g_ActiveConfig.MultisamplingEnabled())
|
|
||||||
{
|
|
||||||
VkAttachmentDescription resolve_attachment = {0,
|
|
||||||
EFB_DEPTH_AS_COLOR_TEXTURE_FORMAT,
|
|
||||||
VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
|
||||||
VK_ATTACHMENT_STORE_OP_STORE,
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
|
||||||
|
|
||||||
subpass_description.pDepthStencilAttachment = nullptr;
|
|
||||||
pass_info.pAttachments = &resolve_attachment;
|
|
||||||
pass_info.attachmentCount = 1;
|
|
||||||
res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
|
|
||||||
&m_depth_resolve_render_pass);
|
|
||||||
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass (EFB depth resolve) failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramebufferManager::DestroyEFBRenderPass()
|
|
||||||
{
|
|
||||||
if (m_efb_load_render_pass != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_efb_load_render_pass, nullptr);
|
|
||||||
m_efb_load_render_pass = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_efb_clear_render_pass != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_efb_clear_render_pass, nullptr);
|
|
||||||
m_efb_clear_render_pass = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_depth_resolve_render_pass != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_depth_resolve_render_pass, nullptr);
|
|
||||||
m_depth_resolve_render_pass = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManager::CreateEFBFramebuffer()
|
bool FramebufferManager::CreateEFBFramebuffer()
|
||||||
@ -256,7 +164,7 @@ bool FramebufferManager::CreateEFBFramebuffer()
|
|||||||
INFO_LOG(VIDEO, "EFB size: %ux%ux%u", efb_width, efb_height, efb_layers);
|
INFO_LOG(VIDEO, "EFB size: %ux%ux%u", efb_width, efb_height, efb_layers);
|
||||||
|
|
||||||
// Update the static variable in the base class. Why does this even exist?
|
// Update the static variable in the base class. Why does this even exist?
|
||||||
FramebufferManagerBase::m_EFBLayers = g_ActiveConfig.iMultisamples;
|
FramebufferManagerBase::m_EFBLayers = efb_layers;
|
||||||
|
|
||||||
// Allocate EFB render targets
|
// Allocate EFB render targets
|
||||||
m_efb_color_texture =
|
m_efb_color_texture =
|
||||||
@ -410,21 +318,17 @@ void FramebufferManager::DestroyEFBFramebuffer()
|
|||||||
m_efb_resolve_depth_texture.reset();
|
m_efb_resolve_depth_texture.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::ResizeEFBTextures()
|
void FramebufferManager::RecreateEFBFramebuffer()
|
||||||
{
|
{
|
||||||
DestroyEFBFramebuffer();
|
DestroyEFBFramebuffer();
|
||||||
|
|
||||||
|
if (!CreateEFBRenderPasses())
|
||||||
|
PanicAlert("Failed to create EFB render pass");
|
||||||
|
|
||||||
if (!CreateEFBFramebuffer())
|
if (!CreateEFBFramebuffer())
|
||||||
PanicAlert("Failed to create EFB textures");
|
PanicAlert("Failed to create EFB textures");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::RecreateRenderPass()
|
|
||||||
{
|
|
||||||
DestroyEFBRenderPass();
|
|
||||||
|
|
||||||
if (!CreateEFBRenderPass())
|
|
||||||
PanicAlert("Failed to create EFB render pass");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramebufferManager::RecompileShaders()
|
void FramebufferManager::RecompileShaders()
|
||||||
{
|
{
|
||||||
DestroyConversionShaders();
|
DestroyConversionShaders();
|
||||||
@ -529,6 +433,8 @@ Texture2D* FramebufferManager::ResolveEFBDepthTexture(const VkRect2D& region)
|
|||||||
|
|
||||||
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);
|
||||||
|
m_efb_resolve_depth_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Draw using resolve shader to write the minimum depth of all samples to the resolve texture.
|
// Draw using resolve shader to write the minimum depth of all samples to the resolve texture.
|
||||||
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
@ -546,8 +452,6 @@ Texture2D* FramebufferManager::ResolveEFBDepthTexture(const VkRect2D& region)
|
|||||||
m_efb_depth_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
m_efb_depth_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Render pass transitions to shader resource.
|
|
||||||
m_efb_resolve_depth_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
|
||||||
return m_efb_resolve_depth_texture.get();
|
return m_efb_resolve_depth_texture.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,6 +619,9 @@ bool FramebufferManager::PopulateColorReadbackTexture()
|
|||||||
|
|
||||||
if (GetEFBWidth() != EFB_WIDTH || GetEFBHeight() != EFB_HEIGHT)
|
if (GetEFBWidth() != EFB_WIDTH || GetEFBHeight() != EFB_HEIGHT)
|
||||||
{
|
{
|
||||||
|
// Transition EFB to shader read before drawing.
|
||||||
|
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
m_color_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
m_color_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
@ -725,10 +632,6 @@ bool FramebufferManager::PopulateColorReadbackTexture()
|
|||||||
|
|
||||||
VkRect2D rect = {{0, 0}, {EFB_WIDTH, EFB_HEIGHT}};
|
VkRect2D rect = {{0, 0}, {EFB_WIDTH, EFB_HEIGHT}};
|
||||||
draw.BeginRenderPass(m_color_copy_framebuffer, rect);
|
draw.BeginRenderPass(m_color_copy_framebuffer, rect);
|
||||||
|
|
||||||
// Transition EFB to shader read before drawing.
|
|
||||||
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
|
||||||
draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetPointSampler());
|
draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetPointSampler());
|
||||||
draw.SetViewportAndScissor(0, 0, EFB_WIDTH, EFB_HEIGHT);
|
draw.SetViewportAndScissor(0, 0, EFB_WIDTH, EFB_HEIGHT);
|
||||||
draw.DrawWithoutVertexBuffer(4);
|
draw.DrawWithoutVertexBuffer(4);
|
||||||
@ -791,6 +694,9 @@ bool FramebufferManager::PopulateDepthReadbackTexture()
|
|||||||
}
|
}
|
||||||
if (GetEFBWidth() != EFB_WIDTH || GetEFBHeight() != EFB_HEIGHT)
|
if (GetEFBWidth() != EFB_WIDTH || GetEFBHeight() != EFB_HEIGHT)
|
||||||
{
|
{
|
||||||
|
// Transition EFB to shader read before drawing.
|
||||||
|
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
m_depth_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
m_depth_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
@ -801,10 +707,6 @@ bool FramebufferManager::PopulateDepthReadbackTexture()
|
|||||||
|
|
||||||
VkRect2D rect = {{0, 0}, {EFB_WIDTH, EFB_HEIGHT}};
|
VkRect2D rect = {{0, 0}, {EFB_WIDTH, EFB_HEIGHT}};
|
||||||
draw.BeginRenderPass(m_depth_copy_framebuffer, rect);
|
draw.BeginRenderPass(m_depth_copy_framebuffer, rect);
|
||||||
|
|
||||||
// Transition EFB to shader read before drawing.
|
|
||||||
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
|
||||||
draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetPointSampler());
|
draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetPointSampler());
|
||||||
draw.SetViewportAndScissor(0, 0, EFB_WIDTH, EFB_HEIGHT);
|
draw.SetViewportAndScissor(0, 0, EFB_WIDTH, EFB_HEIGHT);
|
||||||
draw.DrawWithoutVertexBuffer(4);
|
draw.DrawWithoutVertexBuffer(4);
|
||||||
@ -849,62 +751,12 @@ void FramebufferManager::InvalidatePeekCache()
|
|||||||
|
|
||||||
bool FramebufferManager::CreateReadbackRenderPasses()
|
bool FramebufferManager::CreateReadbackRenderPasses()
|
||||||
{
|
{
|
||||||
VkAttachmentDescription copy_attachment = {
|
m_copy_color_render_pass = g_object_cache->GetRenderPass(
|
||||||
0, // VkAttachmentDescriptionFlags flags
|
EFB_COLOR_TEXTURE_FORMAT, VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
EFB_COLOR_TEXTURE_FORMAT, // VkFormat format
|
m_copy_depth_render_pass = g_object_cache->GetRenderPass(
|
||||||
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
|
EFB_DEPTH_AS_COLOR_TEXTURE_FORMAT, VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp
|
if (m_copy_color_render_pass == VK_NULL_HANDLE || m_copy_depth_render_pass == VK_NULL_HANDLE)
|
||||||
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
|
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
|
|
||||||
};
|
|
||||||
VkAttachmentReference copy_attachment_ref = {
|
|
||||||
0, // uint32_t attachment
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
|
|
||||||
};
|
|
||||||
VkSubpassDescription copy_subpass = {
|
|
||||||
0, // VkSubpassDescriptionFlags flags
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
|
|
||||||
0, // uint32_t inputAttachmentCount
|
|
||||||
nullptr, // const VkAttachmentReference* pInputAttachments
|
|
||||||
1, // uint32_t colorAttachmentCount
|
|
||||||
©_attachment_ref, // const VkAttachmentReference* pColorAttachments
|
|
||||||
nullptr, // const VkAttachmentReference* pResolveAttachments
|
|
||||||
nullptr, // const VkAttachmentReference* pDepthStencilAttachment
|
|
||||||
0, // uint32_t preserveAttachmentCount
|
|
||||||
nullptr // const uint32_t* pPreserveAttachments
|
|
||||||
};
|
|
||||||
VkRenderPassCreateInfo copy_pass = {
|
|
||||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
|
|
||||||
nullptr, // const void* pNext
|
|
||||||
0, // VkRenderPassCreateFlags flags
|
|
||||||
1, // uint32_t attachmentCount
|
|
||||||
©_attachment, // const VkAttachmentDescription* pAttachments
|
|
||||||
1, // uint32_t subpassCount
|
|
||||||
©_subpass, // const VkSubpassDescription* pSubpasses
|
|
||||||
0, // uint32_t dependencyCount
|
|
||||||
nullptr // const VkSubpassDependency* pDependencies
|
|
||||||
};
|
|
||||||
|
|
||||||
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), ©_pass, nullptr,
|
|
||||||
&m_copy_color_render_pass);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass failed: ");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Depth is similar to copy, just a different format.
|
|
||||||
copy_attachment.format = EFB_DEPTH_AS_COLOR_TEXTURE_FORMAT;
|
|
||||||
res = vkCreateRenderPass(g_vulkan_context->GetDevice(), ©_pass, nullptr,
|
|
||||||
&m_copy_depth_render_pass);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some devices don't support point sizes >1 (e.g. Adreno).
|
// Some devices don't support point sizes >1 (e.g. Adreno).
|
||||||
// If we can't use a point size above our maximum IR, use triangles instead.
|
// If we can't use a point size above our maximum IR, use triangles instead.
|
||||||
@ -925,20 +777,6 @@ bool FramebufferManager::CreateReadbackRenderPasses()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::DestroyReadbackRenderPasses()
|
|
||||||
{
|
|
||||||
if (m_copy_color_render_pass != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_copy_color_render_pass, nullptr);
|
|
||||||
m_copy_color_render_pass = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
if (m_copy_depth_render_pass != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_copy_depth_render_pass, nullptr);
|
|
||||||
m_copy_depth_render_pass = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FramebufferManager::CompileReadbackShaders()
|
bool FramebufferManager::CompileReadbackShaders()
|
||||||
{
|
{
|
||||||
std::string source;
|
std::string source;
|
||||||
|
@ -45,10 +45,9 @@ public:
|
|||||||
VkSampleCountFlagBits GetEFBSamples() const;
|
VkSampleCountFlagBits GetEFBSamples() const;
|
||||||
MultisamplingState GetEFBMultisamplingState() const;
|
MultisamplingState GetEFBMultisamplingState() const;
|
||||||
|
|
||||||
void ResizeEFBTextures();
|
void RecreateEFBFramebuffer();
|
||||||
|
|
||||||
// Recompile shaders, use when MSAA mode changes.
|
// Recompile shaders, use when MSAA mode changes.
|
||||||
void RecreateRenderPass();
|
|
||||||
void RecompileShaders();
|
void RecompileShaders();
|
||||||
|
|
||||||
// Reinterpret pixel format of EFB color texture.
|
// Reinterpret pixel format of EFB color texture.
|
||||||
@ -82,8 +81,7 @@ private:
|
|||||||
u32 color;
|
u32 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool CreateEFBRenderPass();
|
bool CreateEFBRenderPasses();
|
||||||
void DestroyEFBRenderPass();
|
|
||||||
bool CreateEFBFramebuffer();
|
bool CreateEFBFramebuffer();
|
||||||
void DestroyEFBFramebuffer();
|
void DestroyEFBFramebuffer();
|
||||||
|
|
||||||
@ -91,7 +89,6 @@ private:
|
|||||||
void DestroyConversionShaders();
|
void DestroyConversionShaders();
|
||||||
|
|
||||||
bool CreateReadbackRenderPasses();
|
bool CreateReadbackRenderPasses();
|
||||||
void DestroyReadbackRenderPasses();
|
|
||||||
bool CompileReadbackShaders();
|
bool CompileReadbackShaders();
|
||||||
void DestroyReadbackShaders();
|
void DestroyReadbackShaders();
|
||||||
bool CreateReadbackTextures();
|
bool CreateReadbackTextures();
|
||||||
|
@ -37,6 +37,7 @@ ObjectCache::~ObjectCache()
|
|||||||
DestroySamplers();
|
DestroySamplers();
|
||||||
DestroyPipelineLayouts();
|
DestroyPipelineLayouts();
|
||||||
DestroyDescriptorSetLayouts();
|
DestroyDescriptorSetLayouts();
|
||||||
|
DestroyRenderPassCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectCache::Initialize()
|
bool ObjectCache::Initialize()
|
||||||
@ -358,4 +359,90 @@ VkSampler ObjectCache::GetSampler(const SamplerState& info)
|
|||||||
m_sampler_cache.emplace(info, sampler);
|
m_sampler_cache.emplace(info, sampler);
|
||||||
return sampler;
|
return sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkRenderPass ObjectCache::GetRenderPass(VkFormat color_format, VkFormat depth_format,
|
||||||
|
u32 multisamples, VkAttachmentLoadOp load_op)
|
||||||
|
{
|
||||||
|
auto key = std::tie(color_format, depth_format, multisamples, load_op);
|
||||||
|
auto it = m_render_pass_cache.find(key);
|
||||||
|
if (it != m_render_pass_cache.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
VkAttachmentReference color_reference;
|
||||||
|
VkAttachmentReference* color_reference_ptr = nullptr;
|
||||||
|
VkAttachmentReference depth_reference;
|
||||||
|
VkAttachmentReference* depth_reference_ptr = nullptr;
|
||||||
|
std::array<VkAttachmentDescription, 2> attachments;
|
||||||
|
u32 num_attachments = 0;
|
||||||
|
if (color_format != VK_FORMAT_UNDEFINED)
|
||||||
|
{
|
||||||
|
attachments[num_attachments] = {0,
|
||||||
|
color_format,
|
||||||
|
static_cast<VkSampleCountFlagBits>(multisamples),
|
||||||
|
load_op,
|
||||||
|
VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||||
|
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
||||||
|
color_reference.attachment = num_attachments;
|
||||||
|
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
color_reference_ptr = &color_reference;
|
||||||
|
num_attachments++;
|
||||||
|
}
|
||||||
|
if (depth_format != VK_FORMAT_UNDEFINED)
|
||||||
|
{
|
||||||
|
attachments[num_attachments] = {0,
|
||||||
|
depth_format,
|
||||||
|
static_cast<VkSampleCountFlagBits>(multisamples),
|
||||||
|
load_op,
|
||||||
|
VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||||
|
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||||
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
|
||||||
|
depth_reference.attachment = num_attachments;
|
||||||
|
depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
depth_reference_ptr = &depth_reference;
|
||||||
|
num_attachments++;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSubpassDescription subpass = {0,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
color_reference_ptr ? 1u : 0u,
|
||||||
|
color_reference_ptr ? color_reference_ptr : nullptr,
|
||||||
|
nullptr,
|
||||||
|
depth_reference_ptr,
|
||||||
|
0,
|
||||||
|
nullptr};
|
||||||
|
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
num_attachments,
|
||||||
|
attachments.data(),
|
||||||
|
1,
|
||||||
|
&subpass,
|
||||||
|
0,
|
||||||
|
nullptr};
|
||||||
|
|
||||||
|
VkRenderPass pass;
|
||||||
|
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr, &pass);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
LOG_VULKAN_ERROR(res, "vkCreateRenderPass failed: ");
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_render_pass_cache.emplace(key, pass);
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectCache::DestroyRenderPassCache()
|
||||||
|
{
|
||||||
|
for (auto& it : m_render_pass_cache)
|
||||||
|
vkDestroyRenderPass(g_vulkan_context->GetDevice(), it.second, nullptr);
|
||||||
|
m_render_pass_cache.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
@ -66,6 +67,10 @@ public:
|
|||||||
// Dummy image for samplers that are unbound
|
// Dummy image for samplers that are unbound
|
||||||
Texture2D* GetDummyImage() const { return m_dummy_texture.get(); }
|
Texture2D* GetDummyImage() const { return m_dummy_texture.get(); }
|
||||||
VkImageView GetDummyImageView() const { return m_dummy_texture->GetView(); }
|
VkImageView GetDummyImageView() const { return m_dummy_texture->GetView(); }
|
||||||
|
// Render pass cache.
|
||||||
|
VkRenderPass GetRenderPass(VkFormat color_format, VkFormat depth_format, u32 multisamples,
|
||||||
|
VkAttachmentLoadOp load_op);
|
||||||
|
|
||||||
// Perform at startup, create descriptor layouts, compiles all static shaders.
|
// Perform at startup, create descriptor layouts, compiles all static shaders.
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
|
|
||||||
@ -81,6 +86,7 @@ private:
|
|||||||
bool CreateUtilityShaderVertexFormat();
|
bool CreateUtilityShaderVertexFormat();
|
||||||
bool CreateStaticSamplers();
|
bool CreateStaticSamplers();
|
||||||
void DestroySamplers();
|
void DestroySamplers();
|
||||||
|
void DestroyRenderPassCache();
|
||||||
|
|
||||||
std::array<VkDescriptorSetLayout, NUM_DESCRIPTOR_SET_LAYOUTS> m_descriptor_set_layouts = {};
|
std::array<VkDescriptorSetLayout, NUM_DESCRIPTOR_SET_LAYOUTS> m_descriptor_set_layouts = {};
|
||||||
std::array<VkPipelineLayout, NUM_PIPELINE_LAYOUTS> m_pipeline_layouts = {};
|
std::array<VkPipelineLayout, NUM_PIPELINE_LAYOUTS> m_pipeline_layouts = {};
|
||||||
@ -96,6 +102,10 @@ private:
|
|||||||
|
|
||||||
// Dummy image for samplers that are unbound
|
// Dummy image for samplers that are unbound
|
||||||
std::unique_ptr<Texture2D> m_dummy_texture;
|
std::unique_ptr<Texture2D> m_dummy_texture;
|
||||||
|
|
||||||
|
// Render pass cache
|
||||||
|
using RenderPassCacheKey = std::tuple<VkFormat, VkFormat, u32, VkAttachmentLoadOp>;
|
||||||
|
std::map<RenderPassCacheKey, VkRenderPass> m_render_pass_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<ObjectCache> g_object_cache;
|
extern std::unique_ptr<ObjectCache> g_object_cache;
|
||||||
|
@ -545,9 +545,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
|||||||
// Handle host window resizes.
|
// Handle host window resizes.
|
||||||
CheckForSurfaceChange();
|
CheckForSurfaceChange();
|
||||||
|
|
||||||
if (CalculateTargetSize())
|
|
||||||
ResizeEFBTextures();
|
|
||||||
|
|
||||||
// Update the window size based on the frame that was just rendered.
|
// Update the window size based on the frame that was just rendered.
|
||||||
// Due to depending on guest state, we need to call this every frame.
|
// Due to depending on guest state, we need to call this every frame.
|
||||||
SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height);
|
SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height);
|
||||||
@ -724,9 +721,8 @@ void Renderer::CheckForSurfaceChange()
|
|||||||
void Renderer::CheckForConfigChanges()
|
void Renderer::CheckForConfigChanges()
|
||||||
{
|
{
|
||||||
// Save the video config so we can compare against to determine which settings have changed.
|
// Save the video config so we can compare against to determine which settings have changed.
|
||||||
|
const u32 old_multisamples = g_ActiveConfig.iMultisamples;
|
||||||
const int old_anisotropy = g_ActiveConfig.iMaxAnisotropy;
|
const int old_anisotropy = g_ActiveConfig.iMaxAnisotropy;
|
||||||
const AspectMode old_aspect_mode = g_ActiveConfig.aspect_mode;
|
|
||||||
const int old_efb_scale = g_ActiveConfig.iEFBScale;
|
|
||||||
const bool old_force_filtering = g_ActiveConfig.bForceFiltering;
|
const bool old_force_filtering = g_ActiveConfig.bForceFiltering;
|
||||||
|
|
||||||
// Copy g_Config to g_ActiveConfig.
|
// Copy g_Config to g_ActiveConfig.
|
||||||
@ -735,21 +731,17 @@ void Renderer::CheckForConfigChanges()
|
|||||||
UpdateActiveConfig();
|
UpdateActiveConfig();
|
||||||
|
|
||||||
// Determine which (if any) settings have changed.
|
// Determine which (if any) settings have changed.
|
||||||
|
const bool multisamples_changed = old_multisamples != g_ActiveConfig.iMultisamples;
|
||||||
const bool anisotropy_changed = old_anisotropy != g_ActiveConfig.iMaxAnisotropy;
|
const bool anisotropy_changed = old_anisotropy != g_ActiveConfig.iMaxAnisotropy;
|
||||||
const bool force_texture_filtering_changed =
|
const bool force_texture_filtering_changed =
|
||||||
old_force_filtering != g_ActiveConfig.bForceFiltering;
|
old_force_filtering != g_ActiveConfig.bForceFiltering;
|
||||||
const bool efb_scale_changed = old_efb_scale != g_ActiveConfig.iEFBScale;
|
|
||||||
const bool aspect_changed = old_aspect_mode != g_ActiveConfig.aspect_mode;
|
|
||||||
|
|
||||||
// Update texture cache settings with any changed options.
|
// Update texture cache settings with any changed options.
|
||||||
TextureCache::GetInstance()->OnConfigChanged(g_ActiveConfig);
|
TextureCache::GetInstance()->OnConfigChanged(g_ActiveConfig);
|
||||||
|
|
||||||
// Handle settings that can cause the target rectangle to change.
|
// Handle settings that can cause the EFB framebuffer to change.
|
||||||
if (efb_scale_changed || aspect_changed)
|
if (CalculateTargetSize() || multisamples_changed)
|
||||||
{
|
RecreateEFBFramebuffer();
|
||||||
if (CalculateTargetSize())
|
|
||||||
ResizeEFBTextures();
|
|
||||||
}
|
|
||||||
|
|
||||||
// MSAA samples changed, we need to recreate the EFB render pass.
|
// MSAA samples changed, we need to recreate the EFB render pass.
|
||||||
// If the stereoscopy mode changed, we need to recreate the buffers as well.
|
// If the stereoscopy mode changed, we need to recreate the buffers as well.
|
||||||
@ -757,10 +749,7 @@ void Renderer::CheckForConfigChanges()
|
|||||||
// Changing stereoscopy from off<->on also requires shaders to be recompiled.
|
// Changing stereoscopy from off<->on also requires shaders to be recompiled.
|
||||||
if (CheckForHostConfigChanges())
|
if (CheckForHostConfigChanges())
|
||||||
{
|
{
|
||||||
g_command_buffer_mgr->WaitForGPUIdle();
|
RecreateEFBFramebuffer();
|
||||||
FramebufferManager::GetInstance()->RecreateRenderPass();
|
|
||||||
FramebufferManager::GetInstance()->ResizeEFBTextures();
|
|
||||||
BindEFBToStateTracker();
|
|
||||||
RecompileShaders();
|
RecompileShaders();
|
||||||
FramebufferManager::GetInstance()->RecompileShaders();
|
FramebufferManager::GetInstance()->RecompileShaders();
|
||||||
g_shader_cache->ReloadShaderAndPipelineCaches();
|
g_shader_cache->ReloadShaderAndPipelineCaches();
|
||||||
@ -798,7 +787,7 @@ void Renderer::OnSwapChainResized()
|
|||||||
m_backbuffer_height = m_swap_chain->GetHeight();
|
m_backbuffer_height = m_swap_chain->GetHeight();
|
||||||
UpdateDrawRectangle();
|
UpdateDrawRectangle();
|
||||||
if (CalculateTargetSize())
|
if (CalculateTargetSize())
|
||||||
ResizeEFBTextures();
|
RecreateEFBFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::BindEFBToStateTracker()
|
void Renderer::BindEFBToStateTracker()
|
||||||
@ -816,11 +805,11 @@ void Renderer::BindEFBToStateTracker()
|
|||||||
FramebufferManager::GetInstance()->GetEFBMultisamplingState());
|
FramebufferManager::GetInstance()->GetEFBMultisamplingState());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::ResizeEFBTextures()
|
void Renderer::RecreateEFBFramebuffer()
|
||||||
{
|
{
|
||||||
// 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();
|
||||||
FramebufferManager::GetInstance()->ResizeEFBTextures();
|
FramebufferManager::GetInstance()->RecreateEFBFramebuffer();
|
||||||
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.
|
||||||
|
@ -82,7 +82,7 @@ private:
|
|||||||
|
|
||||||
void OnSwapChainResized();
|
void OnSwapChainResized();
|
||||||
void BindEFBToStateTracker();
|
void BindEFBToStateTracker();
|
||||||
void ResizeEFBTextures();
|
void RecreateEFBFramebuffer();
|
||||||
|
|
||||||
void RecompileShaders();
|
void RecompileShaders();
|
||||||
bool CompileShaders();
|
bool CompileShaders();
|
||||||
|
@ -33,7 +33,6 @@ SwapChain::~SwapChain()
|
|||||||
{
|
{
|
||||||
DestroySwapChainImages();
|
DestroySwapChainImages();
|
||||||
DestroySwapChain();
|
DestroySwapChain();
|
||||||
DestroyRenderPass();
|
|
||||||
DestroySurface();
|
DestroySurface();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,48 +228,9 @@ bool SwapChain::SelectPresentMode()
|
|||||||
bool SwapChain::CreateRenderPass()
|
bool SwapChain::CreateRenderPass()
|
||||||
{
|
{
|
||||||
// render pass for rendering to the swap chain
|
// render pass for rendering to the swap chain
|
||||||
VkAttachmentDescription present_render_pass_attachments[] = {
|
m_render_pass = g_object_cache->GetRenderPass(m_surface_format.format, VK_FORMAT_UNDEFINED, 1,
|
||||||
{0, m_surface_format.format, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
|
VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||||
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
return m_render_pass != VK_NULL_HANDLE;
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
|
||||||
|
|
||||||
VkAttachmentReference present_render_pass_color_attachment_references[] = {
|
|
||||||
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
|
||||||
|
|
||||||
VkSubpassDescription present_render_pass_subpass_descriptions[] = {
|
|
||||||
{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1,
|
|
||||||
present_render_pass_color_attachment_references, nullptr, nullptr, 0, nullptr}};
|
|
||||||
|
|
||||||
VkRenderPassCreateInfo present_render_pass_info = {
|
|
||||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
|
||||||
nullptr,
|
|
||||||
0,
|
|
||||||
static_cast<u32>(ArraySize(present_render_pass_attachments)),
|
|
||||||
present_render_pass_attachments,
|
|
||||||
static_cast<u32>(ArraySize(present_render_pass_subpass_descriptions)),
|
|
||||||
present_render_pass_subpass_descriptions,
|
|
||||||
0,
|
|
||||||
nullptr};
|
|
||||||
|
|
||||||
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &present_render_pass_info,
|
|
||||||
nullptr, &m_render_pass);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass (present) failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwapChain::DestroyRenderPass()
|
|
||||||
{
|
|
||||||
if (!m_render_pass)
|
|
||||||
return;
|
|
||||||
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_render_pass, nullptr);
|
|
||||||
m_render_pass = VK_NULL_HANDLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwapChain::CreateSwapChain()
|
bool SwapChain::CreateSwapChain()
|
||||||
@ -498,7 +458,6 @@ bool SwapChain::SetVSync(bool enabled)
|
|||||||
bool SwapChain::RecreateSurface(void* native_handle)
|
bool SwapChain::RecreateSurface(void* native_handle)
|
||||||
{
|
{
|
||||||
// Destroy the old swap chain, images, and surface.
|
// Destroy the old swap chain, images, and surface.
|
||||||
DestroyRenderPass();
|
|
||||||
DestroySwapChainImages();
|
DestroySwapChainImages();
|
||||||
DestroySwapChain();
|
DestroySwapChain();
|
||||||
DestroySurface();
|
DestroySurface();
|
||||||
|
@ -68,7 +68,6 @@ private:
|
|||||||
void DestroySwapChain();
|
void DestroySwapChain();
|
||||||
|
|
||||||
bool CreateRenderPass();
|
bool CreateRenderPass();
|
||||||
void DestroyRenderPass();
|
|
||||||
|
|
||||||
bool SetupSwapChainImages();
|
bool SetupSwapChainImages();
|
||||||
void DestroySwapChainImages();
|
void DestroySwapChainImages();
|
||||||
|
@ -37,8 +37,6 @@ TextureCache::TextureCache()
|
|||||||
|
|
||||||
TextureCache::~TextureCache()
|
TextureCache::~TextureCache()
|
||||||
{
|
{
|
||||||
if (m_render_pass != VK_NULL_HANDLE)
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_render_pass, nullptr);
|
|
||||||
TextureCache::DeleteShaders();
|
TextureCache::DeleteShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,11 +45,6 @@ VkShaderModule TextureCache::GetCopyShader() const
|
|||||||
return m_copy_shader;
|
return m_copy_shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPass TextureCache::GetTextureCopyRenderPass() const
|
|
||||||
{
|
|
||||||
return m_render_pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamBuffer* TextureCache::GetTextureUploadBuffer() const
|
StreamBuffer* TextureCache::GetTextureUploadBuffer() const
|
||||||
{
|
{
|
||||||
return m_texture_upload_buffer.get();
|
return m_texture_upload_buffer.get();
|
||||||
@ -73,12 +66,6 @@ bool TextureCache::Initialize()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CreateRenderPasses())
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to create copy render pass");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_texture_converter = std::make_unique<TextureConverter>();
|
m_texture_converter = std::make_unique<TextureConverter>();
|
||||||
if (!m_texture_converter->Initialize())
|
if (!m_texture_converter->Initialize())
|
||||||
{
|
{
|
||||||
@ -98,7 +85,7 @@ bool TextureCache::Initialize()
|
|||||||
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||||
const void* palette, TLUTFormat format)
|
const void* palette, TLUTFormat format)
|
||||||
{
|
{
|
||||||
m_texture_converter->ConvertTexture(destination, source, m_render_pass, palette, format);
|
m_texture_converter->ConvertTexture(destination, source, palette, format);
|
||||||
|
|
||||||
// Ensure both textures remain in the SHADER_READ_ONLY layout so they can be bound.
|
// Ensure both textures remain in the SHADER_READ_ONLY layout so they can be bound.
|
||||||
static_cast<VKTexture*>(source->texture.get())
|
static_cast<VKTexture*>(source->texture.get())
|
||||||
@ -178,50 +165,6 @@ void TextureCache::DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::CreateRenderPasses()
|
|
||||||
{
|
|
||||||
static constexpr VkAttachmentDescription update_attachment = {
|
|
||||||
0,
|
|
||||||
TEXTURECACHE_TEXTURE_FORMAT,
|
|
||||||
VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
|
||||||
VK_ATTACHMENT_STORE_OP_STORE,
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
|
||||||
|
|
||||||
static constexpr VkAttachmentReference color_attachment_reference = {
|
|
||||||
0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
|
||||||
|
|
||||||
static constexpr VkSubpassDescription subpass_description = {
|
|
||||||
0, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
0, nullptr,
|
|
||||||
1, &color_attachment_reference,
|
|
||||||
nullptr, nullptr,
|
|
||||||
0, nullptr};
|
|
||||||
|
|
||||||
VkRenderPassCreateInfo update_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
|
||||||
nullptr,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
&update_attachment,
|
|
||||||
1,
|
|
||||||
&subpass_description,
|
|
||||||
0,
|
|
||||||
nullptr};
|
|
||||||
|
|
||||||
VkResult res =
|
|
||||||
vkCreateRenderPass(g_vulkan_context->GetDevice(), &update_info, nullptr, &m_render_pass);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureCache::CompileShaders()
|
bool TextureCache::CompileShaders()
|
||||||
{
|
{
|
||||||
static const char COPY_SHADER_SOURCE[] = R"(
|
static const char COPY_SHADER_SOURCE[] = R"(
|
||||||
@ -322,8 +265,12 @@ void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
|
|||||||
shader = Util::CompileAndCreateFragmentShader(source);
|
shader = Util::CompileAndCreateFragmentShader(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||||
|
texture->GetRawTexIdentifier()->GetFormat(), VK_FORMAT_UNDEFINED,
|
||||||
|
texture->GetRawTexIdentifier()->GetSamples(), VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
|
|
||||||
UtilityShaderDraw draw(command_buffer,
|
UtilityShaderDraw draw(command_buffer,
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), m_render_pass,
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass,
|
||||||
g_shader_cache->GetPassthroughVertexShader(),
|
g_shader_cache->GetPassthroughVertexShader(),
|
||||||
g_shader_cache->GetPassthroughGeometryShader(), shader);
|
g_shader_cache->GetPassthroughGeometryShader(), shader);
|
||||||
|
|
||||||
|
@ -48,18 +48,13 @@ public:
|
|||||||
TLUTFormat palette_format) override;
|
TLUTFormat palette_format) override;
|
||||||
|
|
||||||
VkShaderModule GetCopyShader() const;
|
VkShaderModule GetCopyShader() const;
|
||||||
VkRenderPass GetTextureCopyRenderPass() const;
|
|
||||||
StreamBuffer* GetTextureUploadBuffer() const;
|
StreamBuffer* GetTextureUploadBuffer() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CreateRenderPasses();
|
|
||||||
|
|
||||||
void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
|
void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
|
||||||
bool scale_by_half, EFBCopyFormat dst_format,
|
bool scale_by_half, EFBCopyFormat dst_format,
|
||||||
bool is_intensity) override;
|
bool is_intensity) override;
|
||||||
|
|
||||||
VkRenderPass m_render_pass = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
std::unique_ptr<StreamBuffer> m_texture_upload_buffer;
|
std::unique_ptr<StreamBuffer> m_texture_upload_buffer;
|
||||||
|
|
||||||
std::unique_ptr<TextureConverter> m_texture_converter;
|
std::unique_ptr<TextureConverter> m_texture_converter;
|
||||||
|
@ -63,9 +63,6 @@ TextureConverter::~TextureConverter()
|
|||||||
if (m_texel_buffer_view_rgba8_uint != VK_NULL_HANDLE)
|
if (m_texel_buffer_view_rgba8_uint != VK_NULL_HANDLE)
|
||||||
vkDestroyBufferView(g_vulkan_context->GetDevice(), m_texel_buffer_view_rgba8_uint, nullptr);
|
vkDestroyBufferView(g_vulkan_context->GetDevice(), m_texel_buffer_view_rgba8_uint, nullptr);
|
||||||
|
|
||||||
if (m_encoding_render_pass != VK_NULL_HANDLE)
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_encoding_render_pass, nullptr);
|
|
||||||
|
|
||||||
for (auto& it : m_encoding_shaders)
|
for (auto& it : m_encoding_shaders)
|
||||||
vkDestroyShaderModule(g_vulkan_context->GetDevice(), it.second, nullptr);
|
vkDestroyShaderModule(g_vulkan_context->GetDevice(), it.second, nullptr);
|
||||||
|
|
||||||
@ -95,12 +92,6 @@ bool TextureConverter::Initialize()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CreateEncodingRenderPass())
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to create encode render pass");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CreateEncodingTexture())
|
if (!CreateEncodingTexture())
|
||||||
{
|
{
|
||||||
PanicAlert("Failed to create encoding texture");
|
PanicAlert("Failed to create encoding texture");
|
||||||
@ -165,8 +156,7 @@ TextureConverter::GetCommandBufferForTextureConversion(const TextureCache::TCach
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextureConverter::ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
void TextureConverter::ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
||||||
TextureCacheBase::TCacheEntry* src_entry,
|
TextureCacheBase::TCacheEntry* src_entry, const void* palette,
|
||||||
VkRenderPass render_pass, const void* palette,
|
|
||||||
TLUTFormat palette_format)
|
TLUTFormat palette_format)
|
||||||
{
|
{
|
||||||
struct PSUniformBlock
|
struct PSUniformBlock
|
||||||
@ -199,6 +189,9 @@ void TextureConverter::ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
|||||||
command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
// Bind and draw to the destination.
|
// Bind and draw to the destination.
|
||||||
|
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||||
|
destination_texture->GetRawTexIdentifier()->GetFormat(), VK_FORMAT_UNDEFINED,
|
||||||
|
destination_texture->GetRawTexIdentifier()->GetSamples(), VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
UtilityShaderDraw draw(command_buffer,
|
UtilityShaderDraw draw(command_buffer,
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_TEXTURE_CONVERSION),
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_TEXTURE_CONVERSION),
|
||||||
render_pass, g_shader_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
|
render_pass, g_shader_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
|
||||||
@ -240,10 +233,13 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p
|
|||||||
->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
|
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||||
|
Util::GetVkFormatForHostTextureFormat(m_encoding_render_texture->GetConfig().format),
|
||||||
|
VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
|
||||||
m_encoding_render_pass, g_shader_cache->GetScreenQuadVertexShader(),
|
render_pass, g_shader_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
|
||||||
VK_NULL_HANDLE, shader);
|
shader);
|
||||||
|
|
||||||
// Uniform - int4 of left,top,native_width,scale
|
// Uniform - int4 of left,top,native_width,scale
|
||||||
EFBEncodeParams encoder_params;
|
EFBEncodeParams encoder_params;
|
||||||
@ -297,10 +293,12 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u
|
|||||||
// the order the guest is expecting and we don't have to swap it at readback time. The width
|
// the order the guest is expecting and we don't have to swap it at readback time. The width
|
||||||
// is halved because we're using an RGBA8 texture, but the YUYV data is two bytes per pixel.
|
// is halved because we're using an RGBA8 texture, but the YUYV data is two bytes per pixel.
|
||||||
u32 output_width = dst_width / 2;
|
u32 output_width = dst_width / 2;
|
||||||
UtilityShaderDraw draw(command_buffer,
|
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
|
Util::GetVkFormatForHostTextureFormat(m_encoding_render_texture->GetConfig().format),
|
||||||
m_encoding_render_pass, g_shader_cache->GetPassthroughVertexShader(),
|
VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
VK_NULL_HANDLE, m_rgb_to_yuyv_shader);
|
UtilityShaderDraw draw(
|
||||||
|
command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass,
|
||||||
|
g_shader_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE, m_rgb_to_yuyv_shader);
|
||||||
VkRect2D region = {{0, 0}, {output_width, dst_height}};
|
VkRect2D region = {{0, 0}, {output_width, dst_height}};
|
||||||
draw.BeginRenderPass(static_cast<VKTexture*>(m_encoding_render_texture.get())->GetFramebuffer(),
|
draw.BeginRenderPass(static_cast<VKTexture*>(m_encoding_render_texture.get())->GetFramebuffer(),
|
||||||
region);
|
region);
|
||||||
@ -368,10 +366,13 @@ void TextureConverter::DecodeYUYVTextureFromMemory(VKTexture* dst_texture, const
|
|||||||
static_cast<int>(src_width / 2)};
|
static_cast<int>(src_width / 2)};
|
||||||
|
|
||||||
// Convert from the YUYV data now in the intermediate texture to RGBA in the destination.
|
// Convert from the YUYV data now in the intermediate texture to RGBA in the destination.
|
||||||
|
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||||
|
dst_texture->GetRawTexIdentifier()->GetFormat(), VK_FORMAT_UNDEFINED,
|
||||||
|
dst_texture->GetRawTexIdentifier()->GetSamples(), VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_TEXTURE_CONVERSION),
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_TEXTURE_CONVERSION),
|
||||||
m_encoding_render_pass, g_shader_cache->GetScreenQuadVertexShader(),
|
render_pass, g_shader_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
|
||||||
VK_NULL_HANDLE, m_yuyv_to_rgb_shader);
|
m_yuyv_to_rgb_shader);
|
||||||
VkRect2D region = {{0, 0}, {src_width, src_height}};
|
VkRect2D region = {{0, 0}, {src_width, src_height}};
|
||||||
draw.BeginRenderPass(dst_texture->GetFramebuffer(), region);
|
draw.BeginRenderPass(dst_texture->GetFramebuffer(), region);
|
||||||
draw.SetViewportAndScissor(0, 0, static_cast<int>(src_width), static_cast<int>(src_height));
|
draw.SetViewportAndScissor(0, 0, static_cast<int>(src_width), static_cast<int>(src_height));
|
||||||
@ -711,42 +712,6 @@ VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyParams& params)
|
|||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureConverter::CreateEncodingRenderPass()
|
|
||||||
{
|
|
||||||
VkAttachmentDescription attachments[] = {
|
|
||||||
{0, Util::GetVkFormatForHostTextureFormat(ENCODING_TEXTURE_FORMAT), VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
|
||||||
|
|
||||||
VkAttachmentReference color_attachment_references[] = {
|
|
||||||
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
|
||||||
|
|
||||||
VkSubpassDescription subpass_descriptions[] = {{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1,
|
|
||||||
color_attachment_references, nullptr, nullptr, 0,
|
|
||||||
nullptr}};
|
|
||||||
|
|
||||||
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
|
||||||
nullptr,
|
|
||||||
0,
|
|
||||||
static_cast<u32>(ArraySize(attachments)),
|
|
||||||
attachments,
|
|
||||||
static_cast<u32>(ArraySize(subpass_descriptions)),
|
|
||||||
subpass_descriptions,
|
|
||||||
0,
|
|
||||||
nullptr};
|
|
||||||
|
|
||||||
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
|
|
||||||
&m_encoding_render_pass);
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass (Encode) failed: ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureConverter::CreateEncodingTexture()
|
bool TextureConverter::CreateEncodingTexture()
|
||||||
{
|
{
|
||||||
TextureConfig config(ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1,
|
TextureConfig config(ENCODING_TEXTURE_WIDTH, ENCODING_TEXTURE_HEIGHT, 1, 1,
|
||||||
|
@ -35,8 +35,8 @@ public:
|
|||||||
|
|
||||||
// Applies palette to dst_entry, using indices from src_entry.
|
// Applies palette to dst_entry, using indices from src_entry.
|
||||||
void ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
void ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
||||||
TextureCache::TCacheEntry* src_entry, VkRenderPass render_pass,
|
TextureCache::TCacheEntry* src_entry, const void* palette,
|
||||||
const void* palette, TLUTFormat palette_format);
|
TLUTFormat palette_format);
|
||||||
|
|
||||||
// Uses an encoding shader to copy src_texture to dest_ptr.
|
// Uses an encoding shader to copy src_texture to dest_ptr.
|
||||||
// NOTE: Executes the current command buffer.
|
// NOTE: Executes the current command buffer.
|
||||||
@ -76,7 +76,6 @@ private:
|
|||||||
VkShaderModule CompileEncodingShader(const EFBCopyParams& params);
|
VkShaderModule CompileEncodingShader(const EFBCopyParams& params);
|
||||||
VkShaderModule GetEncodingShader(const EFBCopyParams& params);
|
VkShaderModule GetEncodingShader(const EFBCopyParams& params);
|
||||||
|
|
||||||
bool CreateEncodingRenderPass();
|
|
||||||
bool CreateEncodingTexture();
|
bool CreateEncodingTexture();
|
||||||
bool CreateDecodingTexture();
|
bool CreateDecodingTexture();
|
||||||
|
|
||||||
@ -109,7 +108,6 @@ private:
|
|||||||
std::map<EFBCopyParams, VkShaderModule> m_encoding_shaders;
|
std::map<EFBCopyParams, VkShaderModule> m_encoding_shaders;
|
||||||
std::unique_ptr<AbstractTexture> m_encoding_render_texture;
|
std::unique_ptr<AbstractTexture> m_encoding_render_texture;
|
||||||
std::unique_ptr<AbstractStagingTexture> m_encoding_readback_texture;
|
std::unique_ptr<AbstractStagingTexture> m_encoding_readback_texture;
|
||||||
VkRenderPass m_encoding_render_pass = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
// Texture decoding - GX format in memory->RGBA8
|
// Texture decoding - GX format in memory->RGBA8
|
||||||
struct TextureDecodingPipeline
|
struct TextureDecodingPipeline
|
||||||
|
@ -56,11 +56,13 @@ std::unique_ptr<VKTexture> VKTexture::Create(const TextureConfig& tex_config)
|
|||||||
if (tex_config.rendertarget)
|
if (tex_config.rendertarget)
|
||||||
{
|
{
|
||||||
VkImageView framebuffer_attachments[] = {texture->GetView()};
|
VkImageView framebuffer_attachments[] = {texture->GetView()};
|
||||||
|
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||||
|
texture->GetFormat(), VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
VkFramebufferCreateInfo framebuffer_info = {
|
VkFramebufferCreateInfo framebuffer_info = {
|
||||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
nullptr,
|
nullptr,
|
||||||
0,
|
0,
|
||||||
TextureCache::GetInstance()->GetTextureCopyRenderPass(),
|
render_pass,
|
||||||
static_cast<u32>(ArraySize(framebuffer_attachments)),
|
static_cast<u32>(ArraySize(framebuffer_attachments)),
|
||||||
framebuffer_attachments,
|
framebuffer_attachments,
|
||||||
texture->GetWidth(),
|
texture->GetWidth(),
|
||||||
@ -175,9 +177,10 @@ void VKTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
|
|||||||
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
|
||||||
|
VkRenderPass render_pass = g_object_cache->GetRenderPass(
|
||||||
|
m_texture->GetFormat(), VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||||
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass,
|
||||||
TextureCache::GetInstance()->GetTextureCopyRenderPass(),
|
|
||||||
g_shader_cache->GetPassthroughVertexShader(),
|
g_shader_cache->GetPassthroughVertexShader(),
|
||||||
g_shader_cache->GetPassthroughGeometryShader(),
|
g_shader_cache->GetPassthroughGeometryShader(),
|
||||||
TextureCache::GetInstance()->GetCopyShader());
|
TextureCache::GetInstance()->GetCopyShader());
|
||||||
|
@ -186,6 +186,25 @@ bool VideoBackend::Initialize(void* window_handle)
|
|||||||
// With the backend information populated, we can now initialize videocommon.
|
// With the backend information populated, we can now initialize videocommon.
|
||||||
InitializeShared();
|
InitializeShared();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
if (!g_command_buffer_mgr->Initialize())
|
||||||
|
{
|
||||||
|
PanicAlert("Failed to create Vulkan command buffers");
|
||||||
|
Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remaining classes are also dependent on object/shader cache.
|
||||||
|
g_object_cache = std::make_unique<ObjectCache>();
|
||||||
|
g_shader_cache = std::make_unique<ShaderCache>();
|
||||||
|
if (!g_object_cache->Initialize() || !g_shader_cache->Initialize())
|
||||||
|
{
|
||||||
|
PanicAlert("Failed to initialize Vulkan object cache.");
|
||||||
|
Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Create swap chain. This has to be done early so that the target size is correct for auto-scale.
|
// Create swap chain. This has to be done early so that the target size is correct for auto-scale.
|
||||||
std::unique_ptr<SwapChain> swap_chain;
|
std::unique_ptr<SwapChain> swap_chain;
|
||||||
if (surface != VK_NULL_HANDLE)
|
if (surface != VK_NULL_HANDLE)
|
||||||
@ -199,39 +218,19 @@ bool VideoBackend::Initialize(void* window_handle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
|
||||||
if (!g_command_buffer_mgr->Initialize())
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to create Vulkan command buffers");
|
|
||||||
Shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create main wrapper instances.
|
// Create main wrapper instances.
|
||||||
g_object_cache = std::make_unique<ObjectCache>();
|
|
||||||
g_shader_cache = std::make_unique<ShaderCache>();
|
|
||||||
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));
|
||||||
|
g_vertex_manager = std::make_unique<VertexManager>();
|
||||||
|
g_texture_cache = std::make_unique<TextureCache>();
|
||||||
|
g_perf_query = std::make_unique<PerfQuery>();
|
||||||
|
|
||||||
// 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() || !g_shader_cache->Initialize() ||
|
if (!StateTracker::CreateInstance() || !FramebufferManager::GetInstance()->Initialize() ||
|
||||||
!StateTracker::CreateInstance() || !FramebufferManager::GetInstance()->Initialize() ||
|
!Renderer::GetInstance()->Initialize() || !VertexManager::GetInstance()->Initialize() ||
|
||||||
!Renderer::GetInstance()->Initialize())
|
!TextureCache::GetInstance()->Initialize() || !PerfQuery::GetInstance()->Initialize())
|
||||||
{
|
|
||||||
PanicAlert("Failed to initialize Vulkan classes.");
|
|
||||||
Shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create remaining wrapper instances.
|
|
||||||
g_vertex_manager = std::make_unique<VertexManager>();
|
|
||||||
g_texture_cache = std::make_unique<TextureCache>();
|
|
||||||
g_perf_query = std::make_unique<PerfQuery>();
|
|
||||||
if (!VertexManager::GetInstance()->Initialize() || !TextureCache::GetInstance()->Initialize() ||
|
|
||||||
!PerfQuery::GetInstance()->Initialize())
|
|
||||||
{
|
{
|
||||||
PanicAlert("Failed to initialize Vulkan classes.");
|
PanicAlert("Failed to initialize Vulkan classes.");
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user