diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index 9b24de4532..0d427e3400 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -485,6 +485,9 @@ void LatteShaderCache_Load() g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureDRCId); g_bootSndPlayer.FadeOutSound(); + + if(Latte_GetStopSignal()) + LatteThread_Exit(); } void LatteShaderCache_ShowProgress(const std::function & loadUpdateFunc, bool isPipelines) @@ -625,8 +628,6 @@ void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId) g_shaderCacheLoaderState.loadedPipelines = 0; LatteShaderCache_ShowProgress(LatteShaderCache_updatePipelineLoadingProgress, true); pipelineCache.EndLoading(); - if(Latte_GetStopSignal()) - LatteThread_Exit(); } bool LatteShaderCache_updatePipelineLoadingProgress() diff --git a/src/Cafe/HW/Latte/Core/LatteThread.cpp b/src/Cafe/HW/Latte/Core/LatteThread.cpp index 8874ecf45d..92a7fdbb12 100644 --- a/src/Cafe/HW/Latte/Core/LatteThread.cpp +++ b/src/Cafe/HW/Latte/Core/LatteThread.cpp @@ -257,6 +257,7 @@ void LatteThread_Exit() LatteSHRC_UnloadAll(); // close disk cache LatteShaderCache_Close(); + RendererOutputShader::ShutdownStatic(); // destroy renderer but make sure that g_renderer remains valid until the destructor has finished if (g_renderer) { diff --git a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp index 409dc24fa4..3a00c36a14 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp +++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp @@ -118,8 +118,8 @@ RendererOutputShader::RendererOutputShader(const std::string& vertex_source, con { auto finalFragmentSrc = PrependFragmentPreamble(fragment_source); - m_vertex_shader = 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_vertex_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false)); + m_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false)); m_vertex_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); } }; - setUniforms(m_vertex_shader, m_uniformLocations[0]); - setUniforms(m_fragment_shader, m_uniformLocations[1]); + setUniforms(m_vertex_shader.get(), m_uniformLocations[0]); + setUniforms(m_fragment_shader.get(), m_uniformLocations[1]); } 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_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; +} diff --git a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h index 61b24c20d3..b12edf8b4a 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h +++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h @@ -21,15 +21,16 @@ class RendererOutputShader RendererShader* GetVertexShader() const { - return m_vertex_shader; + return m_vertex_shader.get(); } RendererShader* GetFragmentShader() const { - return m_fragment_shader; + return m_fragment_shader.get(); } static void InitializeStatic(); + static void ShutdownStatic(); static RendererOutputShader* s_copy_shader; static RendererOutputShader* s_copy_shader_ud; @@ -46,8 +47,8 @@ class RendererOutputShader static std::string PrependFragmentPreamble(const std::string& shaderSrc); protected: - RendererShader* m_vertex_shader; - RendererShader* m_fragment_shader; + std::unique_ptr m_vertex_shader; + std::unique_ptr m_fragment_shader; struct UniformLocations { diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp index 50f2c2d6c4..8a66c81beb 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp @@ -211,6 +211,9 @@ RendererShaderVk::~RendererShaderVk() { while (!list_pipelineInfo.empty()) delete list_pipelineInfo[0]; + + VkDevice vkDev = VulkanRenderer::GetInstance()->GetLogicalDevice(); + vkDestroyShaderModule(vkDev, m_shader_module, nullptr); } void RendererShaderVk::Init() diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp index 56a3ab1253..47dafc9899 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp @@ -60,7 +60,7 @@ void SwapchainInfoVk::Create() VkAttachmentDescription colorAttachment = {}; colorAttachment.format = m_surfaceFormat.format; 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.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h index 7023f291e2..c4977c083b 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h @@ -70,6 +70,7 @@ struct SwapchainInfoVk VkSurfaceFormatKHR m_surfaceFormat{}; VkSwapchainKHR m_swapchain{}; Vector2i m_desiredExtent{}; + VkExtent2D m_actualExtent{}; uint32 swapchainImageIndex = (uint32)-1; uint64 m_presentId = 1; uint64 m_queueDepth = 0; // number of frames with pending presentation requests @@ -92,5 +93,4 @@ struct SwapchainInfoVk VkSemaphore m_currentSemaphore = VK_NULL_HANDLE; std::array m_swapchainQueueFamilyIndices; - VkExtent2D m_actualExtent{}; }; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp index 3494dbc5ea..54ca20cfe7 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp @@ -4,6 +4,14 @@ /* 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) { auto cmdBufferId = m_vkr->GetCurrentCommandBufferId(); @@ -233,6 +241,15 @@ void VKRSynchronizedHeapAllocator::GetStats(uint32& numBuffers, size_t& totalBuf /* 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) { 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; bool allocSuccess; 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) - 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) - 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 cemu_assert_debug(false); if (!allocSuccess) @@ -363,28 +380,14 @@ uint32 VkBufferChunkedHeap::allocateNewChunk(uint32 chunkIndex, uint32 minimumAl return allocationSize; } -uint32_t VKRMemoryManager::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) 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 +bool VKRMemoryManager::FindMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties, uint32& memoryIndex) const { VkPhysicalDeviceMemoryProperties memProperties; vkGetPhysicalDeviceMemoryProperties(m_vkr->GetPhysicalDevice(), &memProperties); 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; return true; @@ -455,31 +458,7 @@ size_t VKRMemoryManager::GetTotalMemoryForBufferType(VkBufferUsageFlags usage, V return total; } -void 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 +bool VKRMemoryManager::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const { VkBufferCreateInfo bufferInfo{}; 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; 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; } @@ -498,7 +477,7 @@ bool VKRMemoryManager::CreateBuffer2(VkDeviceSize size, VkBufferUsageFlags usage VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; - if (!FindMemoryType2(memRequirements.memoryTypeBits, properties, allocInfo.memoryTypeIndex)) + if (!FindMemoryType(memRequirements.memoryTypeBits, properties, allocInfo.memoryTypeIndex)) { vkDestroyBuffer(m_vkr->GetLogicalDevice(), buffer, nullptr); return false; @@ -511,7 +490,7 @@ bool VKRMemoryManager::CreateBuffer2(VkDeviceSize size, VkBufferUsageFlags usage if (vkBindBufferMemory(m_vkr->GetLogicalDevice(), buffer, bufferMemory, 0) != VK_SUCCESS) { 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 true; @@ -533,7 +512,7 @@ bool VKRMemoryManager::CreateBufferFromHostMemory(void* hostPointer, VkDeviceSiz 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; } @@ -554,7 +533,7 @@ bool VKRMemoryManager::CreateBufferFromHostMemory(void* hostPointer, VkDeviceSiz allocInfo.pNext = &importHostMem; - if (!FindMemoryType2(memRequirements.memoryTypeBits, properties, allocInfo.memoryTypeIndex)) + if (!FindMemoryType(memRequirements.memoryTypeBits, properties, allocInfo.memoryTypeIndex)) { vkDestroyBuffer(m_vkr->GetLogicalDevice(), buffer, nullptr); return false; @@ -598,7 +577,7 @@ VkImageMemAllocation* VKRMemoryManager::imageMemoryAllocate(VkImage image) map_textureHeap.emplace(typeFilter, texHeap); } else - texHeap = it->second; + texHeap = it->second.get(); // alloc mem from heap uint32 allocationSize = (uint32)memRequirements.size; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h index 08af5882d3..b81b65ea6a 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h @@ -48,6 +48,7 @@ class VkTextureChunkedHeap : private ChunkedHeap<> { public: VkTextureChunkedHeap(class VKRMemoryManager* memoryManager, uint32 typeFilter) : m_vkrMemoryManager(memoryManager), m_typeFilter(typeFilter) { }; + ~VkTextureChunkedHeap(); struct ChunkInfo { @@ -148,6 +149,7 @@ class VKRSynchronizedRingAllocator 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(const VKRSynchronizedRingAllocator&) = delete; // disallow copy + ~VKRSynchronizedRingAllocator(); struct BufferSyncPoint_t { @@ -256,7 +258,7 @@ class VKRMemoryManager } // texture memory management - std::unordered_map map_textureHeap; // one heap per memory type + std::unordered_map> map_textureHeap; // one heap per memory type std::vector m_textureUploadBuffer; // texture upload buffer @@ -286,9 +288,7 @@ class VKRMemoryManager m_vertexStrideMetalBuffer.CleanupBuffer(latestFinishedCommandBufferId); } - // memory helpers - 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) + bool FindMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties, uint32& memoryIndex) const; // searches for exact properties. Can gracefully fail without throwing exception (returns false) std::vector FindMemoryTypes(uint32_t typeFilter, VkMemoryPropertyFlags properties) const; // image memory allocation @@ -298,8 +298,7 @@ class VKRMemoryManager // buffer management 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 CreateBuffer2(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) const; // same as CreateBuffer but doesn't throw exception on failure + bool CreateBuffer(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; void DeleteBuffer(VkBuffer& buffer, VkDeviceMemory& deviceMem) const; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h index 6bde2a0bdb..ae2a62f2b3 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h @@ -165,6 +165,7 @@ VKFUNC_DEVICE(vkCmdDraw); VKFUNC_DEVICE(vkCmdCopyBufferToImage); VKFUNC_DEVICE(vkCmdCopyImageToBuffer); VKFUNC_DEVICE(vkCmdClearColorImage); +VKFUNC_DEVICE(vkCmdClearAttachments); VKFUNC_DEVICE(vkCmdBindIndexBuffer); VKFUNC_DEVICE(vkCmdBindVertexBuffers); VKFUNC_DEVICE(vkCmdDrawIndexed); @@ -198,6 +199,7 @@ VKFUNC_DEVICE(vkCmdEndTransformFeedbackEXT); // query VKFUNC_DEVICE(vkCreateQueryPool); +VKFUNC_DEVICE(vkDestroyQueryPool); VKFUNC_DEVICE(vkCmdResetQueryPool); VKFUNC_DEVICE(vkCmdBeginQuery); VKFUNC_DEVICE(vkCmdEndQuery); @@ -236,6 +238,7 @@ VKFUNC_DEVICE(vkAllocateDescriptorSets); VKFUNC_DEVICE(vkFreeDescriptorSets); VKFUNC_DEVICE(vkUpdateDescriptorSets); VKFUNC_DEVICE(vkCreateDescriptorPool); +VKFUNC_DEVICE(vkDestroyDescriptorPool); VKFUNC_DEVICE(vkDestroyDescriptorSetLayout); #undef VKFUNC_INIT diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 66369c1035..4ff2faac0d 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -439,7 +439,7 @@ VulkanRenderer::VulkanRenderer() GetDeviceFeatures(); // init memory manager - memoryManager = new VKRMemoryManager(this); + memoryManager.reset(new VKRMemoryManager(this)); try { @@ -577,15 +577,15 @@ VulkanRenderer::VulkanRenderer() void* bufferPtr; // init ringbuffer for uniform vars 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; - 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 - 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; 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) @@ -628,6 +628,31 @@ VulkanRenderer::~VulkanRenderer() m_pipeline_cache_semaphore.notify(); m_pipeline_cache_save_thread.join(); + vkDestroyPipelineCache(m_logicalDevice, m_pipeline_cache, nullptr); + + if(!m_backbufferBlitDescriptorSetCache.empty()) + { + std::vector 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 ImGui_ImplVulkan_Shutdown(); @@ -640,10 +665,6 @@ VulkanRenderer::~VulkanRenderer() memoryManager->DeleteBuffer(m_xfbRingBuffer, m_xfbRingBufferMemory); memoryManager->DeleteBuffer(m_occlusionQueries.bufferQueryResults, m_occlusionQueries.memoryQueryResults); memoryManager->DeleteBuffer(m_bufferCache, m_bufferCacheMemory); - // texture memory - // todo - // upload buffers - // todo m_padSwapchainInfo = nullptr; m_mainSwapchainInfo = nullptr; @@ -666,6 +687,12 @@ VulkanRenderer::~VulkanRenderer() it = VK_NULL_HANDLE; } + for(auto& sem : m_commandBufferSemaphores) + { + vkDestroySemaphore(m_logicalDevice, sem, nullptr); + sem = VK_NULL_HANDLE; + } + if (m_pipelineLayout != VK_NULL_HANDLE) vkDestroyPipelineLayout(m_logicalDevice, m_pipelineLayout, nullptr); @@ -681,8 +708,11 @@ VulkanRenderer::~VulkanRenderer() vkDestroyDebugUtilsMessengerEXT(m_instance, m_debugCallback, nullptr); } + while(!m_destructionQueue.empty()) + ProcessDestructionQueue(); + // destroy memory manager - delete memoryManager; + memoryManager.reset(); // destroy instance, devices if (m_instance != VK_NULL_HANDLE) @@ -825,7 +855,14 @@ void VulkanRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool pad VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 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) { @@ -1608,6 +1645,7 @@ void VulkanRenderer::Initialize() void VulkanRenderer::Shutdown() { + DeleteFontTextures(); Renderer::Shutdown(); SubmitCommandBuffer(); WaitDeviceIdle(); @@ -1808,7 +1846,6 @@ void VulkanRenderer::ImguiEnd() vkCmdEndRenderPass(m_state.currentCommandBuffer); } -std::vector g_imgui_textures; // TODO manage better ImTextureID VulkanRenderer::GenerateTexture(const std::vector& data, const Vector2i& size) { try @@ -1838,6 +1875,7 @@ void VulkanRenderer::DeleteTexture(ImTextureID id) void VulkanRenderer::DeleteFontTextures() { + WaitDeviceIdle(); ImGui_ImplVulkan_DestroyFontsTexture(); } @@ -1876,7 +1914,7 @@ void VulkanRenderer::InitFirstCommandBuffer() vkResetFences(m_logicalDevice, 1, &m_cmd_buffer_fences[m_commandBufferIndex]); VkCommandBufferBeginInfo beginInfo{}; 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); vkCmdSetViewport(m_state.currentCommandBuffer, 0, 1, &m_state.currentViewport); @@ -1998,7 +2036,7 @@ void VulkanRenderer::SubmitCommandBuffer(VkSemaphore signalSemaphore, VkSemaphor VkCommandBufferBeginInfo beginInfo{}; 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); // 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)padView) << 1; - static std::unordered_map s_pipeline_cache; - const auto it = s_pipeline_cache.find(hash); - if (it != s_pipeline_cache.cend()) + const auto it = m_backbufferBlitPipelineCache.find(hash); + if (it != m_backbufferBlitPipelineCache.cend()) return it->second; std::vector shaderStages; @@ -2625,7 +2662,7 @@ VkPipeline VulkanRenderer::backbufferBlit_createGraphicsPipeline(VkDescriptorSet 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(); return pipeline; @@ -2922,9 +2959,6 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu LatteTextureViewVk* texViewVk = (LatteTextureViewVk*)texView; draw_endRenderPass(); - if (clearBackground) - ClearColorbuffer(padView); - // barrier for input texture VkMemoryBarrier memoryBarrier{}; 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); + 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); m_state.currentPipeline = pipeline; @@ -3025,9 +3069,8 @@ VkDescriptorSet VulkanRenderer::backbufferBlit_createDescriptorSet(VkDescriptorS hash += (uint64)texViewVk->GetViewRGBA(); hash += (uint64)texViewVk->GetDefaultTextureSampler(useLinearTexFilter); - static std::unordered_map s_set_cache; - const auto it = s_set_cache.find(hash); - if (it != s_set_cache.cend()) + const auto it = m_backbufferBlitDescriptorSetCache.find(hash); + if (it != m_backbufferBlitDescriptorSetCache.cend()) return it->second; VkDescriptorSetAllocateInfo allocInfo = {}; @@ -3058,7 +3101,7 @@ VkDescriptorSet VulkanRenderer::backbufferBlit_createDescriptorSet(VkDescriptorS vkUpdateDescriptorSets(m_logicalDevice, 1, &descriptorWrites, 0, nullptr); performanceMonitor.vk.numDescriptorSamplerTextures.increment(); - s_set_cache[hash] = result; + m_backbufferBlitDescriptorSetCache[hash] = result; return result; } @@ -3191,7 +3234,8 @@ VkDescriptorSetInfo::~VkDescriptorSetInfo() performanceMonitor.vk.numDescriptorDynUniformBuffers.decrement(statsNumDynUniformBuffers); performanceMonitor.vk.numDescriptorStorageBuffers.decrement(statsNumStorageBuffers); - VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_vkObjDescriptorSet); + auto renderer = VulkanRenderer::GetInstance(); + renderer->ReleaseDestructibleObject(m_vkObjDescriptorSet); m_vkObjDescriptorSet = nullptr; } diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h index 5ef4558dad..f1450487a2 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h @@ -137,8 +137,8 @@ class VulkanRenderer : public Renderer public: // memory management - VKRMemoryManager* memoryManager{}; - VKRMemoryManager* GetMemoryManager() const { return memoryManager; }; + std::unique_ptr memoryManager; + VKRMemoryManager* GetMemoryManager() const { return memoryManager.get(); }; VkSupportedFormatInfo_t m_supportedFormatInfo; @@ -583,6 +583,8 @@ class VulkanRenderer : public Renderer std::shared_mutex m_pipeline_cache_save_mutex; std::thread m_pipeline_cache_save_thread; VkPipelineCache m_pipeline_cache{ nullptr }; + std::unordered_map m_backbufferBlitPipelineCache; + std::unordered_map m_backbufferBlitDescriptorSetCache; VkPipelineLayout m_pipelineLayout{nullptr}; VkCommandPool m_commandPool{ nullptr }; @@ -860,7 +862,7 @@ class VulkanRenderer : public Renderer memBarrier.pNext = nullptr; 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.dstAccessMask = 0; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp index 198a32cb87..3e23b0aa03 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp @@ -900,6 +900,7 @@ VkDescriptorSetInfo* VulkanRenderer::draw_getOrCreateDescriptorSet(PipelineInfo* } } } + VKRObjectSampler* samplerObj = VKRObjectSampler::GetOrCreateSampler(&samplerInfo); vkObjDS->addRef(samplerObj); info.sampler = samplerObj->GetSampler(); @@ -1163,28 +1164,17 @@ void VulkanRenderer::draw_prepareDescriptorSets(PipelineInfo* pipeline_info, VkD const auto geometryShader = LatteSHRC_GetActiveGeometryShader(); const auto pixelShader = LatteSHRC_GetActivePixelShader(); - - if (vertexShader) - { - auto descriptorSetInfo = draw_getOrCreateDescriptorSet(pipeline_info, vertexShader); + auto prepareShaderDescriptors = [this, &pipeline_info](LatteDecompilerShader* shader) -> VkDescriptorSetInfo* { + if (!shader) + return nullptr; + auto descriptorSetInfo = draw_getOrCreateDescriptorSet(pipeline_info, shader); descriptorSetInfo->m_vkObjDescriptorSet->flagForCurrentCommandBuffer(); - vertexDS = descriptorSetInfo; - } + return descriptorSetInfo; + }; - if (pixelShader) - { - auto descriptorSetInfo = draw_getOrCreateDescriptorSet(pipeline_info, pixelShader); - descriptorSetInfo->m_vkObjDescriptorSet->flagForCurrentCommandBuffer(); - pixelDS = descriptorSetInfo; - - } - - if (geometryShader) - { - auto descriptorSetInfo = draw_getOrCreateDescriptorSet(pipeline_info, geometryShader); - descriptorSetInfo->m_vkObjDescriptorSet->flagForCurrentCommandBuffer(); - geometryDS = descriptorSetInfo; - } + vertexDS = prepareShaderDescriptors(vertexShader); + pixelDS = prepareShaderDescriptors(pixelShader); + geometryDS = prepareShaderDescriptors(geometryShader); } void VulkanRenderer::draw_updateVkBlendConstants() diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp index bf33ed9022..f98eb45227 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp @@ -76,6 +76,30 @@ struct CopySurfacePipelineInfo CopySurfacePipelineInfo() = default; CopySurfacePipelineInfo(VkDevice device) : m_device(device) {} 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; @@ -842,5 +866,9 @@ void VulkanRenderer::surfaceCopy_notifyTextureRelease(LatteTextureVk* hostTextur void VulkanRenderer::surfaceCopy_cleanup() { - // todo - release m_copySurfacePipelineCache etc + for(auto& i : m_copySurfacePipelineCache) + { + delete i.second; + } + m_copySurfacePipelineCache = {}; } diff --git a/src/imgui/imgui_impl_vulkan.cpp b/src/imgui/imgui_impl_vulkan.cpp index 723f153c91..f9a23166d1 100644 --- a/src/imgui/imgui_impl_vulkan.cpp +++ b/src/imgui/imgui_impl_vulkan.cpp @@ -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_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; } + + 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)