Merge branch 'main' into metal

This commit is contained in:
SamoZ256 2024-11-01 15:56:10 +01:00 committed by GitHub
commit ed48fbfd55
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 485 additions and 243 deletions

View file

@ -47,7 +47,9 @@ const std::vector<const char*> kOptionalDeviceExtensions =
VK_EXT_FILTER_CUBIC_EXTENSION_NAME, // not supported by any device yet
VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME
VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME,
VK_KHR_PRESENT_WAIT_EXTENSION_NAME,
VK_KHR_PRESENT_ID_EXTENSION_NAME
};
const std::vector<const char*> kRequiredDeviceExtensions =
@ -252,12 +254,24 @@ void VulkanRenderer::GetDeviceFeatures()
pcc.pNext = prevStruct;
prevStruct = &pcc;
VkPhysicalDevicePresentIdFeaturesKHR pidf{};
pidf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR;
pidf.pNext = prevStruct;
prevStruct = &pidf;
VkPhysicalDevicePresentWaitFeaturesKHR pwf{};
pwf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR;
pwf.pNext = prevStruct;
prevStruct = &pwf;
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{};
physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
physicalDeviceFeatures2.pNext = prevStruct;
vkGetPhysicalDeviceFeatures2(m_physicalDevice, &physicalDeviceFeatures2);
cemuLog_log(LogType::Force, "Vulkan: present_wait extension: {}", (pwf.presentWait && pidf.presentId) ? "supported" : "unsupported");
/* Get Vulkan device properties and limits */
VkPhysicalDeviceFloatControlsPropertiesKHR pfcp{};
prevStruct = nullptr;
@ -490,6 +504,24 @@ VulkanRenderer::VulkanRenderer()
customBorderColorFeature.customBorderColors = VK_TRUE;
customBorderColorFeature.customBorderColorWithoutFormat = VK_TRUE;
}
// enable VK_KHR_present_id
VkPhysicalDevicePresentIdFeaturesKHR presentIdFeature{};
if(m_featureControl.deviceExtensions.present_wait)
{
presentIdFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR;
presentIdFeature.pNext = deviceExtensionFeatures;
deviceExtensionFeatures = &presentIdFeature;
presentIdFeature.presentId = VK_TRUE;
}
// enable VK_KHR_present_wait
VkPhysicalDevicePresentWaitFeaturesKHR presentWaitFeature{};
if(m_featureControl.deviceExtensions.present_wait)
{
presentWaitFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR;
presentWaitFeature.pNext = deviceExtensionFeatures;
deviceExtensionFeatures = &presentWaitFeature;
presentWaitFeature.presentWait = VK_TRUE;
}
std::vector<const char*> used_extensions;
VkDeviceCreateInfo createInfo = CreateDeviceCreateInfo(queueCreateInfos, deviceFeatures, deviceExtensionFeatures, used_extensions);
@ -1047,6 +1079,10 @@ VkDeviceCreateInfo VulkanRenderer::CreateDeviceCreateInfo(const std::vector<VkDe
used_extensions.emplace_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.shader_float_controls)
used_extensions.emplace_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.present_wait)
used_extensions.emplace_back(VK_KHR_PRESENT_ID_EXTENSION_NAME);
if (m_featureControl.deviceExtensions.present_wait)
used_extensions.emplace_back(VK_KHR_PRESENT_WAIT_EXTENSION_NAME);
VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@ -1144,6 +1180,7 @@ bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device,
info.deviceExtensions.shader_float_controls = isExtensionAvailable(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
info.deviceExtensions.dynamic_rendering = false; // isExtensionAvailable(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
// dynamic rendering doesn't provide any benefits for us right now. Driver implementations are very unoptimized as of Feb 2022
info.deviceExtensions.present_wait = isExtensionAvailable(VK_KHR_PRESENT_WAIT_EXTENSION_NAME) && isExtensionAvailable(VK_KHR_PRESENT_ID_EXTENSION_NAME);
// check for framedebuggers
info.debugMarkersSupported = false;
@ -1855,6 +1892,7 @@ void VulkanRenderer::ProcessFinishedCommandBuffers()
if (fenceStatus == VK_SUCCESS)
{
ProcessDestructionQueue();
m_uniformVarBufferReadIndex = m_cmdBufferUniformRingbufIndices[m_commandBufferSyncIndex];
m_commandBufferSyncIndex = (m_commandBufferSyncIndex + 1) % m_commandBuffers.size();
memoryManager->cleanupBuffers(m_countCommandBufferFinished);
m_countCommandBufferFinished++;
@ -1948,6 +1986,7 @@ void VulkanRenderer::SubmitCommandBuffer(VkSemaphore signalSemaphore, VkSemaphor
cemuLog_logDebug(LogType::Force, "Vulkan: Waiting for available command buffer...");
WaitForNextFinishedCommandBuffer();
}
m_cmdBufferUniformRingbufIndices[nextCmdBufferIndex] = m_cmdBufferUniformRingbufIndices[m_commandBufferIndex];
m_commandBufferIndex = nextCmdBufferIndex;
@ -2695,11 +2734,21 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
ClearColorImageRaw(chainInfo.m_swapchainImages[chainInfo.swapchainImageIndex], 0, 0, clearColor, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
}
const size_t currentFrameCmdBufferID = GetCurrentCommandBufferId();
VkSemaphore presentSemaphore = chainInfo.m_presentSemaphores[chainInfo.swapchainImageIndex];
SubmitCommandBuffer(presentSemaphore); // submit all command and signal semaphore
cemu_assert_debug(m_numSubmittedCmdBuffers > 0);
// wait for the previous frame to finish rendering
WaitCommandBufferFinished(m_commandBufferIDOfPrevFrame);
m_commandBufferIDOfPrevFrame = currentFrameCmdBufferID;
chainInfo.WaitAvailableFence();
VkPresentIdKHR presentId = {};
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.swapchainCount = 1;
@ -2709,6 +2758,24 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &presentSemaphore;
// if present_wait is available and enabled, add frame markers to present requests
// and limit the number of queued present operations
if (m_featureControl.deviceExtensions.present_wait && chainInfo.m_maxQueued > 0)
{
presentId.sType = VK_STRUCTURE_TYPE_PRESENT_ID_KHR;
presentId.swapchainCount = 1;
presentId.pPresentIds = &chainInfo.m_presentId;
presentInfo.pNext = &presentId;
if(chainInfo.m_queueDepth >= chainInfo.m_maxQueued)
{
uint64 waitFrameId = chainInfo.m_presentId - chainInfo.m_queueDepth;
vkWaitForPresentKHR(m_logicalDevice, chainInfo.m_swapchain, waitFrameId, 40'000'000);
chainInfo.m_queueDepth--;
}
}
VkResult result = vkQueuePresentKHR(m_presentQueue, &presentInfo);
if (result < 0 && result != VK_ERROR_OUT_OF_DATE_KHR)
{
@ -2717,6 +2784,12 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
chainInfo.m_shouldRecreate = true;
if(result >= 0)
{
chainInfo.m_queueDepth++;
chainInfo.m_presentId++;
}
chainInfo.hasDefinedSwapchainImage = false;
chainInfo.swapchainImageIndex = -1;
@ -3491,13 +3564,13 @@ void VulkanRenderer::buffer_bindUniformBuffer(LatteConst::ShaderType shaderType,
switch (shaderType)
{
case LatteConst::ShaderType::Vertex:
dynamicOffsetInfo.shaderUB[VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX].unformBufferOffset[bufferIndex] = offset;
dynamicOffsetInfo.shaderUB[VulkanRendererConst::SHADER_STAGE_INDEX_VERTEX].uniformBufferOffset[bufferIndex] = offset;
break;
case LatteConst::ShaderType::Geometry:
dynamicOffsetInfo.shaderUB[VulkanRendererConst::SHADER_STAGE_INDEX_GEOMETRY].unformBufferOffset[bufferIndex] = offset;
dynamicOffsetInfo.shaderUB[VulkanRendererConst::SHADER_STAGE_INDEX_GEOMETRY].uniformBufferOffset[bufferIndex] = offset;
break;
case LatteConst::ShaderType::Pixel:
dynamicOffsetInfo.shaderUB[VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT].unformBufferOffset[bufferIndex] = offset;
dynamicOffsetInfo.shaderUB[VulkanRendererConst::SHADER_STAGE_INDEX_FRAGMENT].uniformBufferOffset[bufferIndex] = offset;
break;
default:
cemu_assert_debug(false);