From 02594b9d6e9fb0bac2d67720e04b32fa804dd708 Mon Sep 17 00:00:00 2001 From: Cherser-s <29800876+Cherser-s@users.noreply.github.com> Date: Sat, 27 Nov 2021 11:43:27 +0300 Subject: [PATCH] mantle: add attachment clears through render pass --- src/mantle/mantle_cmd_buf.c | 356 +++++++++++++++++++++++++++++--- src/mantle/mantle_cmd_buf_man.c | 3 + src/mantle/mantle_object.h | 22 ++ 3 files changed, 349 insertions(+), 32 deletions(-) diff --git a/src/mantle/mantle_cmd_buf.c b/src/mantle/mantle_cmd_buf.c index 5cdffec5..4fe6dce8 100644 --- a/src/mantle/mantle_cmd_buf.c +++ b/src/mantle/mantle_cmd_buf.c @@ -167,6 +167,46 @@ static void grCmdBufferBeginRenderPass( return; } + // TODO: handle clears in other place if the extent isn't full + for (unsigned i = 0; i < grCmdBuffer->colorAttachmentCount; ++i) { + for (unsigned j = 0; j < grCmdBuffer->clearAttachmentCount; ++j) { + if (!grCmdBuffer->clearAttachments[j].isDepthStencil && + grCmdBuffer->clearAttachments[j].performClear && + grCmdBuffer->colorAttachmentImages[i] == grCmdBuffer->clearAttachments[j].image && + memcmp(&grCmdBuffer->colorAttachmentRanges[i], &grCmdBuffer->clearAttachments[j].range, sizeof(VkImageSubresourceRange)) == 0) { + grCmdBuffer->colorAttachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + grCmdBuffer->colorAttachments[i].clearValue = grCmdBuffer->clearAttachments[j].clearValue; + + grCmdBuffer->clearAttachments[j].ignore = true; + break; + } + } + } + if (grCmdBuffer->hasDepthStencil) { + for (unsigned j = 0; j < grCmdBuffer->clearAttachmentCount; ++j) { + if (grCmdBuffer->clearAttachments[j].isDepthStencil && + grCmdBuffer->clearAttachments[j].performClear && + grCmdBuffer->depthImage == grCmdBuffer->clearAttachments[j].image && + // can't perform a full compare since the client may specify only depth or only stencil + grCmdBuffer->depthRange.baseArrayLayer == grCmdBuffer->clearAttachments[j].range.baseArrayLayer && + grCmdBuffer->depthRange.layerCount == grCmdBuffer->clearAttachments[j].range.layerCount && + grCmdBuffer->depthRange.baseMipLevel == grCmdBuffer->clearAttachments[j].range.baseMipLevel && + grCmdBuffer->depthRange.levelCount == grCmdBuffer->clearAttachments[j].range.levelCount) { + if (grCmdBuffer->clearAttachments[j].range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) { + grCmdBuffer->depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + grCmdBuffer->depthAttachment.clearValue = grCmdBuffer->clearAttachments[j].clearValue; + } + if (grCmdBuffer->clearAttachments[j].range.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) { + grCmdBuffer->stencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + grCmdBuffer->stencilAttachment.clearValue = grCmdBuffer->clearAttachments[j].clearValue; + } + + grCmdBuffer->clearAttachments[j].ignore = true; + break; + } + } + } + const VkRenderingInfoKHR renderingInfo = { .sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, .pNext = NULL, @@ -183,8 +223,20 @@ static void grCmdBufferBeginRenderPass( .pStencilAttachment = grCmdBuffer->hasDepthStencil ? &grCmdBuffer->stencilAttachment : NULL, }; + grCmdFlushClearImages(grCmdBuffer); VKD.vkCmdBeginRenderingKHR(grCmdBuffer->commandBuffer, &renderingInfo); grCmdBuffer->isRendering = true; + // remove clear values, so attachments won't be cleared on restart + for (unsigned i = 0; i < grCmdBuffer->colorAttachmentCount; ++i) { + grCmdBuffer->colorAttachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + grCmdBuffer->colorAttachments[i].clearValue = (VkClearValue) {{{ 0 }}}; + } + if (grCmdBuffer->hasDepthStencil) { + grCmdBuffer->depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + grCmdBuffer->depthAttachment.clearValue = (VkClearValue) {{{ 0 }}}; + grCmdBuffer->stencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + grCmdBuffer->stencilAttachment.clearValue = (VkClearValue) {{{ 0 }}}; + } } void grCmdBufferEndRenderPass( @@ -600,10 +652,14 @@ GR_VOID GR_STDCALL grCmdBindTargets( unsigned colorAttachmentCount = 0; VkRenderingAttachmentInfoKHR colorAttachments[GR_MAX_COLOR_TARGETS]; + VkImageSubresourceRange colorAttachmentRanges[GR_MAX_COLOR_TARGETS]; + VkImage colorAttachmentImages[GR_MAX_COLOR_TARGETS]; VkFormat colorFormats[GR_MAX_COLOR_TARGETS]; bool hasDepthStencil = false; VkRenderingAttachmentInfoKHR depthAttachment; VkRenderingAttachmentInfoKHR stencilAttachment; + VkImageSubresourceRange depthRange; + VkImage depthImage; VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED; VkExtent3D minExtent = { UINT32_MAX, UINT32_MAX, UINT32_MAX }; @@ -623,6 +679,8 @@ GR_VOID GR_STDCALL grCmdBindTargets( .storeOp = VK_ATTACHMENT_STORE_OP_STORE, .clearValue = {{{ 0 }}}, }; + colorAttachmentRanges[colorAttachmentCount] = grColorTargetView->subresourceRange; + colorAttachmentImages[colorAttachmentCount] = grColorTargetView->grParentImage->image; colorFormats[colorAttachmentCount] = grColorTargetView->format; colorAttachmentCount++; @@ -660,6 +718,8 @@ GR_VOID GR_STDCALL grCmdBindTargets( .storeOp = VK_ATTACHMENT_STORE_OP_STORE, .clearValue = {{{ 0 }}}, }; + depthRange = grDepthStencilView->subresourceRange; + depthImage = grDepthStencilView->grParentImage->image; depthStencilFormat = grDepthStencilView->format; minExtent.width = MIN(minExtent.width, grDepthStencilView->extent.width); @@ -676,9 +736,13 @@ GR_VOID GR_STDCALL grCmdBindTargets( // Targets have changed grCmdBuffer->colorAttachmentCount = colorAttachmentCount; memcpy(grCmdBuffer->colorAttachments, colorAttachments, colorAttachmentCount * sizeof(colorAttachments[0])); + memcpy(grCmdBuffer->colorAttachmentRanges, colorAttachmentRanges, colorAttachmentCount * sizeof(colorAttachmentRanges[0])); + memcpy(grCmdBuffer->colorAttachmentImages, colorAttachmentImages, colorAttachmentCount * sizeof(colorAttachmentImages[0])); grCmdBuffer->hasDepthStencil = hasDepthStencil; grCmdBuffer->depthAttachment = depthAttachment; grCmdBuffer->stencilAttachment = stencilAttachment; + grCmdBuffer->depthRange = depthRange; + grCmdBuffer->depthImage = depthImage; grCmdBuffer->minExtent = minExtent; bindPoint->dirtyFlags |= FLAG_DIRTY_RENDER_PASS; @@ -712,32 +776,81 @@ GR_VOID GR_STDCALL grCmdPrepareImages( STACK_ARRAY(VkImageMemoryBarrier, barriers, 128, transitionCount); VkPipelineStageFlags srcStageMask = 0; VkPipelineStageFlags dstStageMask = 0; + unsigned barrierCount = 0; for (unsigned i = 0; i < transitionCount; i++) { const GR_IMAGE_STATE_TRANSITION* stateTransition = &pStateTransitions[i]; GrImage* grImage = (GrImage*)stateTransition->image; bool isDepthStencil = isVkFormatDepthStencil(grImage->format); - barriers[i] = (VkImageMemoryBarrier) { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = NULL, - .srcAccessMask = getVkAccessFlagsImage(stateTransition->oldState, isDepthStencil), - .dstAccessMask = getVkAccessFlagsImage(stateTransition->newState, isDepthStencil), - .oldLayout = getVkImageLayout(stateTransition->oldState, isDepthStencil), - .newLayout = getVkImageLayout(stateTransition->newState, isDepthStencil), - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = grImage->image, - .subresourceRange = getVkImageSubresourceRange(stateTransition->subresourceRange, - grImage->multiplyCubeLayers), - }; + VkImageSubresourceRange subresourceRange = getVkImageSubresourceRange(stateTransition->subresourceRange, + grImage->multiplyCubeLayers); + bool placeBarrier = true; + // TODO: handle cases if level count or layer count are above 1 to avoid bugs due to intersections + if (subresourceRange.levelCount == 1 && + subresourceRange.layerCount == 1 && + grImage->usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && + (stateTransition->oldState == GR_IMAGE_STATE_CLEAR || stateTransition->newState == GR_IMAGE_STATE_CLEAR)) { + for (unsigned i = 0; i < grCmdBuffer->clearAttachmentCount; ++i) { + if (grCmdBuffer->clearAttachments[i].image == grImage->image && + memcmp(&grCmdBuffer->clearAttachments[i].range, &subresourceRange, sizeof(VkImageSubresourceRange)) == 0) { + if (stateTransition->oldState == GR_IMAGE_STATE_CLEAR) { + grCmdBuffer->clearAttachments[i].newLayout = getVkImageLayout(stateTransition->newState, isDepthStencil); + } else if (stateTransition->newState == GR_IMAGE_STATE_CLEAR) { + LOGW("transition to clear with existing overlap\n"); + // HACK: probably shouldn't happen if usage is valid + grCmdBuffer->clearAttachments[i].oldLayout = getVkImageLayout(stateTransition->oldState, isDepthStencil); + grCmdBuffer->clearAttachments[i].hasSrcBarrier = true; + } + placeBarrier = false; + break; + } + } + if (placeBarrier && grCmdBuffer->clearAttachmentCount < COUNT_OF(grCmdBuffer->clearAttachments)) { + // add a new entry + placeBarrier = false; + grCmdBuffer->clearAttachmentCount++; + grCmdBuffer->clearAttachments[grCmdBuffer->clearAttachmentCount - 1] = (GrClearImageState) { + .image = grImage->image, + .isDepthStencil = isVkFormatDepthStencil(grImage->format), + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .hasSrcBarrier = false, + .newLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .range = subresourceRange, + .performClear = false, + .ignore = false, + }; + if (stateTransition->oldState == GR_IMAGE_STATE_CLEAR) { + grCmdBuffer->clearAttachments[grCmdBuffer->clearAttachmentCount - 1].newLayout = getVkImageLayout(stateTransition->newState, isDepthStencil); + } else if (stateTransition->newState == GR_IMAGE_STATE_CLEAR) { + // HACK: probably shouldn't happen if usage is valid + grCmdBuffer->clearAttachments[grCmdBuffer->clearAttachmentCount - 1].oldLayout = getVkImageLayout(stateTransition->oldState, isDepthStencil); + grCmdBuffer->clearAttachments[grCmdBuffer->clearAttachmentCount - 1].hasSrcBarrier = true; + } + } + } + if (placeBarrier) { + barriers[barrierCount++] = (VkImageMemoryBarrier) { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = NULL, + .srcAccessMask = getVkAccessFlagsImage(stateTransition->oldState, isDepthStencil), + .dstAccessMask = getVkAccessFlagsImage(stateTransition->newState, isDepthStencil), + .oldLayout = getVkImageLayout(stateTransition->oldState, isDepthStencil), + .newLayout = getVkImageLayout(stateTransition->newState, isDepthStencil), + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = grImage->image, + .subresourceRange = subresourceRange, + }; - srcStageMask |= getVkPipelineStageFlagsImage(stateTransition->oldState); - dstStageMask |= getVkPipelineStageFlagsImage(stateTransition->newState); + srcStageMask |= getVkPipelineStageFlagsImage(stateTransition->oldState); + dstStageMask |= getVkPipelineStageFlagsImage(stateTransition->newState); + } } - VKD.vkCmdPipelineBarrier(grCmdBuffer->commandBuffer, srcStageMask, dstStageMask, - 0, 0, NULL, 0, NULL, transitionCount, barriers); + VKD.vkCmdPipelineBarrier(grCmdBuffer->commandBuffer, + srcStageMask, dstStageMask, + 0, 0, NULL, 0, NULL, barrierCount, barriers); STACK_ARRAY_FINISH(barriers); } @@ -1125,6 +1238,69 @@ GR_VOID GR_STDCALL grCmdFillMemory( fillSize, data); } +void grCmdFlushClearImages( + GrCmdBuffer* grCmdBuffer) +{ + GrDevice* grDevice = GET_OBJ_DEVICE(grCmdBuffer); + + for (unsigned i = 0; i < grCmdBuffer->clearAttachmentCount; i++) { + if (grCmdBuffer->clearAttachments[i].ignore) { + continue; + } + if (grCmdBuffer->clearAttachments[i].hasSrcBarrier) { + VkImageMemoryBarrier barrier = (VkImageMemoryBarrier) { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = NULL, + // TODO: grab aspectMask from the barrier declaration + .srcAccessMask = grCmdBuffer->clearAttachments[i].range.aspectMask, + .dstAccessMask = grCmdBuffer->clearAttachments[i].range.aspectMask, + .oldLayout = grCmdBuffer->clearAttachments[i].oldLayout, + .newLayout = getVkImageLayout(GR_IMAGE_STATE_CLEAR, grCmdBuffer->clearAttachments[i].isDepthStencil), + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = grCmdBuffer->clearAttachments[i].image, + .subresourceRange = grCmdBuffer->clearAttachments[i].range, + }; + VKD.vkCmdPipelineBarrier(grCmdBuffer->commandBuffer, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // TODO optimize + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, NULL, 0, NULL, 1, &barrier); + } + if (grCmdBuffer->clearAttachments[i].performClear && !grCmdBuffer->clearAttachments[i].isDepthStencil) { + VKD.vkCmdClearColorImage(grCmdBuffer->commandBuffer, grCmdBuffer->clearAttachments[i].image, + getVkImageLayout(GR_IMAGE_STATE_CLEAR, true), + &grCmdBuffer->clearAttachments[i].clearValue.color, + 1, &grCmdBuffer->clearAttachments[i].range); + } else if (grCmdBuffer->clearAttachments[i].performClear) { + VKD.vkCmdClearDepthStencilImage(grCmdBuffer->commandBuffer, grCmdBuffer->clearAttachments[i].image, + getVkImageLayout(GR_IMAGE_STATE_CLEAR, false), + &grCmdBuffer->clearAttachments[i].clearValue.depthStencil, + 1, &grCmdBuffer->clearAttachments[i].range); + } + if (grCmdBuffer->clearAttachments[i].newLayout != VK_IMAGE_LAYOUT_UNDEFINED) { + VkImageMemoryBarrier barrier = (VkImageMemoryBarrier) { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = NULL, + // TODO: grab aspectMask from the barrier declaration + .srcAccessMask = grCmdBuffer->clearAttachments[i].range.aspectMask, + .dstAccessMask = grCmdBuffer->clearAttachments[i].range.aspectMask, + .oldLayout = getVkImageLayout(GR_IMAGE_STATE_CLEAR, grCmdBuffer->clearAttachments[i].isDepthStencil), + .newLayout = grCmdBuffer->clearAttachments[i].newLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = grCmdBuffer->clearAttachments[i].image, + .subresourceRange = grCmdBuffer->clearAttachments[i].range, + }; + VKD.vkCmdPipelineBarrier(grCmdBuffer->commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // TODO optimize + 0, 0, NULL, 0, NULL, 1, &barrier); + } + } + + grCmdBuffer->clearAttachmentCount = 0; +} + GR_VOID GR_STDCALL grCmdClearColorImage( GR_CMD_BUFFER cmdBuffer, GR_IMAGE image, @@ -1145,15 +1321,52 @@ GR_VOID GR_STDCALL grCmdClearColorImage( }; STACK_ARRAY(VkImageSubresourceRange, vkRanges, 128, rangeCount); + unsigned vkRangeCount = 0; + bool isRenderTargetImage = (grImage->usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)); for (unsigned i = 0; i < rangeCount; i++) { - vkRanges[i] = getVkImageSubresourceRange(pRanges[i], grImage->multiplyCubeLayers); + VkImageSubresourceRange vkRange = getVkImageSubresourceRange(pRanges[i], grImage->multiplyCubeLayers); + bool performImmediateClear = true; + if (isRenderTargetImage && + vkRange.levelCount == 1 && vkRange.layerCount == 1) { + // try to find an image + for (unsigned j = 0; j < grCmdBuffer->clearAttachmentCount; ++j) { + if (grCmdBuffer->clearAttachments[j].image == grImage->image && + memcmp(&grCmdBuffer->clearAttachments[j].range, &vkRange, sizeof(VkImageSubresourceRange)) == 0) { + grCmdBuffer->clearAttachments[j].performClear = true; + grCmdBuffer->clearAttachments[j].clearValue = (VkClearValue) { .color = vkColor }; + performImmediateClear = false; + break; + } + } + if (performImmediateClear && grCmdBuffer->clearAttachmentCount < COUNT_OF(grCmdBuffer->clearAttachments)) { + // add a new entry + performImmediateClear = false; + grCmdBuffer->clearAttachmentCount++; + grCmdBuffer->clearAttachments[grCmdBuffer->clearAttachmentCount - 1] = (GrClearImageState) { + .image = grImage->image, + .isDepthStencil = false, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .hasSrcBarrier = false, + .newLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .range = vkRange, + .performClear = true, + .ignore = false, + .clearValue = { .color = vkColor }, + }; + } + } + if (performImmediateClear) { + vkRangeCount++; + vkRanges[vkRangeCount - 1] = vkRange; + } } - VKD.vkCmdClearColorImage(grCmdBuffer->commandBuffer, grImage->image, - getVkImageLayout(GR_IMAGE_STATE_CLEAR, false), - &vkColor, rangeCount, vkRanges); - + if (vkRangeCount > 0) { + VKD.vkCmdClearColorImage(grCmdBuffer->commandBuffer, grImage->image, + getVkImageLayout(GR_IMAGE_STATE_CLEAR, false), + &vkColor, vkRangeCount, vkRanges); + } STACK_ARRAY_FINISH(vkRanges); } @@ -1177,15 +1390,52 @@ GR_VOID GR_STDCALL grCmdClearColorImageRaw( }; STACK_ARRAY(VkImageSubresourceRange, vkRanges, 128, rangeCount); + unsigned vkRangeCount = 0; + bool isRenderTargetImage = (grImage->usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)); for (unsigned i = 0; i < rangeCount; i++) { - vkRanges[i] = getVkImageSubresourceRange(pRanges[i], grImage->multiplyCubeLayers); + VkImageSubresourceRange vkRange = getVkImageSubresourceRange(pRanges[i], grImage->multiplyCubeLayers); + bool performImmediateClear = true; + if (isRenderTargetImage && + vkRange.levelCount == 1 && vkRange.layerCount == 1) { + // try to find an image + for (unsigned j = 0; j < grCmdBuffer->clearAttachmentCount; ++j) { + if (grCmdBuffer->clearAttachments[j].image == grImage->image && + memcmp(&grCmdBuffer->clearAttachments[j].range, &vkRange, sizeof(VkImageSubresourceRange)) == 0) { + grCmdBuffer->clearAttachments[j].performClear = true; + grCmdBuffer->clearAttachments[j].clearValue = (VkClearValue) { .color = vkColor }; + performImmediateClear = false; + break; + } + } + if (performImmediateClear && grCmdBuffer->clearAttachmentCount < COUNT_OF(grCmdBuffer->clearAttachments)) { + // add a new entry + performImmediateClear = false; + grCmdBuffer->clearAttachmentCount++; + grCmdBuffer->clearAttachments[grCmdBuffer->clearAttachmentCount - 1] = (GrClearImageState) { + .image = grImage->image, + .isDepthStencil = false, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .hasSrcBarrier = false, + .newLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .range = vkRange, + .performClear = true, + .ignore = false, + .clearValue = { .color = vkColor }, + }; + } + } + if (performImmediateClear) { + vkRangeCount++; + vkRanges[vkRangeCount - 1] = vkRange; + } } - VKD.vkCmdClearColorImage(grCmdBuffer->commandBuffer, grImage->image, - getVkImageLayout(GR_IMAGE_STATE_CLEAR, false), - &vkColor, rangeCount, vkRanges); - + if (vkRangeCount > 0) { + VKD.vkCmdClearColorImage(grCmdBuffer->commandBuffer, grImage->image, + getVkImageLayout(GR_IMAGE_STATE_CLEAR, false), + &vkColor, vkRangeCount, vkRanges); + } STACK_ARRAY_FINISH(vkRanges); } @@ -1210,15 +1460,57 @@ GR_VOID GR_STDCALL grCmdClearDepthStencil( }; STACK_ARRAY(VkImageSubresourceRange, vkRanges, 128, rangeCount); + unsigned vkRangeCount = 0; + bool isRenderTargetImage = (grImage->usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)); for (unsigned i = 0; i < rangeCount; i++) { - vkRanges[i] = getVkImageSubresourceRange(pRanges[i], grImage->multiplyCubeLayers); + VkImageSubresourceRange vkRange = getVkImageSubresourceRange(pRanges[i], grImage->multiplyCubeLayers); + bool performImmediateClear = true; + if (isRenderTargetImage && + vkRange.levelCount == 1 && vkRange.layerCount == 1) { + LOGT("checking for render target clear image\n"); + // try to find an image + for (unsigned j = 0; j < grCmdBuffer->clearAttachmentCount; ++j) { + if (grCmdBuffer->clearAttachments[j].image == grImage->image && + memcmp(&grCmdBuffer->clearAttachments[j].range, &vkRange, sizeof(VkImageSubresourceRange)) == 0) { + if (!grCmdBuffer->clearAttachments[j].isDepthStencil) { + LOGT("cached clear state isn't depthstencil\n"); + grCmdBuffer->clearAttachments[j].isDepthStencil = true; + } + grCmdBuffer->clearAttachments[j].performClear = true; + grCmdBuffer->clearAttachments[j].clearValue = (VkClearValue) { .depthStencil = depthStencilValue }; + performImmediateClear = false; + break; + } + } + if (performImmediateClear && grCmdBuffer->clearAttachmentCount < COUNT_OF(grCmdBuffer->clearAttachments)) { + // add a new entry + performImmediateClear = false; + grCmdBuffer->clearAttachmentCount++; + grCmdBuffer->clearAttachments[grCmdBuffer->clearAttachmentCount - 1] = (GrClearImageState) { + .image = grImage->image, + .isDepthStencil = true, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .hasSrcBarrier = false, + .newLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .range = vkRange, + .performClear = true, + .ignore = false, + .clearValue = { .depthStencil = depthStencilValue }, + }; + } + } + if (performImmediateClear) { + vkRangeCount++; + vkRanges[vkRangeCount - 1] = vkRange; + } } - VKD.vkCmdClearDepthStencilImage(grCmdBuffer->commandBuffer, grImage->image, - getVkImageLayout(GR_IMAGE_STATE_CLEAR, false), - &depthStencilValue, rangeCount, vkRanges); - + if (vkRangeCount > 0) { + VKD.vkCmdClearDepthStencilImage(grCmdBuffer->commandBuffer, grImage->image, + getVkImageLayout(GR_IMAGE_STATE_CLEAR, false), + &depthStencilValue, vkRangeCount, vkRanges); + } STACK_ARRAY_FINISH(vkRanges); } diff --git a/src/mantle/mantle_cmd_buf_man.c b/src/mantle/mantle_cmd_buf_man.c index 7a6d71c6..b9cbcf59 100644 --- a/src/mantle/mantle_cmd_buf_man.c +++ b/src/mantle/mantle_cmd_buf_man.c @@ -113,6 +113,8 @@ GR_RESULT GR_STDCALL grCreateCommandBuffer( .colorAttachmentCount = 0, .colorAttachments = { { 0 } }, .colorFormats = { 0 }, + .clearAttachments = {}, + .clearAttachmentCount = 0, .hasDepthStencil = false, .depthAttachment = { 0 }, .stencilAttachment = { 0 }, @@ -185,6 +187,7 @@ GR_RESULT GR_STDCALL grEndCommandBuffer( GrDevice* grDevice = GET_OBJ_DEVICE(grCmdBuffer); grCmdBufferEndRenderPass(grCmdBuffer); + grCmdFlushClearImages(grCmdBuffer); VkResult res = VKD.vkEndCommandBuffer(grCmdBuffer->commandBuffer); if (res != VK_SUCCESS) { diff --git a/src/mantle/mantle_object.h b/src/mantle/mantle_object.h index 90d291dc..a030f8a0 100644 --- a/src/mantle/mantle_object.h +++ b/src/mantle/mantle_object.h @@ -142,6 +142,18 @@ typedef struct _GrBorderColorPalette { float* data; } GrBorderColorPalette; +typedef struct _GrClearImageState { + VkImage image; + bool isDepthStencil; + VkImageLayout oldLayout; + bool hasSrcBarrier; + VkImageLayout newLayout; + VkImageSubresourceRange range; + bool performClear; + bool ignore; + VkClearValue clearValue; +} GrClearImageState; + typedef struct _GrCmdBuffer { GrObject grObj; VkCommandPool commandPool; @@ -166,10 +178,17 @@ typedef struct _GrCmdBuffer { // Render pass unsigned colorAttachmentCount; VkRenderingAttachmentInfoKHR colorAttachments[GR_MAX_COLOR_TARGETS]; + VkImageSubresourceRange colorAttachmentRanges[GR_MAX_COLOR_TARGETS]; + VkImage colorAttachmentImages[GR_MAX_COLOR_TARGETS]; VkFormat colorFormats[GR_MAX_COLOR_TARGETS]; + // clear resource tracking + GrClearImageState clearAttachments[64]; + unsigned clearAttachmentCount; bool hasDepthStencil; VkRenderingAttachmentInfoKHR depthAttachment; VkRenderingAttachmentInfoKHR stencilAttachment; + VkImageSubresourceRange depthRange; + VkImage depthImage; VkFormat depthStencilFormat; VkExtent3D minExtent; } GrCmdBuffer; @@ -363,6 +382,9 @@ typedef struct _GrWsiWinDisplay { void grCmdBufferEndRenderPass( GrCmdBuffer* grCmdBuffer); +void grCmdFlushClearImages( + GrCmdBuffer* grCmdBuffer); + void grCmdBufferResetState( GrCmdBuffer* grCmdBuffer);