mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-04-29 06:49:24 -04:00
Vulkan: Improve post-shutdown cleanup and minor improvements (#1401)
This commit is contained in:
parent
4f9eea07e0
commit
e834515f43
15 changed files with 190 additions and 118 deletions
|
@ -485,6 +485,9 @@ void LatteShaderCache_Load()
|
||||||
g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureDRCId);
|
g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureDRCId);
|
||||||
|
|
||||||
g_bootSndPlayer.FadeOutSound();
|
g_bootSndPlayer.FadeOutSound();
|
||||||
|
|
||||||
|
if(Latte_GetStopSignal())
|
||||||
|
LatteThread_Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateFunc, bool isPipelines)
|
void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateFunc, bool isPipelines)
|
||||||
|
@ -625,8 +628,6 @@ void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId)
|
||||||
g_shaderCacheLoaderState.loadedPipelines = 0;
|
g_shaderCacheLoaderState.loadedPipelines = 0;
|
||||||
LatteShaderCache_ShowProgress(LatteShaderCache_updatePipelineLoadingProgress, true);
|
LatteShaderCache_ShowProgress(LatteShaderCache_updatePipelineLoadingProgress, true);
|
||||||
pipelineCache.EndLoading();
|
pipelineCache.EndLoading();
|
||||||
if(Latte_GetStopSignal())
|
|
||||||
LatteThread_Exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LatteShaderCache_updatePipelineLoadingProgress()
|
bool LatteShaderCache_updatePipelineLoadingProgress()
|
||||||
|
|
|
@ -257,6 +257,7 @@ void LatteThread_Exit()
|
||||||
LatteSHRC_UnloadAll();
|
LatteSHRC_UnloadAll();
|
||||||
// close disk cache
|
// close disk cache
|
||||||
LatteShaderCache_Close();
|
LatteShaderCache_Close();
|
||||||
|
RendererOutputShader::ShutdownStatic();
|
||||||
// destroy renderer but make sure that g_renderer remains valid until the destructor has finished
|
// destroy renderer but make sure that g_renderer remains valid until the destructor has finished
|
||||||
if (g_renderer)
|
if (g_renderer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -118,8 +118,8 @@ RendererOutputShader::RendererOutputShader(const std::string& vertex_source, con
|
||||||
{
|
{
|
||||||
auto finalFragmentSrc = PrependFragmentPreamble(fragment_source);
|
auto finalFragmentSrc = PrependFragmentPreamble(fragment_source);
|
||||||
|
|
||||||
m_vertex_shader = g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false);
|
m_vertex_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false));
|
||||||
m_fragment_shader = g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false);
|
m_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false));
|
||||||
|
|
||||||
m_vertex_shader->PreponeCompilation(true);
|
m_vertex_shader->PreponeCompilation(true);
|
||||||
m_fragment_shader->PreponeCompilation(true);
|
m_fragment_shader->PreponeCompilation(true);
|
||||||
|
@ -169,8 +169,8 @@ void RendererOutputShader::SetUniformParameters(const LatteTextureView& texture_
|
||||||
shader->SetUniform2fv(locations.m_loc_outputResolution, res, 1);
|
shader->SetUniform2fv(locations.m_loc_outputResolution, res, 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
setUniforms(m_vertex_shader, m_uniformLocations[0]);
|
setUniforms(m_vertex_shader.get(), m_uniformLocations[0]);
|
||||||
setUniforms(m_fragment_shader, m_uniformLocations[1]);
|
setUniforms(m_fragment_shader.get(), m_uniformLocations[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererOutputShader* RendererOutputShader::s_copy_shader;
|
RendererOutputShader* RendererOutputShader::s_copy_shader;
|
||||||
|
@ -325,3 +325,15 @@ void RendererOutputShader::InitializeStatic()
|
||||||
s_hermit_shader = new RendererOutputShader(vertex_source, s_hermite_shader_source);
|
s_hermit_shader = new RendererOutputShader(vertex_source, s_hermite_shader_source);
|
||||||
s_hermit_shader_ud = new RendererOutputShader(vertex_source_ud, s_hermite_shader_source);
|
s_hermit_shader_ud = new RendererOutputShader(vertex_source_ud, s_hermite_shader_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererOutputShader::ShutdownStatic()
|
||||||
|
{
|
||||||
|
delete s_copy_shader;
|
||||||
|
delete s_copy_shader_ud;
|
||||||
|
|
||||||
|
delete s_bicubic_shader;
|
||||||
|
delete s_bicubic_shader_ud;
|
||||||
|
|
||||||
|
delete s_hermit_shader;
|
||||||
|
delete s_hermit_shader_ud;
|
||||||
|
}
|
||||||
|
|
|
@ -21,15 +21,16 @@ public:
|
||||||
|
|
||||||
RendererShader* GetVertexShader() const
|
RendererShader* GetVertexShader() const
|
||||||
{
|
{
|
||||||
return m_vertex_shader;
|
return m_vertex_shader.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererShader* GetFragmentShader() const
|
RendererShader* GetFragmentShader() const
|
||||||
{
|
{
|
||||||
return m_fragment_shader;
|
return m_fragment_shader.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitializeStatic();
|
static void InitializeStatic();
|
||||||
|
static void ShutdownStatic();
|
||||||
|
|
||||||
static RendererOutputShader* s_copy_shader;
|
static RendererOutputShader* s_copy_shader;
|
||||||
static RendererOutputShader* s_copy_shader_ud;
|
static RendererOutputShader* s_copy_shader_ud;
|
||||||
|
@ -46,8 +47,8 @@ public:
|
||||||
static std::string PrependFragmentPreamble(const std::string& shaderSrc);
|
static std::string PrependFragmentPreamble(const std::string& shaderSrc);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RendererShader* m_vertex_shader;
|
std::unique_ptr<RendererShader> m_vertex_shader;
|
||||||
RendererShader* m_fragment_shader;
|
std::unique_ptr<RendererShader> m_fragment_shader;
|
||||||
|
|
||||||
struct UniformLocations
|
struct UniformLocations
|
||||||
{
|
{
|
||||||
|
|
|
@ -211,6 +211,9 @@ RendererShaderVk::~RendererShaderVk()
|
||||||
{
|
{
|
||||||
while (!list_pipelineInfo.empty())
|
while (!list_pipelineInfo.empty())
|
||||||
delete list_pipelineInfo[0];
|
delete list_pipelineInfo[0];
|
||||||
|
|
||||||
|
VkDevice vkDev = VulkanRenderer::GetInstance()->GetLogicalDevice();
|
||||||
|
vkDestroyShaderModule(vkDev, m_shader_module, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererShaderVk::Init()
|
void RendererShaderVk::Init()
|
||||||
|
|
|
@ -60,7 +60,7 @@ void SwapchainInfoVk::Create()
|
||||||
VkAttachmentDescription colorAttachment = {};
|
VkAttachmentDescription colorAttachment = {};
|
||||||
colorAttachment.format = m_surfaceFormat.format;
|
colorAttachment.format = m_surfaceFormat.format;
|
||||||
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
|
|
@ -70,6 +70,7 @@ struct SwapchainInfoVk
|
||||||
VkSurfaceFormatKHR m_surfaceFormat{};
|
VkSurfaceFormatKHR m_surfaceFormat{};
|
||||||
VkSwapchainKHR m_swapchain{};
|
VkSwapchainKHR m_swapchain{};
|
||||||
Vector2i m_desiredExtent{};
|
Vector2i m_desiredExtent{};
|
||||||
|
VkExtent2D m_actualExtent{};
|
||||||
uint32 swapchainImageIndex = (uint32)-1;
|
uint32 swapchainImageIndex = (uint32)-1;
|
||||||
uint64 m_presentId = 1;
|
uint64 m_presentId = 1;
|
||||||
uint64 m_queueDepth = 0; // number of frames with pending presentation requests
|
uint64 m_queueDepth = 0; // number of frames with pending presentation requests
|
||||||
|
@ -92,5 +93,4 @@ private:
|
||||||
VkSemaphore m_currentSemaphore = VK_NULL_HANDLE;
|
VkSemaphore m_currentSemaphore = VK_NULL_HANDLE;
|
||||||
|
|
||||||
std::array<uint32, 2> m_swapchainQueueFamilyIndices;
|
std::array<uint32, 2> m_swapchainQueueFamilyIndices;
|
||||||
VkExtent2D m_actualExtent{};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,14 @@
|
||||||
|
|
||||||
/* VKRSynchronizedMemoryBuffer */
|
/* VKRSynchronizedMemoryBuffer */
|
||||||
|
|
||||||
|
VKRSynchronizedRingAllocator::~VKRSynchronizedRingAllocator()
|
||||||
|
{
|
||||||
|
for(auto& buf : m_buffers)
|
||||||
|
{
|
||||||
|
m_vkrMemMgr->DeleteBuffer(buf.vk_buffer, buf.vk_mem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VKRSynchronizedRingAllocator::addUploadBufferSyncPoint(AllocatorBuffer_t& buffer, uint32 offset)
|
void VKRSynchronizedRingAllocator::addUploadBufferSyncPoint(AllocatorBuffer_t& buffer, uint32 offset)
|
||||||
{
|
{
|
||||||
auto cmdBufferId = m_vkr->GetCurrentCommandBufferId();
|
auto cmdBufferId = m_vkr->GetCurrentCommandBufferId();
|
||||||
|
@ -233,6 +241,15 @@ void VKRSynchronizedHeapAllocator::GetStats(uint32& numBuffers, size_t& totalBuf
|
||||||
|
|
||||||
/* VkTextureChunkedHeap */
|
/* VkTextureChunkedHeap */
|
||||||
|
|
||||||
|
VkTextureChunkedHeap::~VkTextureChunkedHeap()
|
||||||
|
{
|
||||||
|
VkDevice device = VulkanRenderer::GetInstance()->GetLogicalDevice();
|
||||||
|
for (auto& i : m_list_chunkInfo)
|
||||||
|
{
|
||||||
|
vkFreeMemory(device, i.mem, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32 VkTextureChunkedHeap::allocateNewChunk(uint32 chunkIndex, uint32 minimumAllocationSize)
|
uint32 VkTextureChunkedHeap::allocateNewChunk(uint32 chunkIndex, uint32 minimumAllocationSize)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(m_list_chunkInfo.size() == chunkIndex);
|
cemu_assert_debug(m_list_chunkInfo.size() == chunkIndex);
|
||||||
|
@ -310,11 +327,11 @@ VKRBuffer* VKRBuffer::Create(VKR_BUFFER_TYPE bufferType, size_t bufferSize, VkMe
|
||||||
VkDeviceMemory bufferMemory;
|
VkDeviceMemory bufferMemory;
|
||||||
bool allocSuccess;
|
bool allocSuccess;
|
||||||
if (bufferType == VKR_BUFFER_TYPE::STAGING)
|
if (bufferType == VKR_BUFFER_TYPE::STAGING)
|
||||||
allocSuccess = memMgr->CreateBuffer2(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, properties, buffer, bufferMemory);
|
allocSuccess = memMgr->CreateBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, properties, buffer, bufferMemory);
|
||||||
else if (bufferType == VKR_BUFFER_TYPE::INDEX)
|
else if (bufferType == VKR_BUFFER_TYPE::INDEX)
|
||||||
allocSuccess = memMgr->CreateBuffer2(bufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, properties, buffer, bufferMemory);
|
allocSuccess = memMgr->CreateBuffer(bufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, properties, buffer, bufferMemory);
|
||||||
else if (bufferType == VKR_BUFFER_TYPE::STRIDE)
|
else if (bufferType == VKR_BUFFER_TYPE::STRIDE)
|
||||||
allocSuccess = memMgr->CreateBuffer2(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, properties, buffer, bufferMemory);
|
allocSuccess = memMgr->CreateBuffer(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, properties, buffer, bufferMemory);
|
||||||
else
|
else
|
||||||
cemu_assert_debug(false);
|
cemu_assert_debug(false);
|
||||||
if (!allocSuccess)
|
if (!allocSuccess)
|
||||||
|
@ -363,28 +380,14 @@ uint32 VkBufferChunkedHeap::allocateNewChunk(uint32 chunkIndex, uint32 minimumAl
|
||||||
return allocationSize;
|
return allocationSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t VKRMemoryManager::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) const
|
bool VKRMemoryManager::FindMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties, uint32& memoryIndex) const
|
||||||
{
|
|
||||||
VkPhysicalDeviceMemoryProperties memProperties;
|
|
||||||
vkGetPhysicalDeviceMemoryProperties(m_vkr->GetPhysicalDevice(), &memProperties);
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
|
|
||||||
{
|
|
||||||
if ((typeFilter & (1 << i)) != 0 && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
m_vkr->UnrecoverableError(fmt::format("failed to find suitable memory type ({0:#08x} {1:#08x})", typeFilter, properties).c_str());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VKRMemoryManager::FindMemoryType2(uint32 typeFilter, VkMemoryPropertyFlags properties, uint32& memoryIndex) const
|
|
||||||
{
|
{
|
||||||
VkPhysicalDeviceMemoryProperties memProperties;
|
VkPhysicalDeviceMemoryProperties memProperties;
|
||||||
vkGetPhysicalDeviceMemoryProperties(m_vkr->GetPhysicalDevice(), &memProperties);
|
vkGetPhysicalDeviceMemoryProperties(m_vkr->GetPhysicalDevice(), &memProperties);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
|
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
|
||||||
{
|
{
|
||||||
if (typeFilter & (1 << i) && memProperties.memoryTypes[i].propertyFlags == properties)
|
if (typeFilter & (1 << i) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||||
{
|
{
|
||||||
memoryIndex = i;
|
memoryIndex = i;
|
||||||
return true;
|
return true;
|
||||||
|
@ -455,31 +458,7 @@ size_t VKRMemoryManager::GetTotalMemoryForBufferType(VkBufferUsageFlags usage, V
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKRMemoryManager::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const
|
bool VKRMemoryManager::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const
|
||||||
{
|
|
||||||
VkBufferCreateInfo bufferInfo{};
|
|
||||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
||||||
bufferInfo.usage = usage;
|
|
||||||
bufferInfo.size = size;
|
|
||||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
if (vkCreateBuffer(m_vkr->GetLogicalDevice(), &bufferInfo, nullptr, &buffer) != VK_SUCCESS)
|
|
||||||
m_vkr->UnrecoverableError("Failed to create buffer");
|
|
||||||
|
|
||||||
VkMemoryRequirements memRequirements;
|
|
||||||
vkGetBufferMemoryRequirements(m_vkr->GetLogicalDevice(), buffer, &memRequirements);
|
|
||||||
|
|
||||||
VkMemoryAllocateInfo allocInfo{};
|
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
||||||
allocInfo.allocationSize = memRequirements.size;
|
|
||||||
allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits, properties);
|
|
||||||
|
|
||||||
if (vkAllocateMemory(m_vkr->GetLogicalDevice(), &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS)
|
|
||||||
m_vkr->UnrecoverableError("Failed to allocate buffer memory");
|
|
||||||
if (vkBindBufferMemory(m_vkr->GetLogicalDevice(), buffer, bufferMemory, 0) != VK_SUCCESS)
|
|
||||||
m_vkr->UnrecoverableError("Failed to bind buffer memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VKRMemoryManager::CreateBuffer2(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const
|
|
||||||
{
|
{
|
||||||
VkBufferCreateInfo bufferInfo{};
|
VkBufferCreateInfo bufferInfo{};
|
||||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
@ -488,7 +467,7 @@ bool VKRMemoryManager::CreateBuffer2(VkDeviceSize size, VkBufferUsageFlags usage
|
||||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
if (vkCreateBuffer(m_vkr->GetLogicalDevice(), &bufferInfo, nullptr, &buffer) != VK_SUCCESS)
|
if (vkCreateBuffer(m_vkr->GetLogicalDevice(), &bufferInfo, nullptr, &buffer) != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
cemuLog_log(LogType::Force, "Failed to create buffer (CreateBuffer2)");
|
cemuLog_log(LogType::Force, "Failed to create buffer (CreateBuffer)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +477,7 @@ bool VKRMemoryManager::CreateBuffer2(VkDeviceSize size, VkBufferUsageFlags usage
|
||||||
VkMemoryAllocateInfo allocInfo{};
|
VkMemoryAllocateInfo allocInfo{};
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
allocInfo.allocationSize = memRequirements.size;
|
allocInfo.allocationSize = memRequirements.size;
|
||||||
if (!FindMemoryType2(memRequirements.memoryTypeBits, properties, allocInfo.memoryTypeIndex))
|
if (!FindMemoryType(memRequirements.memoryTypeBits, properties, allocInfo.memoryTypeIndex))
|
||||||
{
|
{
|
||||||
vkDestroyBuffer(m_vkr->GetLogicalDevice(), buffer, nullptr);
|
vkDestroyBuffer(m_vkr->GetLogicalDevice(), buffer, nullptr);
|
||||||
return false;
|
return false;
|
||||||
|
@ -511,7 +490,7 @@ bool VKRMemoryManager::CreateBuffer2(VkDeviceSize size, VkBufferUsageFlags usage
|
||||||
if (vkBindBufferMemory(m_vkr->GetLogicalDevice(), buffer, bufferMemory, 0) != VK_SUCCESS)
|
if (vkBindBufferMemory(m_vkr->GetLogicalDevice(), buffer, bufferMemory, 0) != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
vkDestroyBuffer(m_vkr->GetLogicalDevice(), buffer, nullptr);
|
vkDestroyBuffer(m_vkr->GetLogicalDevice(), buffer, nullptr);
|
||||||
cemuLog_log(LogType::Force, "Failed to bind buffer (CreateBuffer2)");
|
cemuLog_log(LogType::Force, "Failed to bind buffer (CreateBuffer)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -533,7 +512,7 @@ bool VKRMemoryManager::CreateBufferFromHostMemory(void* hostPointer, VkDeviceSiz
|
||||||
|
|
||||||
if (vkCreateBuffer(m_vkr->GetLogicalDevice(), &bufferInfo, nullptr, &buffer) != VK_SUCCESS)
|
if (vkCreateBuffer(m_vkr->GetLogicalDevice(), &bufferInfo, nullptr, &buffer) != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
cemuLog_log(LogType::Force, "Failed to create buffer (CreateBuffer2)");
|
cemuLog_log(LogType::Force, "Failed to create buffer (CreateBuffer)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,7 +533,7 @@ bool VKRMemoryManager::CreateBufferFromHostMemory(void* hostPointer, VkDeviceSiz
|
||||||
|
|
||||||
allocInfo.pNext = &importHostMem;
|
allocInfo.pNext = &importHostMem;
|
||||||
|
|
||||||
if (!FindMemoryType2(memRequirements.memoryTypeBits, properties, allocInfo.memoryTypeIndex))
|
if (!FindMemoryType(memRequirements.memoryTypeBits, properties, allocInfo.memoryTypeIndex))
|
||||||
{
|
{
|
||||||
vkDestroyBuffer(m_vkr->GetLogicalDevice(), buffer, nullptr);
|
vkDestroyBuffer(m_vkr->GetLogicalDevice(), buffer, nullptr);
|
||||||
return false;
|
return false;
|
||||||
|
@ -598,7 +577,7 @@ VkImageMemAllocation* VKRMemoryManager::imageMemoryAllocate(VkImage image)
|
||||||
map_textureHeap.emplace(typeFilter, texHeap);
|
map_textureHeap.emplace(typeFilter, texHeap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
texHeap = it->second;
|
texHeap = it->second.get();
|
||||||
|
|
||||||
// alloc mem from heap
|
// alloc mem from heap
|
||||||
uint32 allocationSize = (uint32)memRequirements.size;
|
uint32 allocationSize = (uint32)memRequirements.size;
|
||||||
|
|
|
@ -48,6 +48,7 @@ class VkTextureChunkedHeap : private ChunkedHeap<>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VkTextureChunkedHeap(class VKRMemoryManager* memoryManager, uint32 typeFilter) : m_vkrMemoryManager(memoryManager), m_typeFilter(typeFilter) { };
|
VkTextureChunkedHeap(class VKRMemoryManager* memoryManager, uint32 typeFilter) : m_vkrMemoryManager(memoryManager), m_typeFilter(typeFilter) { };
|
||||||
|
~VkTextureChunkedHeap();
|
||||||
|
|
||||||
struct ChunkInfo
|
struct ChunkInfo
|
||||||
{
|
{
|
||||||
|
@ -148,6 +149,7 @@ class VKRSynchronizedRingAllocator
|
||||||
public:
|
public:
|
||||||
VKRSynchronizedRingAllocator(class VulkanRenderer* vkRenderer, class VKRMemoryManager* vkMemoryManager, VKR_BUFFER_TYPE bufferType, uint32 minimumBufferAllocSize) : m_vkr(vkRenderer), m_vkrMemMgr(vkMemoryManager), m_bufferType(bufferType), m_minimumBufferAllocSize(minimumBufferAllocSize) {};
|
VKRSynchronizedRingAllocator(class VulkanRenderer* vkRenderer, class VKRMemoryManager* vkMemoryManager, VKR_BUFFER_TYPE bufferType, uint32 minimumBufferAllocSize) : m_vkr(vkRenderer), m_vkrMemMgr(vkMemoryManager), m_bufferType(bufferType), m_minimumBufferAllocSize(minimumBufferAllocSize) {};
|
||||||
VKRSynchronizedRingAllocator(const VKRSynchronizedRingAllocator&) = delete; // disallow copy
|
VKRSynchronizedRingAllocator(const VKRSynchronizedRingAllocator&) = delete; // disallow copy
|
||||||
|
~VKRSynchronizedRingAllocator();
|
||||||
|
|
||||||
struct BufferSyncPoint_t
|
struct BufferSyncPoint_t
|
||||||
{
|
{
|
||||||
|
@ -256,7 +258,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// texture memory management
|
// texture memory management
|
||||||
std::unordered_map<uint32, VkTextureChunkedHeap*> map_textureHeap; // one heap per memory type
|
std::unordered_map<uint32, std::unique_ptr<VkTextureChunkedHeap>> map_textureHeap; // one heap per memory type
|
||||||
std::vector<uint8> m_textureUploadBuffer;
|
std::vector<uint8> m_textureUploadBuffer;
|
||||||
|
|
||||||
// texture upload buffer
|
// texture upload buffer
|
||||||
|
@ -286,9 +288,7 @@ public:
|
||||||
m_vertexStrideMetalBuffer.CleanupBuffer(latestFinishedCommandBufferId);
|
m_vertexStrideMetalBuffer.CleanupBuffer(latestFinishedCommandBufferId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// memory helpers
|
bool FindMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties, uint32& memoryIndex) const; // searches for exact properties. Can gracefully fail without throwing exception (returns false)
|
||||||
uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) const;
|
|
||||||
bool FindMemoryType2(uint32 typeFilter, VkMemoryPropertyFlags properties, uint32& memoryIndex) const; // searches for exact properties. Can gracefully fail without throwing exception (returns false)
|
|
||||||
std::vector<uint32> FindMemoryTypes(uint32_t typeFilter, VkMemoryPropertyFlags properties) const;
|
std::vector<uint32> FindMemoryTypes(uint32_t typeFilter, VkMemoryPropertyFlags properties) const;
|
||||||
|
|
||||||
// image memory allocation
|
// image memory allocation
|
||||||
|
@ -298,8 +298,7 @@ public:
|
||||||
// buffer management
|
// buffer management
|
||||||
size_t GetTotalMemoryForBufferType(VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, size_t minimumBufferSize = 16 * 1024 * 1024);
|
size_t GetTotalMemoryForBufferType(VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, size_t minimumBufferSize = 16 * 1024 * 1024);
|
||||||
|
|
||||||
void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const;
|
bool CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const; // same as CreateBuffer but doesn't throw exception on failure
|
||||||
bool CreateBuffer2(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const; // same as CreateBuffer but doesn't throw exception on failure
|
|
||||||
bool CreateBufferFromHostMemory(void* hostPointer, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const;
|
bool CreateBufferFromHostMemory(void* hostPointer, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const;
|
||||||
|
|
||||||
void DeleteBuffer(VkBuffer& buffer, VkDeviceMemory& deviceMem) const;
|
void DeleteBuffer(VkBuffer& buffer, VkDeviceMemory& deviceMem) const;
|
||||||
|
|
|
@ -165,6 +165,7 @@ VKFUNC_DEVICE(vkCmdDraw);
|
||||||
VKFUNC_DEVICE(vkCmdCopyBufferToImage);
|
VKFUNC_DEVICE(vkCmdCopyBufferToImage);
|
||||||
VKFUNC_DEVICE(vkCmdCopyImageToBuffer);
|
VKFUNC_DEVICE(vkCmdCopyImageToBuffer);
|
||||||
VKFUNC_DEVICE(vkCmdClearColorImage);
|
VKFUNC_DEVICE(vkCmdClearColorImage);
|
||||||
|
VKFUNC_DEVICE(vkCmdClearAttachments);
|
||||||
VKFUNC_DEVICE(vkCmdBindIndexBuffer);
|
VKFUNC_DEVICE(vkCmdBindIndexBuffer);
|
||||||
VKFUNC_DEVICE(vkCmdBindVertexBuffers);
|
VKFUNC_DEVICE(vkCmdBindVertexBuffers);
|
||||||
VKFUNC_DEVICE(vkCmdDrawIndexed);
|
VKFUNC_DEVICE(vkCmdDrawIndexed);
|
||||||
|
@ -198,6 +199,7 @@ VKFUNC_DEVICE(vkCmdEndTransformFeedbackEXT);
|
||||||
|
|
||||||
// query
|
// query
|
||||||
VKFUNC_DEVICE(vkCreateQueryPool);
|
VKFUNC_DEVICE(vkCreateQueryPool);
|
||||||
|
VKFUNC_DEVICE(vkDestroyQueryPool);
|
||||||
VKFUNC_DEVICE(vkCmdResetQueryPool);
|
VKFUNC_DEVICE(vkCmdResetQueryPool);
|
||||||
VKFUNC_DEVICE(vkCmdBeginQuery);
|
VKFUNC_DEVICE(vkCmdBeginQuery);
|
||||||
VKFUNC_DEVICE(vkCmdEndQuery);
|
VKFUNC_DEVICE(vkCmdEndQuery);
|
||||||
|
@ -236,6 +238,7 @@ VKFUNC_DEVICE(vkAllocateDescriptorSets);
|
||||||
VKFUNC_DEVICE(vkFreeDescriptorSets);
|
VKFUNC_DEVICE(vkFreeDescriptorSets);
|
||||||
VKFUNC_DEVICE(vkUpdateDescriptorSets);
|
VKFUNC_DEVICE(vkUpdateDescriptorSets);
|
||||||
VKFUNC_DEVICE(vkCreateDescriptorPool);
|
VKFUNC_DEVICE(vkCreateDescriptorPool);
|
||||||
|
VKFUNC_DEVICE(vkDestroyDescriptorPool);
|
||||||
VKFUNC_DEVICE(vkDestroyDescriptorSetLayout);
|
VKFUNC_DEVICE(vkDestroyDescriptorSetLayout);
|
||||||
|
|
||||||
#undef VKFUNC_INIT
|
#undef VKFUNC_INIT
|
||||||
|
|
|
@ -439,7 +439,7 @@ VulkanRenderer::VulkanRenderer()
|
||||||
GetDeviceFeatures();
|
GetDeviceFeatures();
|
||||||
|
|
||||||
// init memory manager
|
// init memory manager
|
||||||
memoryManager = new VKRMemoryManager(this);
|
memoryManager.reset(new VKRMemoryManager(this));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -577,15 +577,15 @@ VulkanRenderer::VulkanRenderer()
|
||||||
void* bufferPtr;
|
void* bufferPtr;
|
||||||
// init ringbuffer for uniform vars
|
// init ringbuffer for uniform vars
|
||||||
m_uniformVarBufferMemoryIsCoherent = false;
|
m_uniformVarBufferMemoryIsCoherent = false;
|
||||||
if (memoryManager->CreateBuffer2(UNIFORMVAR_RINGBUFFER_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, m_uniformVarBuffer, m_uniformVarBufferMemory))
|
if (memoryManager->CreateBuffer(UNIFORMVAR_RINGBUFFER_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, m_uniformVarBuffer, m_uniformVarBufferMemory))
|
||||||
m_uniformVarBufferMemoryIsCoherent = true;
|
m_uniformVarBufferMemoryIsCoherent = true;
|
||||||
else if (memoryManager->CreateBuffer2(UNIFORMVAR_RINGBUFFER_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_uniformVarBuffer, m_uniformVarBufferMemory))
|
else if (memoryManager->CreateBuffer(UNIFORMVAR_RINGBUFFER_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_uniformVarBuffer, m_uniformVarBufferMemory))
|
||||||
m_uniformVarBufferMemoryIsCoherent = true; // unified memory
|
m_uniformVarBufferMemoryIsCoherent = true; // unified memory
|
||||||
else if (memoryManager->CreateBuffer2(UNIFORMVAR_RINGBUFFER_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, m_uniformVarBuffer, m_uniformVarBufferMemory))
|
else if (memoryManager->CreateBuffer(UNIFORMVAR_RINGBUFFER_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, m_uniformVarBuffer, m_uniformVarBufferMemory))
|
||||||
m_uniformVarBufferMemoryIsCoherent = true;
|
m_uniformVarBufferMemoryIsCoherent = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memoryManager->CreateBuffer2(UNIFORMVAR_RINGBUFFER_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, m_uniformVarBuffer, m_uniformVarBufferMemory);
|
memoryManager->CreateBuffer(UNIFORMVAR_RINGBUFFER_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, m_uniformVarBuffer, m_uniformVarBufferMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_uniformVarBufferMemoryIsCoherent)
|
if (!m_uniformVarBufferMemoryIsCoherent)
|
||||||
|
@ -628,6 +628,31 @@ VulkanRenderer::~VulkanRenderer()
|
||||||
m_pipeline_cache_semaphore.notify();
|
m_pipeline_cache_semaphore.notify();
|
||||||
m_pipeline_cache_save_thread.join();
|
m_pipeline_cache_save_thread.join();
|
||||||
|
|
||||||
|
vkDestroyPipelineCache(m_logicalDevice, m_pipeline_cache, nullptr);
|
||||||
|
|
||||||
|
if(!m_backbufferBlitDescriptorSetCache.empty())
|
||||||
|
{
|
||||||
|
std::vector<VkDescriptorSet> freeVector;
|
||||||
|
freeVector.reserve(m_backbufferBlitDescriptorSetCache.size());
|
||||||
|
std::transform(m_backbufferBlitDescriptorSetCache.begin(), m_backbufferBlitDescriptorSetCache.end(), std::back_inserter(freeVector), [](auto& i) {
|
||||||
|
return i.second;
|
||||||
|
});
|
||||||
|
vkFreeDescriptorSets(m_logicalDevice, m_descriptorPool, freeVector.size(), freeVector.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
vkDestroyDescriptorPool(m_logicalDevice, m_descriptorPool, nullptr);
|
||||||
|
|
||||||
|
for(auto& i : m_backbufferBlitPipelineCache)
|
||||||
|
{
|
||||||
|
vkDestroyPipeline(m_logicalDevice, i.second, nullptr);
|
||||||
|
}
|
||||||
|
m_backbufferBlitPipelineCache = {};
|
||||||
|
|
||||||
|
if(m_occlusionQueries.queryPool != VK_NULL_HANDLE)
|
||||||
|
vkDestroyQueryPool(m_logicalDevice, m_occlusionQueries.queryPool, nullptr);
|
||||||
|
|
||||||
|
vkDestroyDescriptorSetLayout(m_logicalDevice, m_swapchainDescriptorSetLayout, nullptr);
|
||||||
|
|
||||||
// shut down imgui
|
// shut down imgui
|
||||||
ImGui_ImplVulkan_Shutdown();
|
ImGui_ImplVulkan_Shutdown();
|
||||||
|
|
||||||
|
@ -640,10 +665,6 @@ VulkanRenderer::~VulkanRenderer()
|
||||||
memoryManager->DeleteBuffer(m_xfbRingBuffer, m_xfbRingBufferMemory);
|
memoryManager->DeleteBuffer(m_xfbRingBuffer, m_xfbRingBufferMemory);
|
||||||
memoryManager->DeleteBuffer(m_occlusionQueries.bufferQueryResults, m_occlusionQueries.memoryQueryResults);
|
memoryManager->DeleteBuffer(m_occlusionQueries.bufferQueryResults, m_occlusionQueries.memoryQueryResults);
|
||||||
memoryManager->DeleteBuffer(m_bufferCache, m_bufferCacheMemory);
|
memoryManager->DeleteBuffer(m_bufferCache, m_bufferCacheMemory);
|
||||||
// texture memory
|
|
||||||
// todo
|
|
||||||
// upload buffers
|
|
||||||
// todo
|
|
||||||
|
|
||||||
m_padSwapchainInfo = nullptr;
|
m_padSwapchainInfo = nullptr;
|
||||||
m_mainSwapchainInfo = nullptr;
|
m_mainSwapchainInfo = nullptr;
|
||||||
|
@ -666,6 +687,12 @@ VulkanRenderer::~VulkanRenderer()
|
||||||
it = VK_NULL_HANDLE;
|
it = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(auto& sem : m_commandBufferSemaphores)
|
||||||
|
{
|
||||||
|
vkDestroySemaphore(m_logicalDevice, sem, nullptr);
|
||||||
|
sem = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_pipelineLayout != VK_NULL_HANDLE)
|
if (m_pipelineLayout != VK_NULL_HANDLE)
|
||||||
vkDestroyPipelineLayout(m_logicalDevice, m_pipelineLayout, nullptr);
|
vkDestroyPipelineLayout(m_logicalDevice, m_pipelineLayout, nullptr);
|
||||||
|
|
||||||
|
@ -681,8 +708,11 @@ VulkanRenderer::~VulkanRenderer()
|
||||||
vkDestroyDebugUtilsMessengerEXT(m_instance, m_debugCallback, nullptr);
|
vkDestroyDebugUtilsMessengerEXT(m_instance, m_debugCallback, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while(!m_destructionQueue.empty())
|
||||||
|
ProcessDestructionQueue();
|
||||||
|
|
||||||
// destroy memory manager
|
// destroy memory manager
|
||||||
delete memoryManager;
|
memoryManager.reset();
|
||||||
|
|
||||||
// destroy instance, devices
|
// destroy instance, devices
|
||||||
if (m_instance != VK_NULL_HANDLE)
|
if (m_instance != VK_NULL_HANDLE)
|
||||||
|
@ -825,7 +855,14 @@ void VulkanRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool pad
|
||||||
VkMemoryAllocateInfo allocInfo{};
|
VkMemoryAllocateInfo allocInfo{};
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
allocInfo.allocationSize = memRequirements.size;
|
allocInfo.allocationSize = memRequirements.size;
|
||||||
allocInfo.memoryTypeIndex = memoryManager->FindMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
uint32 memIndex;
|
||||||
|
bool foundMemory = memoryManager->FindMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memIndex);
|
||||||
|
if(!foundMemory)
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "Screenshot request failed due to incompatible vulkan memory types.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allocInfo.memoryTypeIndex = memIndex;
|
||||||
|
|
||||||
if (vkAllocateMemory(m_logicalDevice, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS)
|
if (vkAllocateMemory(m_logicalDevice, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -1608,6 +1645,7 @@ void VulkanRenderer::Initialize()
|
||||||
|
|
||||||
void VulkanRenderer::Shutdown()
|
void VulkanRenderer::Shutdown()
|
||||||
{
|
{
|
||||||
|
DeleteFontTextures();
|
||||||
Renderer::Shutdown();
|
Renderer::Shutdown();
|
||||||
SubmitCommandBuffer();
|
SubmitCommandBuffer();
|
||||||
WaitDeviceIdle();
|
WaitDeviceIdle();
|
||||||
|
@ -1808,7 +1846,6 @@ void VulkanRenderer::ImguiEnd()
|
||||||
vkCmdEndRenderPass(m_state.currentCommandBuffer);
|
vkCmdEndRenderPass(m_state.currentCommandBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LatteTextureVk*> g_imgui_textures; // TODO manage better
|
|
||||||
ImTextureID VulkanRenderer::GenerateTexture(const std::vector<uint8>& data, const Vector2i& size)
|
ImTextureID VulkanRenderer::GenerateTexture(const std::vector<uint8>& data, const Vector2i& size)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -1838,6 +1875,7 @@ void VulkanRenderer::DeleteTexture(ImTextureID id)
|
||||||
|
|
||||||
void VulkanRenderer::DeleteFontTextures()
|
void VulkanRenderer::DeleteFontTextures()
|
||||||
{
|
{
|
||||||
|
WaitDeviceIdle();
|
||||||
ImGui_ImplVulkan_DestroyFontsTexture();
|
ImGui_ImplVulkan_DestroyFontsTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1876,7 +1914,7 @@ void VulkanRenderer::InitFirstCommandBuffer()
|
||||||
vkResetFences(m_logicalDevice, 1, &m_cmd_buffer_fences[m_commandBufferIndex]);
|
vkResetFences(m_logicalDevice, 1, &m_cmd_buffer_fences[m_commandBufferIndex]);
|
||||||
VkCommandBufferBeginInfo beginInfo{};
|
VkCommandBufferBeginInfo beginInfo{};
|
||||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
vkBeginCommandBuffer(m_state.currentCommandBuffer, &beginInfo);
|
vkBeginCommandBuffer(m_state.currentCommandBuffer, &beginInfo);
|
||||||
|
|
||||||
vkCmdSetViewport(m_state.currentCommandBuffer, 0, 1, &m_state.currentViewport);
|
vkCmdSetViewport(m_state.currentCommandBuffer, 0, 1, &m_state.currentViewport);
|
||||||
|
@ -1998,7 +2036,7 @@ void VulkanRenderer::SubmitCommandBuffer(VkSemaphore signalSemaphore, VkSemaphor
|
||||||
|
|
||||||
VkCommandBufferBeginInfo beginInfo{};
|
VkCommandBufferBeginInfo beginInfo{};
|
||||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
vkBeginCommandBuffer(m_state.currentCommandBuffer, &beginInfo);
|
vkBeginCommandBuffer(m_state.currentCommandBuffer, &beginInfo);
|
||||||
|
|
||||||
// make sure some states are set for this command buffer
|
// make sure some states are set for this command buffer
|
||||||
|
@ -2519,9 +2557,8 @@ VkPipeline VulkanRenderer::backbufferBlit_createGraphicsPipeline(VkDescriptorSet
|
||||||
hash += (uint64)(chainInfo.m_usesSRGB);
|
hash += (uint64)(chainInfo.m_usesSRGB);
|
||||||
hash += ((uint64)padView) << 1;
|
hash += ((uint64)padView) << 1;
|
||||||
|
|
||||||
static std::unordered_map<uint64, VkPipeline> s_pipeline_cache;
|
const auto it = m_backbufferBlitPipelineCache.find(hash);
|
||||||
const auto it = s_pipeline_cache.find(hash);
|
if (it != m_backbufferBlitPipelineCache.cend())
|
||||||
if (it != s_pipeline_cache.cend())
|
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
||||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||||
|
@ -2625,7 +2662,7 @@ VkPipeline VulkanRenderer::backbufferBlit_createGraphicsPipeline(VkDescriptorSet
|
||||||
throw std::runtime_error(fmt::format("Failed to create graphics pipeline: {}", result));
|
throw std::runtime_error(fmt::format("Failed to create graphics pipeline: {}", result));
|
||||||
}
|
}
|
||||||
|
|
||||||
s_pipeline_cache[hash] = pipeline;
|
m_backbufferBlitPipelineCache[hash] = pipeline;
|
||||||
m_pipeline_cache_semaphore.notify();
|
m_pipeline_cache_semaphore.notify();
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
|
@ -2922,9 +2959,6 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
|
||||||
LatteTextureViewVk* texViewVk = (LatteTextureViewVk*)texView;
|
LatteTextureViewVk* texViewVk = (LatteTextureViewVk*)texView;
|
||||||
draw_endRenderPass();
|
draw_endRenderPass();
|
||||||
|
|
||||||
if (clearBackground)
|
|
||||||
ClearColorbuffer(padView);
|
|
||||||
|
|
||||||
// barrier for input texture
|
// barrier for input texture
|
||||||
VkMemoryBarrier memoryBarrier{};
|
VkMemoryBarrier memoryBarrier{};
|
||||||
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
||||||
|
@ -2961,6 +2995,16 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
|
||||||
|
|
||||||
vkCmdBeginRenderPass(m_state.currentCommandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(m_state.currentCommandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
|
if (clearBackground)
|
||||||
|
{
|
||||||
|
VkClearAttachment clearAttachment{};
|
||||||
|
clearAttachment.clearValue = {0,0,0,0};
|
||||||
|
clearAttachment.colorAttachment = 0;
|
||||||
|
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
VkClearRect clearExtent = {{{0,0},chainInfo.m_actualExtent}, 0, 1};
|
||||||
|
vkCmdClearAttachments(m_state.currentCommandBuffer, 1, &clearAttachment, 1, &clearExtent);
|
||||||
|
}
|
||||||
|
|
||||||
vkCmdBindPipeline(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
vkCmdBindPipeline(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
m_state.currentPipeline = pipeline;
|
m_state.currentPipeline = pipeline;
|
||||||
|
|
||||||
|
@ -3025,9 +3069,8 @@ VkDescriptorSet VulkanRenderer::backbufferBlit_createDescriptorSet(VkDescriptorS
|
||||||
hash += (uint64)texViewVk->GetViewRGBA();
|
hash += (uint64)texViewVk->GetViewRGBA();
|
||||||
hash += (uint64)texViewVk->GetDefaultTextureSampler(useLinearTexFilter);
|
hash += (uint64)texViewVk->GetDefaultTextureSampler(useLinearTexFilter);
|
||||||
|
|
||||||
static std::unordered_map<uint64, VkDescriptorSet> s_set_cache;
|
const auto it = m_backbufferBlitDescriptorSetCache.find(hash);
|
||||||
const auto it = s_set_cache.find(hash);
|
if (it != m_backbufferBlitDescriptorSetCache.cend())
|
||||||
if (it != s_set_cache.cend())
|
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
||||||
VkDescriptorSetAllocateInfo allocInfo = {};
|
VkDescriptorSetAllocateInfo allocInfo = {};
|
||||||
|
@ -3058,7 +3101,7 @@ VkDescriptorSet VulkanRenderer::backbufferBlit_createDescriptorSet(VkDescriptorS
|
||||||
vkUpdateDescriptorSets(m_logicalDevice, 1, &descriptorWrites, 0, nullptr);
|
vkUpdateDescriptorSets(m_logicalDevice, 1, &descriptorWrites, 0, nullptr);
|
||||||
performanceMonitor.vk.numDescriptorSamplerTextures.increment();
|
performanceMonitor.vk.numDescriptorSamplerTextures.increment();
|
||||||
|
|
||||||
s_set_cache[hash] = result;
|
m_backbufferBlitDescriptorSetCache[hash] = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3191,7 +3234,8 @@ VkDescriptorSetInfo::~VkDescriptorSetInfo()
|
||||||
performanceMonitor.vk.numDescriptorDynUniformBuffers.decrement(statsNumDynUniformBuffers);
|
performanceMonitor.vk.numDescriptorDynUniformBuffers.decrement(statsNumDynUniformBuffers);
|
||||||
performanceMonitor.vk.numDescriptorStorageBuffers.decrement(statsNumStorageBuffers);
|
performanceMonitor.vk.numDescriptorStorageBuffers.decrement(statsNumStorageBuffers);
|
||||||
|
|
||||||
VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_vkObjDescriptorSet);
|
auto renderer = VulkanRenderer::GetInstance();
|
||||||
|
renderer->ReleaseDestructibleObject(m_vkObjDescriptorSet);
|
||||||
m_vkObjDescriptorSet = nullptr;
|
m_vkObjDescriptorSet = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,8 +137,8 @@ class VulkanRenderer : public Renderer
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// memory management
|
// memory management
|
||||||
VKRMemoryManager* memoryManager{};
|
std::unique_ptr<VKRMemoryManager> memoryManager;
|
||||||
VKRMemoryManager* GetMemoryManager() const { return memoryManager; };
|
VKRMemoryManager* GetMemoryManager() const { return memoryManager.get(); };
|
||||||
|
|
||||||
VkSupportedFormatInfo_t m_supportedFormatInfo;
|
VkSupportedFormatInfo_t m_supportedFormatInfo;
|
||||||
|
|
||||||
|
@ -583,6 +583,8 @@ private:
|
||||||
std::shared_mutex m_pipeline_cache_save_mutex;
|
std::shared_mutex m_pipeline_cache_save_mutex;
|
||||||
std::thread m_pipeline_cache_save_thread;
|
std::thread m_pipeline_cache_save_thread;
|
||||||
VkPipelineCache m_pipeline_cache{ nullptr };
|
VkPipelineCache m_pipeline_cache{ nullptr };
|
||||||
|
std::unordered_map<uint64, VkPipeline> m_backbufferBlitPipelineCache;
|
||||||
|
std::unordered_map<uint64, VkDescriptorSet> m_backbufferBlitDescriptorSetCache;
|
||||||
VkPipelineLayout m_pipelineLayout{nullptr};
|
VkPipelineLayout m_pipelineLayout{nullptr};
|
||||||
VkCommandPool m_commandPool{ nullptr };
|
VkCommandPool m_commandPool{ nullptr };
|
||||||
|
|
||||||
|
@ -860,7 +862,7 @@ private:
|
||||||
memBarrier.pNext = nullptr;
|
memBarrier.pNext = nullptr;
|
||||||
|
|
||||||
VkPipelineStageFlags srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
VkPipelineStageFlags srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||||
|
|
||||||
memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
|
memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
memBarrier.dstAccessMask = 0;
|
memBarrier.dstAccessMask = 0;
|
||||||
|
|
|
@ -900,6 +900,7 @@ VkDescriptorSetInfo* VulkanRenderer::draw_getOrCreateDescriptorSet(PipelineInfo*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VKRObjectSampler* samplerObj = VKRObjectSampler::GetOrCreateSampler(&samplerInfo);
|
VKRObjectSampler* samplerObj = VKRObjectSampler::GetOrCreateSampler(&samplerInfo);
|
||||||
vkObjDS->addRef(samplerObj);
|
vkObjDS->addRef(samplerObj);
|
||||||
info.sampler = samplerObj->GetSampler();
|
info.sampler = samplerObj->GetSampler();
|
||||||
|
@ -1163,28 +1164,17 @@ void VulkanRenderer::draw_prepareDescriptorSets(PipelineInfo* pipeline_info, VkD
|
||||||
const auto geometryShader = LatteSHRC_GetActiveGeometryShader();
|
const auto geometryShader = LatteSHRC_GetActiveGeometryShader();
|
||||||
const auto pixelShader = LatteSHRC_GetActivePixelShader();
|
const auto pixelShader = LatteSHRC_GetActivePixelShader();
|
||||||
|
|
||||||
|
auto prepareShaderDescriptors = [this, &pipeline_info](LatteDecompilerShader* shader) -> VkDescriptorSetInfo* {
|
||||||
if (vertexShader)
|
if (!shader)
|
||||||
{
|
return nullptr;
|
||||||
auto descriptorSetInfo = draw_getOrCreateDescriptorSet(pipeline_info, vertexShader);
|
auto descriptorSetInfo = draw_getOrCreateDescriptorSet(pipeline_info, shader);
|
||||||
descriptorSetInfo->m_vkObjDescriptorSet->flagForCurrentCommandBuffer();
|
descriptorSetInfo->m_vkObjDescriptorSet->flagForCurrentCommandBuffer();
|
||||||
vertexDS = descriptorSetInfo;
|
return descriptorSetInfo;
|
||||||
}
|
};
|
||||||
|
|
||||||
if (pixelShader)
|
vertexDS = prepareShaderDescriptors(vertexShader);
|
||||||
{
|
pixelDS = prepareShaderDescriptors(pixelShader);
|
||||||
auto descriptorSetInfo = draw_getOrCreateDescriptorSet(pipeline_info, pixelShader);
|
geometryDS = prepareShaderDescriptors(geometryShader);
|
||||||
descriptorSetInfo->m_vkObjDescriptorSet->flagForCurrentCommandBuffer();
|
|
||||||
pixelDS = descriptorSetInfo;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (geometryShader)
|
|
||||||
{
|
|
||||||
auto descriptorSetInfo = draw_getOrCreateDescriptorSet(pipeline_info, geometryShader);
|
|
||||||
descriptorSetInfo->m_vkObjDescriptorSet->flagForCurrentCommandBuffer();
|
|
||||||
geometryDS = descriptorSetInfo;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::draw_updateVkBlendConstants()
|
void VulkanRenderer::draw_updateVkBlendConstants()
|
||||||
|
|
|
@ -76,6 +76,30 @@ struct CopySurfacePipelineInfo
|
||||||
CopySurfacePipelineInfo() = default;
|
CopySurfacePipelineInfo() = default;
|
||||||
CopySurfacePipelineInfo(VkDevice device) : m_device(device) {}
|
CopySurfacePipelineInfo(VkDevice device) : m_device(device) {}
|
||||||
CopySurfacePipelineInfo(const CopySurfacePipelineInfo& info) = delete;
|
CopySurfacePipelineInfo(const CopySurfacePipelineInfo& info) = delete;
|
||||||
|
~CopySurfacePipelineInfo()
|
||||||
|
{
|
||||||
|
auto renderer = VulkanRenderer::GetInstance();
|
||||||
|
renderer->ReleaseDestructibleObject(vkObjRenderPass);
|
||||||
|
renderer->ReleaseDestructibleObject(vkObjPipeline);
|
||||||
|
|
||||||
|
for(auto& i : map_framebuffers)
|
||||||
|
{
|
||||||
|
for(auto& fb : i.second.m_array)
|
||||||
|
{
|
||||||
|
renderer->ReleaseDestructibleObject(fb->vkObjFramebuffer);
|
||||||
|
renderer->ReleaseDestructibleObject(fb->vkObjImageView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& i : map_descriptors)
|
||||||
|
{
|
||||||
|
for(auto& descriptor : i.second.m_array)
|
||||||
|
{
|
||||||
|
renderer->ReleaseDestructibleObject(descriptor->vkObjImageView);
|
||||||
|
renderer->ReleaseDestructibleObject(descriptor->vkObjDescriptorSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VkDevice m_device = nullptr;
|
VkDevice m_device = nullptr;
|
||||||
|
|
||||||
|
@ -842,5 +866,9 @@ void VulkanRenderer::surfaceCopy_notifyTextureRelease(LatteTextureVk* hostTextur
|
||||||
|
|
||||||
void VulkanRenderer::surfaceCopy_cleanup()
|
void VulkanRenderer::surfaceCopy_cleanup()
|
||||||
{
|
{
|
||||||
// todo - release m_copySurfacePipelineCache etc
|
for(auto& i : m_copySurfacePipelineCache)
|
||||||
|
{
|
||||||
|
delete i.second;
|
||||||
|
}
|
||||||
|
m_copySurfacePipelineCache = {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -465,6 +465,15 @@ void ImGui_ImplVulkan_DestroyFontsTexture()
|
||||||
if (g_FontView) { vkDestroyImageView(v->Device, g_FontView, v->Allocator); g_FontView = VK_NULL_HANDLE; }
|
if (g_FontView) { vkDestroyImageView(v->Device, g_FontView, v->Allocator); g_FontView = VK_NULL_HANDLE; }
|
||||||
if (g_FontImage) { vkDestroyImage(v->Device, g_FontImage, v->Allocator); g_FontImage = VK_NULL_HANDLE; }
|
if (g_FontImage) { vkDestroyImage(v->Device, g_FontImage, v->Allocator); g_FontImage = VK_NULL_HANDLE; }
|
||||||
if (g_FontMemory) { vkFreeMemory(v->Device, g_FontMemory, v->Allocator); g_FontMemory = VK_NULL_HANDLE; }
|
if (g_FontMemory) { vkFreeMemory(v->Device, g_FontMemory, v->Allocator); g_FontMemory = VK_NULL_HANDLE; }
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
auto texture = io.Fonts->TexID;
|
||||||
|
if(texture != (ImTextureID)nullptr)
|
||||||
|
{
|
||||||
|
ImGui_ImplVulkan_DeleteTexture(texture);
|
||||||
|
delete (ImGuiTexture*)texture;
|
||||||
|
io.Fonts->TexID = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||||
|
|
Loading…
Add table
Reference in a new issue