【发布时间】:2018-02-27 14:18:36
【问题描述】:
我有一个尺寸为4096*4096(所以67108864 字节,因为有4 个通道)的图像,我想将其从暂存缓冲区复制到设备本地图像。缓冲区已经存储了数据,并且我已经正确设置了图像屏障,所以现在我想执行复制操作......除非它不起作用。当我调用 vkCmdCopyBufferToImage() 时,验证层给了我这个错误信息 -
IMAGE(ERROR): object: 0x0 type: 6 location: 3903 msgCode: 417333590: vkCmdCopyBufferToImage(): pRegion[0] exceeds buffer size of 67108864 bytes. The spec valid usage text states 'The buffer region specified by each element of pRegions mustbe a region that is contained within srcBuffer' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdCopyBufferToImage-pRegions-00171).
我找不到我给它的值有什么问题。我传递给它的VkBufferImageCopy 结构看起来像这样-
VkBufferImageCopy bufImgCopy;
bufImgCopy.bufferOffset = 0;
bufImgCopy.bufferImageHeight = 0;
bufImgCopy.bufferRowLength = 0;
bufImgCopy.imageExtent = modelTexture.imgExtents; // 4096 * 4096 * 1
bufImgCopy.imageOffset = {0, 0, 0};
bufImgCopy.imageSubresource.aspectMask = modelTexture.subResource.aspectMask; // Colour attachment
bufImgCopy.imageSubresource.baseArrayLayer = modelTexture.subResource.baseArrayLayer; // 0
bufImgCopy.imageSubresource.layerCount = VK_REMAINING_ARRAY_LAYERS;
bufImgCopy.imageSubresource.mipLevel = 0;
我无法弄清楚为什么 api 认为结构指定的大小大于缓冲区大小。图片格式为VK_FORMAT_B8G8R8A8_UNORM。
编辑
这是设置暂存缓冲区的代码-
stageBuf.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
stageBuf.shareMode = VK_SHARING_MODE_EXCLUSIVE;
stageBuf.bufSize = static_cast<VkDeviceSize>(verts.size() * sizeof(vert) + indices.size() * sizeof(u32)) > modelImage.size ? static_cast<VkDeviceSize>(verts.size() * sizeof(vert) + indices.size() * sizeof(u32)) : modelImage.size;
// filled from the previous struct.
VkBufferCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.queueFamilyIndexCount = bufInfo.qFCount;
info.pQueueFamilyIndices = bufInfo.qFIndices;
info.usage = bufInfo.usage;
info.sharingMode = bufInfo.shareMode;
info.size = bufInfo.bufSize;
if (vkCreateBuffer(device, &info, nullptr, &(bufInfo.buf)) != VK_SUCCESS)
{ //...
VkMemoryRequirements memReqs;
vkGetBufferMemoryRequirements(device, buf, &memReqs);
for (u32 type = 0; type < memProps.memoryTypeCount; ++type)
if ((memReqs.memoryTypeBits & (1 << type)) &&
((memProps.memoryTypes[type].propertyFlags & memFlags) == memFlags)) // The usual things to set buffers up.
{
VkMemoryAllocateInfo info;
info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
info.pNext = nullptr;
info.allocationSize = memReqs.size;
info.memoryTypeIndex = type;
if (vkAllocateMemory(device, &info, nullptr, &mem.memory) == VK_SUCCESS)
{ //....
// All this works perfectly except for the texture copy.
if (vkBindBufferMemory(device, buf, mem.memory, mem.offset) != VK_SUCCESS)
{ //...
我将这个暂存缓冲区用于顶点缓冲区和索引缓冲区(我已将其作为具有偏移量的单个缓冲区)以及我试图复制到的图像。分配的内存是根据最大数据结构的大小来分配的。
【问题讨论】:
-
图像有多少层数组?只有一个或多个?
-
只有一个。它还有 4 个 mipmap 层。
-
您在哪里提供要复制的 mipmap 级别数?我现在没有规范,我不记得缓冲区图像复制的所有参数。以及为什么会有两个变量bufImgCopy和bufImgCopies?
-
您能否添加设置和上传暂存缓冲区的实际代码。缓冲区图像复制结构看起来不错,因此有趣的部分可能是您上传数据的位置。也尝试将 layerCount 设置为 1 而不是使用 VK_REMAINING_ARRAY_LAYERS。
-
@SaschaWillems
VK_REMAINING_ARRAY_LAYERS对VkImageSubresourceLayers无效。你应该这样回答。
标签: vulkan