Synchronization 为什么这个Vulkan代码有一个写后再写的危险?

Synchronization 为什么这个Vulkan代码有一个写后再写的危险?,synchronization,vulkan,Synchronization,Vulkan,我正在尝试新的Vulkan,它在我的纹理加载代码中发现了一个写-写危险: mipLevelCount=mipmaps==mipmaps::生成?MathUtil::GetMipmapCount(宽度、高度):1; VkImageSubresourceRange={}; range.aspectMask=VK\u IMAGE\u ASPECT\u COLOR\u位; range.baseMipLevel=0; range.levelCount=mipLevelCount; range.baseA

我正在尝试新的Vulkan,它在我的纹理加载代码中发现了一个写-写危险:


mipLevelCount=mipmaps==mipmaps::生成?MathUtil::GetMipmapCount(宽度、高度):1;
VkImageSubresourceRange={};
range.aspectMask=VK\u IMAGE\u ASPECT\u COLOR\u位;
range.baseMipLevel=0;
range.levelCount=mipLevelCount;
range.baseArrayLayer=0;
range.layerCount=1;
imageMemoryBarrier={};
imageMemoryBarrier.sType=VK_结构_类型_图像_内存_屏障;
imageMemoryBarrier.srcQueueFamilyIndex=VK_队列_族_忽略;
imageMemoryBarrier.dstQueueFamilyIndex=VK_队列_族被忽略;
imageMemoryBarrier.srcAccessMask=0;
imageMemoryBarrier.dstAccessMask=VK_访问_传输_写入_位;
imageMemoryBarrier.oldLayout=VK_图像_布局_传输_DST_优化;
imageMemoryBarrier.newLayout=VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.image=图像;
imageMemoryBarrier.subresourceRange=范围;
VKCmd管线屏障(
GfxDeviceGlobal::texCmdBuffer,
VK_管道_阶段_传输_位,
VK_管道_阶段_片段_着色器_位,
0,
0,空ptr,
0,空ptr,
1、&imageMemoryBarrier);
对于(int i=1;i>i,1);
常量std::int32\u t mipHeight=MathUtil::Max(高度>>i,1);
VkImageBlit imageBlit={};
imageBlit.srcSubresource.aspectMask=VK\u IMAGE\u ASPECT\u COLOR\u位;
imageBlit.srcSubresource.baseArrayLayer=0;
imageBlit.srcSubresource.layerCount=1;
imageBlit.srcSubresource.mipLevel=0;
srcpoffsets[0]={0,0,0};
srcpoffsets[1]={width,height,1};
imageBlit.dstSubresource.aspectMask=VK_IMAGE_ASPECT_COLOR_位;
imageBlit.dstSubresource.baseArrayLayer=0;
imageBlit.dstSubresource.layerCount=1;
imageBlit.dstSubresource.mipLevel=i;
dstOffsets[0]={0,0,0};
dstOffsets[1]={mipWidth,mipHeight,1};
VKCMDBLTIMAGE(GfxDeviceGlobal::texCmdBuffer,图像,VK_图像_布局_常规,图像,
VK_图像_布局_常规,1和imageBlit,VK_滤波器_线性);
}
imageMemoryBarrier.srcAccessMask=VK\u访问\u传输\u写入\u位;
imageMemoryBarrier.dstAccessMask=VK_访问_着色器_读取_位;
imageMemoryBarrier.oldLayout=VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.newLayout=VK\u IMAGE\u LAYOUT\u SHADER\u READ\u ONLY\u OPTIMAL;
imageMemoryBarrier.image=图像;
imageMemoryBarrier.subresourceRange=范围;
imageMemoryBarrier.subresourceRange.baseMipLevel=0;
imageMemoryBarrier.subresourceRange.levelCount=mipLevelCount;

vkCmdPipelineBarrier(//让我们记住,布局转换是在
srcStage
dstStage
之间进行的读写操作

首先提交布局转换。它发生在
VK\u PIPELINE\u STAGE\u FRAGMENT\u SHADER\u BIT
之前

然后执行
vkcmdblimitimage
,这将是不同步的,因为这是一个
STAGE\u传输
,而不是
STAGE\u FRAGMENT\u着色器
。虽然
mipLevelCount==1
,但整个循环都是死代码

然后是另一个布局转换。它发生在
VK\u PIPELINE\u STAGE\u TRANSFER\u BIT
之后

因此,有两个布局转换可能同时发生


我认为设置
dstStageMask=VK\u PIPELINE\u STAGE\u TRANSFER\u BIT
应该可以解决这个问题。

请显示
range
miplegcount
变量的值。基于代码的意图,似乎应该是
basemiplege=1
而不是
basemiplege=0
?@krOoze我添加了范围代码。
miplovelCount
在本例中为1,我还没有使用其他计数进行测试。
ERROR: Validation Error: [ SYNC-HAZARD-WRITE_AFTER_WRITE ] Object 0: handle = 0x559307e35610, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0xfdf9f5e1 | vkCmdPipelineBarrier: Hazard WRITE_AFTER_WRITE for image barrier 0 VkImage 0x559307e35610[]. Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: SYNC_IMAGE_LAYOUT_TRANSITION, write_barriers: 0, command: vkCmdPipelineBarrier, seq_no: 1, reset_no: 3).