mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-06 06:51:18 +12:00
Merge branch 'main' into metal
This commit is contained in:
commit
ed48fbfd55
35 changed files with 485 additions and 243 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue