diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index 27c03edc..e669faac 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -310,8 +310,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { const auto& clearColor = MG_State::pGLContext->GetClearColor(); const auto clearDepth = MG_State::pGLContext->GetClearDepth(); const auto clearStencil = static_cast(MG_State::pGLContext->GetClearStencil()); - pVulkanRenderer->RequestClear(mask, clearColor, clearDepth, clearStencil, drawFboExternalIndex, - isDefaultFboTarget); + pVulkanRenderer->QueueClearRequest(mask, clearColor, clearDepth, clearStencil, + drawFboExternalIndex, + isDefaultFboTarget); } void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) { @@ -422,35 +423,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::BlitFramebuffer called with null VulkanRenderer"); - MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::BlitFramebuffer called with null GL context"); - - const auto& readFboSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read); - const auto& drawFboSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw); - const auto readFbo = readFboSlot.GetBoundObject(); - const auto drawFbo = drawFboSlot.GetBoundObject(); - const auto defaultFboInfo = MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo; - const auto defaultFbo = defaultFboInfo ? defaultFboInfo->defaultFBO : nullptr; - - const Bool readIsDefault = (readFbo == defaultFbo) || (readFbo == nullptr && defaultFbo != nullptr); - const Bool drawIsDefault = (drawFbo == defaultFbo) || (drawFbo == nullptr && defaultFbo != nullptr); - - Uint readFboExternalIndex = 0; - if (readFbo) { - readFboExternalIndex = readFbo->GetExternalIndex(); - } else if (defaultFbo) { - readFboExternalIndex = defaultFbo->GetExternalIndex(); - } - - Uint drawFboExternalIndex = 0; - if (drawFbo) { - drawFboExternalIndex = drawFbo->GetExternalIndex(); - } else if (defaultFbo) { - drawFboExternalIndex = defaultFbo->GetExternalIndex(); - } - - pVulkanRenderer->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, - readFboExternalIndex, drawFboExternalIndex, readIsDefault, drawIsDefault); } void Present() { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 33df2aa3..b93cb284 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -327,8 +327,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { MGLOG_I("VulkanRenderer shut down completed"); } - void VulkanRenderer::RequestClear(GLbitfield mask, const FloatVec4& color, Float depth, Uint32 stencil, - Uint drawFboExternalIndex, Bool isDefaultFramebufferTarget) { + void VulkanRenderer::QueueClearRequest(GLbitfield mask, const FloatVec4& color, Float depth, Uint32 stencil, + Uint drawFboExternalIndex, Bool isDefaultFramebufferTarget) { const GLbitfield supportedMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; const GLbitfield requestMask = (mask & supportedMask); if (requestMask == 0) { @@ -1190,600 +1190,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } - Bool VulkanRenderer::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, - GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter, - Uint readFboExternalIndex, Uint drawFboExternalIndex, - - Bool readIsDefaultFramebuffer, Bool drawIsDefaultFramebuffer) { - if ((mask & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) == 0) { - MGLOG_D("BlitFramebuffer skipped: empty mask"); - return false; - } - - VkFilter vkFilter = VK_FILTER_NEAREST; - if (filter == GL_NEAREST) { - vkFilter = VK_FILTER_NEAREST; - } else if (filter == GL_LINEAR) { - vkFilter = VK_FILTER_LINEAR; - } else { - MGLOG_W("BlitFramebuffer skipped: filter %u is not supported", filter); - return false; - } - - auto& frame = m_frameContext.GetCurrent(); - if (frame.hasCommandBufferRecorded) { - MGLOG_D("BlitFramebuffer skipped: current frame command buffer already finalized"); - return false; - } - - if (!frame.isCommandRecording) { - m_frameContext.BeginCommandRecording(); - MOBILEGL_ASSERT(m_uniformDescriptorBinder != nullptr, "BlitFramebuffer: binder is null"); - m_uniformDescriptorBinder->BeginFrame(m_frameContext.GetCurrentFrameIndex()); - } - - VkCommandBuffer commandBuffer = frame.commandBuffer; - if (m_isMainRenderPassActive) { - MOBILEGL_ASSERT(m_renderPassManager != nullptr, "BlitFramebuffer: render pass manager is null"); - m_renderPassManager->EndRenderPass(commandBuffer); - if (m_activeRenderTargetIsDefault) { - m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - } - m_isMainRenderPassActive = false; - m_activeRenderPass = VK_NULL_HANDLE; - m_activeRenderExtent = {0, 0}; - m_activeDepthStencilFormat = VK_FORMAT_UNDEFINED; - m_activeRenderTargetIsDefault = true; - m_activeDrawFboExternalIndex = 0; - } - - MOBILEGL_ASSERT(m_framebufferManager != nullptr, "BlitFramebuffer: framebuffer manager not available"); - MOBILEGL_ASSERT(m_renderPassManager != nullptr, "BlitFramebuffer: renderpass manager is null"); - - auto consumePendingClearForTarget = [&](Bool targetIsDefault, Uint targetFboExternalIndex) { - const Uint64 pendingKey = BuildPendingClearKey(targetFboExternalIndex, targetIsDefault); - auto pendingIt = m_pendingClears.find(pendingKey); - if (pendingIt == m_pendingClears.end()) { - return; - } - - const PendingClearState pending = pendingIt->second; - m_pendingClears.erase(pendingIt); - - const auto prevExtent = m_activeRenderExtent; - const auto prevDepthStencilFormat = m_activeDepthStencilFormat; - - if (targetIsDefault) { - TransitionSwapchainImageToColorAttachment(commandBuffer, m_imageIndexAcquired); - TransitionDepthStencilImageToAttachment(commandBuffer, m_imageIndexAcquired); - - VkRenderPass renderPass = VK_NULL_HANDLE; - VkFramebuffer framebuffer = VK_NULL_HANDLE; - VkExtent2D extent{}; - VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED; - if (!GetDefaultRenderTargetForCurrentImage(renderPass, framebuffer, extent, depthStencilFormat)) { - return; - } - m_renderPassManager->BeginRenderPass(commandBuffer, renderPass, framebuffer, extent); - - m_activeRenderExtent = extent; - m_activeDepthStencilFormat = depthStencilFormat; - - if ((pending.mask & GL_COLOR_BUFFER_BIT) != 0) { - m_renderPassManager->RecordColorClear(commandBuffer, m_activeRenderExtent, pending.color); - } - if ((pending.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) { - m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent, pending.mask, - pending.depth, pending.stencil, - m_activeDepthStencilFormat); - } - - m_renderPassManager->EndRenderPass(commandBuffer); - } else { - const auto targetFbo = MG_State::pGLContext->GetFramebufferObject(targetFboExternalIndex); - VkRenderPass offscreenRenderPass = VK_NULL_HANDLE; - VkFramebuffer offscreenFramebuffer = VK_NULL_HANDLE; - VkExtent2D offscreenExtent{}; - VkFormat offscreenDepthStencilFormat = VK_FORMAT_UNDEFINED; - if (targetFbo && - EnsureOffscreenRenderTarget(targetFboExternalIndex, *targetFbo, offscreenRenderPass, - offscreenFramebuffer, offscreenExtent, offscreenDepthStencilFormat) && - m_framebufferManager->Transition(commandBuffer, - VkRenderTargetManager::TransitionResource::OffscreenColor, - VkRenderTargetManager::TransitionUsage::Attachment, - targetFboExternalIndex)) { - m_renderPassManager->BeginRenderPass(commandBuffer, offscreenRenderPass, offscreenFramebuffer, - offscreenExtent); - - m_activeRenderExtent = offscreenExtent; - m_activeDepthStencilFormat = offscreenDepthStencilFormat; - - if ((pending.mask & GL_COLOR_BUFFER_BIT) != 0) { - m_renderPassManager->RecordColorClear(commandBuffer, m_activeRenderExtent, pending.color); - } - if ((pending.mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) { - m_renderPassManager->RecordDepthStencilClear(commandBuffer, m_activeRenderExtent, pending.mask, - pending.depth, pending.stencil, - m_activeDepthStencilFormat); - } - - m_renderPassManager->EndRenderPass(commandBuffer); - } - } - - m_activeRenderExtent = prevExtent; - m_activeDepthStencilFormat = prevDepthStencilFormat; - }; - - consumePendingClearForTarget(drawIsDefaultFramebuffer, drawFboExternalIndex); - - auto selectSrcStageAccess = [](VkImageLayout layout, VkPipelineStageFlags& outStage, VkAccessFlags& outAccess) { - switch (layout) { - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - outStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - outAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - outStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - outAccess = VK_ACCESS_TRANSFER_WRITE_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - outStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - outAccess = VK_ACCESS_TRANSFER_READ_BIT; - break; - case VK_IMAGE_LAYOUT_GENERAL: - outStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - outAccess = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - break; - case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: - default: - outStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - outAccess = 0; - break; - } - }; - - auto transitionSwapchainLayout = [&](VkImageLayout newLayout, VkPipelineStageFlags dstStage, - VkAccessFlags dstAccess) { - const auto oldLayout = m_swapchainObject.GetImageLayout(m_imageIndexAcquired); - if (oldLayout == newLayout) { - return; - } - VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkAccessFlags srcAccess = 0; - selectSrcStageAccess(oldLayout, srcStage, srcAccess); - - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccess; - barrier.dstAccessMask = dstAccess; - barrier.oldLayout = oldLayout; - barrier.newLayout = newLayout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = m_swapchainObject.GetImage(m_imageIndexAcquired); - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - - vkCmdPipelineBarrier(commandBuffer, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); - m_swapchainObject.SetImageLayout(m_imageIndexAcquired, newLayout); - }; - - auto clampCoord = [](GLint value, GLint minValue, GLint maxValue) -> GLint { - if (value < minValue) { - return minValue; - } - if (value > maxValue) { - return maxValue; - } - return value; - }; - - const Bool wantColor = (mask & GL_COLOR_BUFFER_BIT) != 0; - if (wantColor) { - VkImage srcImage = VK_NULL_HANDLE; - VkImage dstImage = VK_NULL_HANDLE; - VkExtent2D srcExtent{}; - VkExtent2D dstExtent{}; - - if (readIsDefaultFramebuffer) { - srcImage = m_swapchainObject.GetImage(m_imageIndexAcquired); - srcExtent = m_swapchainObject.GetExtent(); - } else { - const auto readFbo = MG_State::pGLContext->GetFramebufferObject(readFboExternalIndex); - if (!readFbo) { - MGLOG_W("BlitFramebuffer skipped: read FBO %u not found", readFboExternalIndex); - return false; - } - if (!m_framebufferManager->EnsureOffscreenColorTarget(readFboExternalIndex, *readFbo)) { - MGLOG_W("BlitFramebuffer skipped: failed to materialize read FBO %u", readFboExternalIndex); - return false; - } - if (!m_framebufferManager->GetOffscreenColorImage(readFboExternalIndex, srcImage, srcExtent)) { - MGLOG_W("BlitFramebuffer skipped: read FBO %u has no color target", readFboExternalIndex); - return false; - } - } - - if (drawIsDefaultFramebuffer) { - dstImage = m_swapchainObject.GetImage(m_imageIndexAcquired); - dstExtent = m_swapchainObject.GetExtent(); - } else { - const auto drawFbo = MG_State::pGLContext->GetFramebufferObject(drawFboExternalIndex); - if (!drawFbo) { - MGLOG_W("BlitFramebuffer skipped: draw FBO %u not found", drawFboExternalIndex); - return false; - } - if (!m_framebufferManager->EnsureOffscreenColorTarget(drawFboExternalIndex, *drawFbo)) { - MGLOG_W("BlitFramebuffer skipped: failed to materialize draw FBO %u", drawFboExternalIndex); - return false; - } - if (!m_framebufferManager->GetOffscreenColorImage(drawFboExternalIndex, dstImage, dstExtent)) { - MGLOG_W("BlitFramebuffer skipped: draw FBO %u has no color target", drawFboExternalIndex); - return false; - } - } - - if (srcImage == VK_NULL_HANDLE || dstImage == VK_NULL_HANDLE) { - MGLOG_W("BlitFramebuffer skipped: missing source/destination image"); - return false; - } - - const Bool sameImage = (srcImage == dstImage); - - if (readIsDefaultFramebuffer) { - if (sameImage) { - transitionSwapchainLayout(VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT); - } else { - transitionSwapchainLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT); - } - } else if (!m_framebufferManager->Transition(commandBuffer, - VkRenderTargetManager::TransitionResource::OffscreenColor, - VkRenderTargetManager::TransitionUsage::TransferSrc, - readFboExternalIndex)) { - MGLOG_W("BlitFramebuffer skipped: failed to transition read FBO %u to transfer src", - readFboExternalIndex); - return false; - } - - if (drawIsDefaultFramebuffer) { - if (sameImage) { - transitionSwapchainLayout(VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT); - } else { - transitionSwapchainLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT); - } - } else if (sameImage) { - if (!m_framebufferManager->Transition(commandBuffer, - VkRenderTargetManager::TransitionResource::OffscreenColor, - VkRenderTargetManager::TransitionUsage::General, - drawFboExternalIndex)) { - MGLOG_W("BlitFramebuffer skipped: failed to transition draw FBO %u to general", - drawFboExternalIndex); - return false; - } - } else if (!m_framebufferManager->Transition(commandBuffer, - VkRenderTargetManager::TransitionResource::OffscreenColor, - VkRenderTargetManager::TransitionUsage::TransferDst, - drawFboExternalIndex)) { - MGLOG_W("BlitFramebuffer skipped: failed to transition draw FBO %u to transfer dst", - drawFboExternalIndex); - return false; - } - - GLint srcX0Clamped = clampCoord(srcX0, 0, static_cast(srcExtent.width)); - GLint srcX1Clamped = clampCoord(srcX1, 0, static_cast(srcExtent.width)); - GLint srcY0Clamped = clampCoord(srcY0, 0, static_cast(srcExtent.height)); - GLint srcY1Clamped = clampCoord(srcY1, 0, static_cast(srcExtent.height)); - if (readIsDefaultFramebuffer) { - const GLint height = static_cast(srcExtent.height); - srcY0Clamped = height - srcY0Clamped; - srcY1Clamped = height - srcY1Clamped; - srcY0Clamped = clampCoord(srcY0Clamped, 0, height); - srcY1Clamped = clampCoord(srcY1Clamped, 0, height); - } - - GLint dstX0Clamped = clampCoord(dstX0, 0, static_cast(dstExtent.width)); - GLint dstX1Clamped = clampCoord(dstX1, 0, static_cast(dstExtent.width)); - GLint dstY0Clamped = clampCoord(dstY0, 0, static_cast(dstExtent.height)); - GLint dstY1Clamped = clampCoord(dstY1, 0, static_cast(dstExtent.height)); - if (drawIsDefaultFramebuffer) { - const GLint height = static_cast(dstExtent.height); - dstY0Clamped = height - dstY0Clamped; - dstY1Clamped = height - dstY1Clamped; - dstY0Clamped = clampCoord(dstY0Clamped, 0, height); - dstY1Clamped = clampCoord(dstY1Clamped, 0, height); - } - - if (srcX0Clamped == srcX1Clamped || srcY0Clamped == srcY1Clamped || dstX0Clamped == dstX1Clamped || - dstY0Clamped == dstY1Clamped) { - MGLOG_D("BlitFramebuffer skipped: empty blit region"); - return true; - } - - VkImageBlit blit{}; - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.mipLevel = 0; - blit.srcSubresource.baseArrayLayer = 0; - blit.srcSubresource.layerCount = 1; - blit.srcOffsets[0] = {srcX0Clamped, srcY0Clamped, 0}; - blit.srcOffsets[1] = {srcX1Clamped, srcY1Clamped, 1}; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.mipLevel = 0; - blit.dstSubresource.baseArrayLayer = 0; - blit.dstSubresource.layerCount = 1; - blit.dstOffsets[0] = {dstX0Clamped, dstY0Clamped, 0}; - blit.dstOffsets[1] = {dstX1Clamped, dstY1Clamped, 1}; - - const VkImageLayout srcLayout = sameImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - const VkImageLayout dstLayout = sameImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - vkCmdBlitImage(commandBuffer, srcImage, srcLayout, dstImage, dstLayout, 1, &blit, vkFilter); - } - - auto hasStencilComponent = [](VkFormat format) -> Bool { - return format == VK_FORMAT_D24_UNORM_S8_UINT || format == VK_FORMAT_D32_SFLOAT_S8_UINT; - }; - - const Bool wantDepth = (mask & GL_DEPTH_BUFFER_BIT) != 0; - const Bool wantStencil = (mask & GL_STENCIL_BUFFER_BIT) != 0; - - if (wantDepth || wantStencil) { - if (filter != GL_NEAREST) { - MGLOG_W("BlitFramebuffer: depth/stencil blit requires GL_NEAREST, overriding filter"); - vkFilter = VK_FILTER_NEAREST; - } - - VkImage srcDepthImage = VK_NULL_HANDLE; - VkImage dstDepthImage = VK_NULL_HANDLE; - VkExtent2D srcDepthExtent{}; - VkExtent2D dstDepthExtent{}; - VkFormat srcDepthFormat = VK_FORMAT_UNDEFINED; - VkFormat dstDepthFormat = VK_FORMAT_UNDEFINED; - - if (readIsDefaultFramebuffer) { - if (m_depthStencilImages.empty() || m_depthStencilFormat == VK_FORMAT_UNDEFINED) { - MGLOG_W("BlitFramebuffer: default framebuffer has no depth/stencil image"); - } else { - srcDepthImage = m_depthStencilImages[m_imageIndexAcquired]; - srcDepthExtent = m_swapchainObject.GetExtent(); - srcDepthFormat = m_depthStencilFormat; - } - } else { - const auto readFbo = MG_State::pGLContext->GetFramebufferObject(readFboExternalIndex); - if (!readFbo) { - MGLOG_W("BlitFramebuffer: read FBO %u not found", readFboExternalIndex); - } else if (!m_framebufferManager->EnsureOffscreenColorTarget(readFboExternalIndex, *readFbo)) { - MGLOG_W("BlitFramebuffer: failed to materialize read FBO %u for depth/stencil", - readFboExternalIndex); - } else if (!m_framebufferManager->GetOffscreenDepthStencilImage(readFboExternalIndex, srcDepthImage, - srcDepthExtent, srcDepthFormat)) { - MGLOG_W("BlitFramebuffer: read FBO %u has no depth/stencil image", readFboExternalIndex); - } - } - - if (drawIsDefaultFramebuffer) { - if (m_depthStencilImages.empty() || m_depthStencilFormat == VK_FORMAT_UNDEFINED) { - MGLOG_W("BlitFramebuffer: default framebuffer has no depth/stencil image"); - } else { - dstDepthImage = m_depthStencilImages[m_imageIndexAcquired]; - dstDepthExtent = m_swapchainObject.GetExtent(); - dstDepthFormat = m_depthStencilFormat; - } - } else { - const auto drawFbo = MG_State::pGLContext->GetFramebufferObject(drawFboExternalIndex); - if (!drawFbo) { - MGLOG_W("BlitFramebuffer: draw FBO %u not found", drawFboExternalIndex); - } else if (!m_framebufferManager->EnsureOffscreenColorTarget(drawFboExternalIndex, *drawFbo)) { - MGLOG_W("BlitFramebuffer: failed to materialize draw FBO %u for depth/stencil", - drawFboExternalIndex); - } else if (!m_framebufferManager->GetOffscreenDepthStencilImage(drawFboExternalIndex, dstDepthImage, - dstDepthExtent, dstDepthFormat)) { - MGLOG_W("BlitFramebuffer: draw FBO %u has no depth/stencil image", drawFboExternalIndex); - } - } - - if (srcDepthImage != VK_NULL_HANDLE && dstDepthImage != VK_NULL_HANDLE) { - if (srcDepthFormat != dstDepthFormat) { - MGLOG_W("BlitFramebuffer: depth/stencil format mismatch (src=%d, dst=%d), skipping", srcDepthFormat, - dstDepthFormat); - } else { - VkImageAspectFlags srcAspectMask = 0; - VkImageAspectFlags dstAspectMask = 0; - if (wantDepth) { - srcAspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; - dstAspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; - } - if (wantStencil && hasStencilComponent(srcDepthFormat)) { - srcAspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - dstAspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } else if (wantStencil) { - MGLOG_W("BlitFramebuffer: stencil bit requested but format has no stencil component"); - } - - const VkImageAspectFlags aspectMask = srcAspectMask & dstAspectMask; - if (aspectMask != 0) { - const Bool sameDepthImage = (srcDepthImage == dstDepthImage); - const VkImageAspectFlags fullAspectMask = - VK_IMAGE_ASPECT_DEPTH_BIT | - (hasStencilComponent(srcDepthFormat) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0); - - auto transitionDefaultDepthStencil = [&](VkImageLayout newLayout, VkPipelineStageFlags dstStage, - VkAccessFlags dstAccess) { - if (m_depthStencilImages.empty()) { - return; - } - const auto oldLayout = m_depthStencilImageLayouts[m_imageIndexAcquired]; - if (oldLayout == newLayout) { - return; - } - VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkAccessFlags srcAccess = 0; - switch (oldLayout) { - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - srcStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - srcAccess = VK_ACCESS_TRANSFER_READ_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - srcAccess = VK_ACCESS_TRANSFER_WRITE_BIT; - break; - case VK_IMAGE_LAYOUT_GENERAL: - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - srcAccess = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - break; - default: - srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - srcAccess = 0; - break; - } - - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccess; - barrier.dstAccessMask = dstAccess; - barrier.oldLayout = oldLayout; - barrier.newLayout = newLayout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = m_depthStencilImages[m_imageIndexAcquired]; - barrier.subresourceRange.aspectMask = fullAspectMask; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - - vkCmdPipelineBarrier(commandBuffer, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, - &barrier); - m_depthStencilImageLayouts[m_imageIndexAcquired] = newLayout; - }; - - if (readIsDefaultFramebuffer) { - if (sameDepthImage) { - transitionDefaultDepthStencil(VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT | - VK_ACCESS_TRANSFER_WRITE_BIT); - } else { - transitionDefaultDepthStencil(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT); - } - } else if (!m_framebufferManager->Transition( - commandBuffer, VkRenderTargetManager::TransitionResource::OffscreenDepthStencil, - VkRenderTargetManager::TransitionUsage::TransferSrc, readFboExternalIndex)) { - MGLOG_W("BlitFramebuffer: failed to transition read depth/stencil FBO %u to transfer src", - readFboExternalIndex); - } - - if (drawIsDefaultFramebuffer) { - if (sameDepthImage) { - transitionDefaultDepthStencil(VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT | - VK_ACCESS_TRANSFER_WRITE_BIT); - } else { - transitionDefaultDepthStencil(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT); - } - } else if (sameDepthImage) { - if (!m_framebufferManager->Transition( - commandBuffer, VkRenderTargetManager::TransitionResource::OffscreenDepthStencil, - VkRenderTargetManager::TransitionUsage::General, drawFboExternalIndex)) { - MGLOG_W("BlitFramebuffer: failed to transition draw depth/stencil FBO %u to general", - drawFboExternalIndex); - } - } else if (!m_framebufferManager->Transition( - commandBuffer, VkRenderTargetManager::TransitionResource::OffscreenDepthStencil, - VkRenderTargetManager::TransitionUsage::TransferDst, drawFboExternalIndex)) { - MGLOG_W("BlitFramebuffer: failed to transition draw depth/stencil FBO %u to transfer dst", - drawFboExternalIndex); - } - - GLint srcDX0 = clampCoord(srcX0, 0, static_cast(srcDepthExtent.width)); - GLint srcDX1 = clampCoord(srcX1, 0, static_cast(srcDepthExtent.width)); - GLint srcDY0 = clampCoord(srcY0, 0, static_cast(srcDepthExtent.height)); - GLint srcDY1 = clampCoord(srcY1, 0, static_cast(srcDepthExtent.height)); - if (readIsDefaultFramebuffer) { - const GLint height = static_cast(srcDepthExtent.height); - srcDY0 = height - srcDY0; - srcDY1 = height - srcDY1; - srcDY0 = clampCoord(srcDY0, 0, height); - srcDY1 = clampCoord(srcDY1, 0, height); - } - - GLint dstDX0 = clampCoord(dstX0, 0, static_cast(dstDepthExtent.width)); - GLint dstDX1 = clampCoord(dstX1, 0, static_cast(dstDepthExtent.width)); - GLint dstDY0 = clampCoord(dstY0, 0, static_cast(dstDepthExtent.height)); - GLint dstDY1 = clampCoord(dstY1, 0, static_cast(dstDepthExtent.height)); - if (drawIsDefaultFramebuffer) { - const GLint height = static_cast(dstDepthExtent.height); - dstDY0 = height - dstDY0; - dstDY1 = height - dstDY1; - dstDY0 = clampCoord(dstDY0, 0, height); - dstDY1 = clampCoord(dstDY1, 0, height); - } - - if (srcDX0 != srcDX1 && srcDY0 != srcDY1 && dstDX0 != dstDX1 && dstDY0 != dstDY1) { - VkImageBlit depthBlit{}; - depthBlit.srcSubresource.aspectMask = aspectMask; - depthBlit.srcSubresource.mipLevel = 0; - depthBlit.srcSubresource.baseArrayLayer = 0; - depthBlit.srcSubresource.layerCount = 1; - depthBlit.srcOffsets[0] = {srcDX0, srcDY0, 0}; - depthBlit.srcOffsets[1] = {srcDX1, srcDY1, 1}; - depthBlit.dstSubresource.aspectMask = aspectMask; - depthBlit.dstSubresource.mipLevel = 0; - depthBlit.dstSubresource.baseArrayLayer = 0; - depthBlit.dstSubresource.layerCount = 1; - depthBlit.dstOffsets[0] = {dstDX0, dstDY0, 0}; - depthBlit.dstOffsets[1] = {dstDX1, dstDY1, 1}; - - const VkImageLayout depthSrcLayout = - sameDepthImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - const VkImageLayout depthDstLayout = - sameDepthImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - vkCmdBlitImage(commandBuffer, srcDepthImage, depthSrcLayout, dstDepthImage, depthDstLayout, - 1, &depthBlit, vkFilter); - } - } - } - } - } - - if (readIsDefaultFramebuffer || drawIsDefaultFramebuffer) { - transitionSwapchainLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0); - } - - return true; - } - - void VulkanRenderer::Render() { - // Route test rendering through the same frame-start logic used by draw calls, - // so pending glClear() state can be consumed consistently. - EnsureFrameRecordingStarted(); - auto& frame = m_frameContext.GetCurrent(); - if (!frame.isCommandRecording || !m_isMainRenderPassActive) { - MGLOG_D("Render skipped: frame recording was not started"); - return; - } - - VkCommandBuffer& commandBuffer = frame.commandBuffer; - const auto swapchainExtent = m_swapchainObject.GetExtent(); - - (void)commandBuffer; - (void)swapchainExtent; - } - void VulkanRenderer::Present() { MOBILEGL_ASSERT(m_imageIndexAcquired < m_swapchainObject.GetImageCount(), "Present, acquired image index out of range"); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 2297c26b..0e0ad9d8 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -70,17 +70,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { void Initialize(); void Shutdown(); - void RequestClear(GLbitfield mask, const FloatVec4& color, Float depth, Uint32 stencil, - Uint drawFboExternalIndex, Bool isDefaultFramebufferTarget); + void QueueClearRequest(GLbitfield mask, const FloatVec4& color, Float depth, Uint32 stencil, + Uint drawFboExternalIndex, Bool isDefaultFramebufferTarget); Bool ConsumePendingColorClear(VkClearColorValue& outClearColor); void EnsureFrameRecordingStarted(); void DrawArrays(const DrawArrayPayload& payload); void DrawElements(const DrawElementPayload& payload); void MultiDrawElements(const Vector& payloads); - Bool BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, - GLint dstY1, GLbitfield mask, GLenum filter, Uint readFboExternalIndex, - Uint drawFboExternalIndex, Bool readIsDefaultFramebuffer, Bool drawIsDefaultFramebuffer); - void Render(); void Present(); const PhysicalDevice& GetPhysicalDevice() const;