diff --git a/.github/workflows/generate_pot.yml b/.github/workflows/generate_pot.yml index 7dfa86f8..b057d441 100644 --- a/.github/workflows/generate_pot.yml +++ b/.github/workflows/generate_pot.yml @@ -35,7 +35,7 @@ jobs: -o cemu.pot - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: POT file path: ./cemu.pot diff --git a/src/Cafe/GameProfile/GameProfile.cpp b/src/Cafe/GameProfile/GameProfile.cpp index 2a83b3fe..ea303226 100644 --- a/src/Cafe/GameProfile/GameProfile.cpp +++ b/src/Cafe/GameProfile/GameProfile.cpp @@ -140,14 +140,14 @@ bool gameProfile_loadEnumOption(IniParser& iniParser, const char* optionName, T& for(const T& v : T()) { // test integer option - if (boost::iequals(fmt::format("{}", static_cast::type>(v)), *option_value)) + if (boost::iequals(fmt::format("{}", fmt::underlying(v)), *option_value)) { option = v; return true; } // test enum name - if(boost::iequals(fmt::format("{}", fmt::underlying(v)), *option_value)) + if(boost::iequals(fmt::format("{}", v), *option_value)) { option = v; return true; diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerX64.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerX64.cpp index a30295b5..97b2c14c 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerX64.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerX64.cpp @@ -114,13 +114,13 @@ void* ATTR_MS_ABI PPCRecompiler_virtualHLE(PPCInterpreter_t* hCPU, uint32 hleFun void ATTR_MS_ABI PPCRecompiler_getTBL(PPCInterpreter_t* hCPU, uint32 gprIndex) { - uint64 coreTime = coreinit::coreinit_getTimerTick(); + uint64 coreTime = coreinit::OSGetSystemTime(); hCPU->gpr[gprIndex] = (uint32)(coreTime&0xFFFFFFFF); } void ATTR_MS_ABI PPCRecompiler_getTBU(PPCInterpreter_t* hCPU, uint32 gprIndex) { - uint64 coreTime = coreinit::coreinit_getTimerTick(); + uint64 coreTime = coreinit::OSGetSystemTime(); hCPU->gpr[gprIndex] = (uint32)((coreTime>>32)&0xFFFFFFFF); } diff --git a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp index a8f81901..f592cc9e 100644 --- a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp +++ b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp @@ -799,7 +799,7 @@ LatteCMDPtr LatteCP_itHLESampleTimer(LatteCMDPtr cmd, uint32 nWords) { cemu_assert_debug(nWords == 1); MPTR timerMPTR = (MPTR)LatteReadCMD(); - memory_writeU64(timerMPTR, coreinit::coreinit_getTimerTick()); + memory_writeU64(timerMPTR, coreinit::OSGetSystemTime()); return cmd; } diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index a6b136a6..86035973 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 8874ecf4..92a7fdbb 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 409dc24f..3a00c36a 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 61b24c20..b12edf8b 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h +++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h @@ -21,15 +21,16 @@ public: 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 @@ public: 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 50f2c2d6..8a66c81b 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 56a3ab12..47dafc98 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 7023f291..c4977c08 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 @@ private: 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 3494dbc5..54ca20cf 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 08af5882..b81b65ea 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 @@ public: } // 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 @@ public: 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 @@ public: // 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 6bde2a0b..ae2a62f2 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 66369c10..4ff2faac 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 5ef4558d..f1450487 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 @@ private: 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 @@ private: 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 198a32cb..3e23b0aa 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 bf33ed90..f98eb452 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/Cafe/IOSU/legacy/iosu_acp.cpp b/src/Cafe/IOSU/legacy/iosu_acp.cpp index f5144ee6..6a9e6b89 100644 --- a/src/Cafe/IOSU/legacy/iosu_acp.cpp +++ b/src/Cafe/IOSU/legacy/iosu_acp.cpp @@ -469,7 +469,7 @@ namespace iosu entry->ukn0C = 0; entry->sizeA = _swapEndianU64(0); // ukn entry->sizeB = _swapEndianU64(dirSize); - entry->time = _swapEndianU64((coreinit::coreinit_getOSTime() / ESPRESSO_TIMER_CLOCK)); + entry->time = _swapEndianU64((coreinit::OSGetTime() / ESPRESSO_TIMER_CLOCK)); sprintf(entry->path, "%susr/save/%08x/%08x/meta/", devicePath, (uint32)(titleId >> 32), (uint32)(titleId & 0xFFFFFFFF)); count++; } @@ -504,7 +504,7 @@ namespace iosu entry->ukn0C = 0; entry->sizeA = _swapEndianU64(0); entry->sizeB = _swapEndianU64(0); - entry->time = _swapEndianU64((coreinit::coreinit_getOSTime() / ESPRESSO_TIMER_CLOCK)); + entry->time = _swapEndianU64((coreinit::OSGetTime() / ESPRESSO_TIMER_CLOCK)); sprintf(entry->path, "%susr/save/%08x/%08x/meta/", devicePath, (uint32)(titleId >> 32), (uint32)(titleId & 0xFFFFFFFF)); count++; } @@ -584,7 +584,7 @@ namespace iosu uint64 _ACPGetTimestamp() { - return coreinit::coreinit_getOSTime() / ESPRESSO_TIMER_CLOCK; + return coreinit::OSGetTime() / ESPRESSO_TIMER_CLOCK; } nnResult ACPUpdateSaveTimeStamp(uint32 persistentId, uint64 titleId, ACPDeviceType deviceType) diff --git a/src/Cafe/OS/libs/camera/camera.cpp b/src/Cafe/OS/libs/camera/camera.cpp index 03e01bfc..efb8013d 100644 --- a/src/Cafe/OS/libs/camera/camera.cpp +++ b/src/Cafe/OS/libs/camera/camera.cpp @@ -186,7 +186,7 @@ namespace camera if (g_cameraCounter == 0) { coreinit::OSCreateAlarm(g_alarm_camera.GetPtr()); - coreinit::OSSetPeriodicAlarm(g_alarm_camera.GetPtr(), coreinit::coreinit_getOSTime(), (uint64)ESPRESSO_TIMER_CLOCK / 60ull, RPLLoader_MakePPCCallable(ppcCAMUpdate60)); + coreinit::OSSetPeriodicAlarm(g_alarm_camera.GetPtr(), coreinit::OSGetTime(), (uint64)ESPRESSO_TIMER_CLOCK / 60ull, RPLLoader_MakePPCCallable(ppcCAMUpdate60)); } g_cameraCounter++; diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp index f7e58115..ae2d1e63 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp @@ -166,7 +166,7 @@ namespace coreinit void alarm_update() { cemu_assert_debug(!__OSHasSchedulerLock()); - uint64 currentTick = coreinit::coreinit_getOSTime(); + uint64 currentTick = coreinit::OSGetTime(); if (!OSHostAlarm::quickCheckForAlarm(currentTick)) return; __OSLockScheduler(); @@ -233,7 +233,7 @@ namespace coreinit if (period == 0) return; - uint64 currentTime = coreinit_getOSTime(); + uint64 currentTime = OSGetTime(); uint64 ticksSinceStart = currentTime - startTime; uint64 numPeriods = ticksSinceStart / period; @@ -267,7 +267,7 @@ namespace coreinit void OSSetAlarm(OSAlarm_t* alarm, uint64 delayInTicks, MPTR handlerFunc) { __OSLockScheduler(); - __OSInitiateAlarm(alarm, coreinit_getOSTime() + delayInTicks, 0, handlerFunc, false); + __OSInitiateAlarm(alarm, OSGetTime() + delayInTicks, 0, handlerFunc, false); __OSUnlockScheduler(); } @@ -310,7 +310,7 @@ namespace coreinit while( true ) { OSWaitEvent(g_alarmEvent.GetPtr()); - uint64 currentTick = coreinit_getOSTime(); + uint64 currentTick = OSGetTime(); while (true) { // get alarm to fire diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Spinlock.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Spinlock.cpp index 5201d441..3d235107 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Spinlock.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Spinlock.cpp @@ -86,11 +86,11 @@ namespace coreinit else { // loop until lock acquired or timeout occurred - uint64 timeoutValue = coreinit_getTimerTick() + coreinit::EspressoTime::ConvertNsToTimerTicks(timeout); + uint64 timeoutValue = OSGetSystemTime() + coreinit::EspressoTime::ConvertNsToTimerTicks(timeout); while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread)) { OSYieldThread(); - if (coreinit_getTimerTick() >= timeoutValue) + if (OSGetSystemTime() >= timeoutValue) { return false; } @@ -182,11 +182,11 @@ namespace coreinit else { // loop until lock acquired or timeout occurred - uint64 timeoutValue = coreinit_getTimerTick() + coreinit::EspressoTime::ConvertNsToTimerTicks(timeout); + uint64 timeoutValue = OSGetSystemTime() + coreinit::EspressoTime::ConvertNsToTimerTicks(timeout); while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread)) { OSYieldThread(); - if (coreinit_getTimerTick() >= timeoutValue) + if (OSGetSystemTime() >= timeoutValue) { return false; } diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp index c144c384..e81cc577 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp @@ -73,8 +73,6 @@ namespace coreinit } } - uint64 coreinit_getOSTime(); - bool OSWaitEventWithTimeout(OSEvent* event, uint64 timeout) { __OSLockScheduler(); @@ -95,14 +93,14 @@ namespace coreinit // workaround for a bad implementation in some Unity games (like Qube Directors Cut, see FEventWiiU::Wait) // where the the return value of OSWaitEventWithTimeout is ignored and instead the game measures the elapsed time to determine if a timeout occurred - timeout = timeout * 98ULL / 100ULL; // 98% (we want the function to return slightly before the actual timeout) + if (timeout < 0x00FFFFFFFFFFFFFFULL) + timeout = timeout * 98ULL / 100ULL; // 98% (we want the function to return slightly before the actual timeout) WaitEventWithTimeoutData data; data.thread = OSGetCurrentThread(); data.threadQueue = &event->threadQueue; data.hasTimeout = false; - - auto hostAlarm = coreinit::OSHostAlarmCreate(coreinit::coreinit_getOSTime() + coreinit::EspressoTime::ConvertNsToTimerTicks(timeout), 0, _OSWaitEventWithTimeoutHandler, &data); + auto hostAlarm = coreinit::OSHostAlarmCreate(OSGetTime() + coreinit::EspressoTime::ConvertNsToTimerTicks(timeout), 0, _OSWaitEventWithTimeoutHandler, &data); event->threadQueue.queueAndWait(OSGetCurrentThread()); coreinit::OSHostAlarmDestroy(hostAlarm); if (data.hasTimeout) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp index db457047..870d1850 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp @@ -655,7 +655,7 @@ namespace coreinit StackAllocator _threadQueue; OSInitThreadQueue(_threadQueue.GetPointer()); __OSLockScheduler(); - OSHostAlarm* hostAlarm = OSHostAlarmCreate(coreinit_getOSTime() + ticks, 0, _OSSleepTicks_alarmHandler, _threadQueue.GetPointer()); + OSHostAlarm* hostAlarm = OSHostAlarmCreate(OSGetTime() + ticks, 0, _OSSleepTicks_alarmHandler, _threadQueue.GetPointer()); _threadQueue.GetPointer()->queueAndWait(OSGetCurrentThread()); OSHostAlarmDestroy(hostAlarm); __OSUnlockScheduler(); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Time.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Time.cpp index d6fc27b2..50a404f4 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Time.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Time.cpp @@ -3,38 +3,32 @@ namespace coreinit { - - uint64 coreinit_getTimerTick() + uint64 coreinit_GetMFTB() { // bus clock is 1/5th of core clock // timer clock is 1/4th of bus clock return PPCInterpreter_getMainCoreCycleCounter() / 20ULL; } - uint64 coreinit_getOSTime() + uint64 OSGetSystemTime() { - return coreinit_getTimerTick() + ppcCyclesSince2000TimerClock; - } - - void export_OSGetTick(PPCInterpreter_t* hCPU) - { - uint64 osTime = coreinit_getOSTime(); - osLib_returnFromFunction(hCPU, (uint32)osTime); + return coreinit_GetMFTB(); } uint64 OSGetTime() { - return coreinit_getOSTime(); + return OSGetSystemTime() + ppcCyclesSince2000TimerClock; } - void export_OSGetSystemTime(PPCInterpreter_t* hCPU) + uint32 OSGetSystemTick() { - osLib_returnFromFunction64(hCPU, coreinit_getTimerTick()); + return static_cast(coreinit_GetMFTB()); } - void export_OSGetSystemTick(PPCInterpreter_t* hCPU) + uint32 OSGetTick() { - osLib_returnFromFunction(hCPU, (uint32)coreinit_getTimerTick()); + uint64 osTime = OSGetTime(); + return static_cast(osTime); } uint32 getLeapDaysUntilYear(uint32 year) @@ -360,14 +354,13 @@ namespace coreinit void InitializeTimeAndCalendar() { cafeExportRegister("coreinit", OSGetTime, LogType::Placeholder); - osLib_addFunction("coreinit", "OSGetSystemTime", export_OSGetSystemTime); - osLib_addFunction("coreinit", "OSGetTick", export_OSGetTick); - osLib_addFunction("coreinit", "OSGetSystemTick", export_OSGetSystemTick); + cafeExportRegister("coreinit", OSGetSystemTime, LogType::Placeholder); + cafeExportRegister("coreinit", OSGetTick, LogType::Placeholder); + cafeExportRegister("coreinit", OSGetSystemTick, LogType::Placeholder); cafeExportRegister("coreinit", OSTicksToCalendarTime, LogType::Placeholder); cafeExportRegister("coreinit", OSCalendarTimeToTicks, LogType::Placeholder); - //timeTest(); } }; \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Time.h b/src/Cafe/OS/libs/coreinit/coreinit_Time.h index 3aa92b99..380ccf1d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Time.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_Time.h @@ -40,25 +40,21 @@ namespace coreinit inline TimerTicks ConvertNsToTimerTicks(uint64 ns) { - return ((GetTimerClock() / 31250LL) * ((TimerTicks)ns) / 32000LL); + return static_cast((static_cast(GetTimerClock()) / 31250ULL) * (ns) / 32000ULL); } inline TimerTicks ConvertMsToTimerTicks(uint64 ms) { - return (TimerTicks)ms * GetTimerClock() / 1000LL; + return static_cast(ms * static_cast(GetTimerClock()) / 1000ULL); } }; void OSTicksToCalendarTime(uint64 ticks, OSCalendarTime_t* calenderStruct); + + uint64 OSGetSystemTime(); uint64 OSGetTime(); - - uint64 coreinit_getOSTime(); - uint64 coreinit_getTimerTick(); - - static uint64 OSGetSystemTime() - { - return coreinit_getTimerTick(); - } + uint32 OSGetSystemTick(); + uint32 OSGetTick(); void InitializeTimeAndCalendar(); }; diff --git a/src/Cafe/OS/libs/dmae/dmae.cpp b/src/Cafe/OS/libs/dmae/dmae.cpp index 6b3e8d0d..7c513784 100644 --- a/src/Cafe/OS/libs/dmae/dmae.cpp +++ b/src/Cafe/OS/libs/dmae/dmae.cpp @@ -11,7 +11,7 @@ uint64 dmaeRetiredTimestamp = 0; uint64 dmae_getTimestamp() { - return coreinit::coreinit_getTimerTick(); + return coreinit::OSGetSystemTime(); } void dmae_setRetiredTimestamp(uint64 timestamp) diff --git a/src/Cafe/OS/libs/gx2/GX2.cpp b/src/Cafe/OS/libs/gx2/GX2.cpp index c2ea34a4..593d31fb 100644 --- a/src/Cafe/OS/libs/gx2/GX2.cpp +++ b/src/Cafe/OS/libs/gx2/GX2.cpp @@ -322,7 +322,7 @@ uint64 _prevReturnedGPUTime = 0; uint64 Latte_GetTime() { - uint64 gpuTime = coreinit::coreinit_getTimerTick(); + uint64 gpuTime = coreinit::OSGetSystemTime(); gpuTime *= 20000ULL; if (gpuTime <= _prevReturnedGPUTime) gpuTime = _prevReturnedGPUTime + 1; // avoid ever returning identical timestamps diff --git a/src/Cafe/OS/libs/gx2/GX2_Misc.cpp b/src/Cafe/OS/libs/gx2/GX2_Misc.cpp index 2111238a..3c7ea3f9 100644 --- a/src/Cafe/OS/libs/gx2/GX2_Misc.cpp +++ b/src/Cafe/OS/libs/gx2/GX2_Misc.cpp @@ -54,7 +54,7 @@ void gx2Export_GX2GetGPUTimeout(PPCInterpreter_t* hCPU) void gx2Export_GX2SampleTopGPUCycle(PPCInterpreter_t* hCPU) { cemuLog_log(LogType::GX2, "GX2SampleTopGPUCycle(0x{:08x})", hCPU->gpr[3]); - memory_writeU64(hCPU->gpr[3], coreinit::coreinit_getTimerTick()); + memory_writeU64(hCPU->gpr[3], coreinit::OSGetSystemTime()); osLib_returnFromFunction(hCPU, 0); } diff --git a/src/Cafe/OS/libs/nn_acp/nn_acp.cpp b/src/Cafe/OS/libs/nn_acp/nn_acp.cpp index 37ea471f..9cde0213 100644 --- a/src/Cafe/OS/libs/nn_acp/nn_acp.cpp +++ b/src/Cafe/OS/libs/nn_acp/nn_acp.cpp @@ -315,7 +315,7 @@ namespace acp ppcDefineParamU32BEPtr(timestamp64, 0); ppcDefineParamU32BEPtr(ukn, 1); // probably timezone or offset? Could also be a bool for success/failed - uint64 t = coreinit::coreinit_getOSTime() + (uint64)((sint64)(ppcCyclesSince2000_UTC - ppcCyclesSince2000) / 20LL); + uint64 t = coreinit::OSGetTime() + (uint64)((sint64)(ppcCyclesSince2000_UTC - ppcCyclesSince2000) / 20LL); timestamp64[0] = (uint32)(t >> 32); timestamp64[1] = (uint32)(t & 0xFFFFFFFF); diff --git a/src/Cafe/OS/libs/padscore/padscore.cpp b/src/Cafe/OS/libs/padscore/padscore.cpp index 0a577b97..2f359748 100644 --- a/src/Cafe/OS/libs/padscore/padscore.cpp +++ b/src/Cafe/OS/libs/padscore/padscore.cpp @@ -760,7 +760,7 @@ namespace padscore void start() { OSCreateAlarm(&g_padscore.alarm); - const uint64 start_tick = coreinit::coreinit_getOSTime(); + const uint64 start_tick = coreinit::OSGetTime(); const uint64 period_tick = coreinit::EspressoTime::GetTimerClock() / 200; // every 5ms MPTR handler = PPCInterpreter_makeCallableExportDepr(TickFunction); OSSetPeriodicAlarm(&g_padscore.alarm, start_tick, period_tick, handler); diff --git a/src/Cafe/OS/libs/vpad/vpad.cpp b/src/Cafe/OS/libs/vpad/vpad.cpp index ded4304d..21c1c9e5 100644 --- a/src/Cafe/OS/libs/vpad/vpad.cpp +++ b/src/Cafe/OS/libs/vpad/vpad.cpp @@ -267,7 +267,7 @@ namespace vpad { if (channel <= 1 && vpadDelayEnabled) { - uint64 currentTime = coreinit::coreinit_getOSTime(); + uint64 currentTime = coreinit::OSGetTime(); const auto dif = currentTime - vpad::g_vpad.controller_data[channel].drcLastCallTime; if (dif <= (ESPRESSO_TIMER_CLOCK / 60ull)) { @@ -1149,7 +1149,7 @@ namespace vpad void start() { coreinit::OSCreateAlarm(&g_vpad.alarm); - const uint64 start_tick = coreinit::coreinit_getOSTime(); + const uint64 start_tick = coreinit::OSGetTime(); const uint64 period_tick = coreinit::EspressoTime::GetTimerClock() * 5 / 1000; const MPTR handler = PPCInterpreter_makeCallableExportDepr(TickFunction); coreinit::OSSetPeriodicAlarm(&g_vpad.alarm, start_tick, period_tick, handler); diff --git a/src/audio/IAudioAPI.cpp b/src/audio/IAudioAPI.cpp index c8b66b6d..1ba109f9 100644 --- a/src/audio/IAudioAPI.cpp +++ b/src/audio/IAudioAPI.cpp @@ -129,6 +129,7 @@ AudioAPIPtr IAudioAPI::CreateDeviceFromConfig(AudioType type, sint32 rate, sint3 audioAPIDev = CreateDevice(audio_api, device_description, rate, channels, samples_per_block, bits_per_sample); audioAPIDev->SetVolume(TV ? config.tv_volume : config.pad_volume); + return audioAPIDev; } @@ -220,7 +221,7 @@ AudioChannels IAudioAPI::AudioTypeToChannels(AudioType type) case Gamepad: return config.pad_channels; case Portal: - return config.portal_channels; + return kMono; default: return kMono; } @@ -241,3 +242,19 @@ std::wstring IAudioAPI::GetDeviceFromType(AudioType type) return L""; } } + +sint32 IAudioAPI::GetVolumeFromType(AudioType type) +{ + auto& config = GetConfig(); + switch (type) + { + case TV: + return config.tv_volume; + case Gamepad: + return config.pad_volume; + case Portal: + return config.portal_volume; + default: + return 0; + } +} diff --git a/src/audio/IAudioAPI.h b/src/audio/IAudioAPI.h index 43105370..34df421a 100644 --- a/src/audio/IAudioAPI.h +++ b/src/audio/IAudioAPI.h @@ -95,6 +95,7 @@ private: void InitWFX(sint32 samplerate, sint32 channels, sint32 bits_per_sample); static AudioChannels AudioTypeToChannels(AudioType type); static std::wstring GetDeviceFromType(AudioType type); + static sint32 GetVolumeFromType(AudioType type); }; diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp index 86f8b478..809a5470 100644 --- a/src/config/CemuConfig.cpp +++ b/src/config/CemuConfig.cpp @@ -275,7 +275,6 @@ void CemuConfig::Load(XMLConfigParser& parser) tv_channels = audio.get("TVChannels", kStereo); pad_channels = audio.get("PadChannels", kStereo); input_channels = audio.get("InputChannels", kMono); - portal_channels = audio.get("PortalChannels", kMono); tv_volume = audio.get("TVVolume", 20); pad_volume = audio.get("PadVolume", 0); input_volume = audio.get("InputVolume", 20); @@ -520,7 +519,6 @@ void CemuConfig::Save(XMLConfigParser& parser) audio.set("TVChannels", tv_channels); audio.set("PadChannels", pad_channels); audio.set("InputChannels", input_channels); - audio.set("InputChannels", portal_channels); audio.set("TVVolume", tv_volume); audio.set("PadVolume", pad_volume); audio.set("InputVolume", input_volume); diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index a3d733e5..e8c7e237 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -192,7 +192,7 @@ ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Enabled); #endif template <> -struct fmt::formatter : formatter { +struct fmt::formatter : formatter { template auto format(const PrecompiledShaderOption c, FormatContext &ctx) const { string_view name; @@ -207,7 +207,7 @@ struct fmt::formatter : formatter { } }; template <> -struct fmt::formatter : formatter { +struct fmt::formatter : formatter { template auto format(const AccurateShaderMulOption c, FormatContext &ctx) const { string_view name; @@ -221,7 +221,7 @@ struct fmt::formatter : formatter { } }; template <> -struct fmt::formatter : formatter { +struct fmt::formatter : formatter { template auto format(const CPUMode c, FormatContext &ctx) const { string_view name; @@ -238,7 +238,7 @@ struct fmt::formatter : formatter { } }; template <> -struct fmt::formatter : formatter { +struct fmt::formatter : formatter { template auto format(const CPUModeLegacy c, FormatContext &ctx) const { string_view name; @@ -255,7 +255,7 @@ struct fmt::formatter : formatter { } }; template <> -struct fmt::formatter : formatter { +struct fmt::formatter : formatter { template auto format(const CafeConsoleRegion v, FormatContext &ctx) const { string_view name; @@ -276,7 +276,7 @@ struct fmt::formatter : formatter { } }; template <> -struct fmt::formatter : formatter { +struct fmt::formatter : formatter { template auto format(const CafeConsoleLanguage v, FormatContext &ctx) { string_view name; @@ -302,7 +302,7 @@ struct fmt::formatter : formatter { #if BOOST_OS_WINDOWS template <> -struct fmt::formatter : formatter { +struct fmt::formatter : formatter { template auto format(const CrashDump v, FormatContext &ctx) { string_view name; @@ -319,7 +319,7 @@ struct fmt::formatter : formatter { }; #elif BOOST_OS_UNIX template <> -struct fmt::formatter : formatter { +struct fmt::formatter : formatter { template auto format(const CrashDump v, FormatContext &ctx) { string_view name; @@ -479,7 +479,7 @@ struct CemuConfig // audio sint32 audio_api = 0; sint32 audio_delay = 2; - AudioChannels tv_channels = kStereo, pad_channels = kStereo, input_channels = kMono, portal_channels = kMono; + AudioChannels tv_channels = kStereo, pad_channels = kStereo, input_channels = kMono; sint32 tv_volume = 50, pad_volume = 0, input_volume = 50, portal_volume = 50; std::wstring tv_device{ L"default" }, pad_device, input_device, portal_device; diff --git a/src/gui/GeneralSettings2.cpp b/src/gui/GeneralSettings2.cpp index dafa32f8..4c23aedc 100644 --- a/src/gui/GeneralSettings2.cpp +++ b/src/gui/GeneralSettings2.cpp @@ -559,17 +559,6 @@ wxPanel* GeneralSettings2::AddAudioPage(wxNotebook* notebook) m_portal_device->Bind(wxEVT_CHOICE, &GeneralSettings2::OnAudioDeviceSelected, this); - const wxString audio_channel_drc_choices[] = { _("Mono") }; // mono for now only - - portal_audio_row->Add(new wxStaticText(box, wxID_ANY, _("Channels")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); - m_portal_channels = new wxChoice(box, wxID_ANY, wxDefaultPosition, wxDefaultSize, std::size(audio_channel_drc_choices), audio_channel_drc_choices); - - m_portal_channels->SetSelection(0); // set default to mono - - m_portal_channels->Bind(wxEVT_CHOICE, &GeneralSettings2::OnAudioChannelsSelected, this); - portal_audio_row->Add(m_portal_channels, 0, wxEXPAND | wxALL, 5); - portal_audio_row->AddSpacer(0); - portal_audio_row->Add(new wxStaticText(box, wxID_ANY, _("Volume")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); m_portal_volume = new wxSlider(box, wxID_ANY, 100, 0, 100); portal_audio_row->Add(m_portal_volume, 0, wxEXPAND | wxALL, 5); @@ -1030,7 +1019,6 @@ void GeneralSettings2::StoreConfig() config.pad_channels = kStereo; // (AudioChannels)m_pad_channels->GetSelection(); //config.input_channels = (AudioChannels)m_input_channels->GetSelection(); config.input_channels = kMono; // (AudioChannels)m_input_channels->GetSelection(); - config.portal_channels = kMono; // (AudioChannels)m_portal_channels->GetSelection(); config.tv_volume = m_tv_volume->GetValue(); config.pad_volume = m_pad_volume->GetValue(); @@ -1720,7 +1708,6 @@ void GeneralSettings2::ApplyConfig() m_pad_channels->SetSelection(0); //m_input_channels->SetSelection(config.pad_channels); m_input_channels->SetSelection(0); - m_portal_channels->SetSelection(0); SendSliderEvent(m_tv_volume, config.tv_volume); @@ -1975,7 +1962,7 @@ void GeneralSettings2::UpdateAudioDevice() } catch (std::runtime_error& ex) { - cemuLog_log(LogType::Force, "can't initialize pad audio: {}", ex.what()); + cemuLog_log(LogType::Force, "can't initialize portal audio: {}", ex.what()); } } } @@ -2010,13 +1997,6 @@ void GeneralSettings2::OnAudioChannelsSelected(wxCommandEvent& event) config.pad_channels = (AudioChannels)obj->GetSelection(); } - else if (obj == m_portal_channels) - { - if (config.portal_channels == (AudioChannels)obj->GetSelection()) - return; - - config.portal_channels = (AudioChannels)obj->GetSelection(); - } else cemu_assert_debug(false); diff --git a/src/gui/GeneralSettings2.h b/src/gui/GeneralSettings2.h index a37b9c1b..5e27d6e2 100644 --- a/src/gui/GeneralSettings2.h +++ b/src/gui/GeneralSettings2.h @@ -64,7 +64,7 @@ private: wxChoice* m_audio_api; wxSlider *m_audio_latency; wxSlider *m_tv_volume, *m_pad_volume, *m_input_volume, *m_portal_volume; - wxChoice *m_tv_channels, *m_pad_channels, *m_input_channels, *m_portal_channels; + wxChoice *m_tv_channels, *m_pad_channels, *m_input_channels; wxChoice *m_tv_device, *m_pad_device, *m_input_device, *m_portal_device; // Account diff --git a/src/gui/dialogs/SaveImport/SaveImportWindow.cpp b/src/gui/dialogs/SaveImport/SaveImportWindow.cpp index b31f24b2..1b1fecbf 100644 --- a/src/gui/dialogs/SaveImport/SaveImportWindow.cpp +++ b/src/gui/dialogs/SaveImport/SaveImportWindow.cpp @@ -304,7 +304,7 @@ void SaveImportWindow::OnImport(wxCommandEvent& event) auto new_node = info_node.append_child("account"); new_node.append_attribute("persistentId").set_value(new_persistend_id_string.c_str()); auto timestamp = new_node.append_child("timestamp"); - timestamp.text().set(fmt::format("{:016x}", coreinit::coreinit_getOSTime() / ESPRESSO_TIMER_CLOCK).c_str()); // TODO time not initialized yet? + timestamp.text().set(fmt::format("{:016x}", coreinit::OSGetTime() / ESPRESSO_TIMER_CLOCK).c_str()); // TODO time not initialized yet? if(!doc.save_file(saveinfo.c_str())) cemuLog_log(LogType::Force, "couldn't insert save entry in saveinfo.xml: {}", _pathToUtf8(saveinfo)); diff --git a/src/imgui/imgui_impl_vulkan.cpp b/src/imgui/imgui_impl_vulkan.cpp index 723f153c..f9a23166 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)