diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index 9ad6b6b47..e80177810 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -61,65 +61,46 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) // at least more than one each VkCmdBuffer cmd = GetNextCmd(); - VkResourceRecord *record = GetResourceManager()->GetResourceRecord(id); + WrappedVkImage *im = (WrappedVkImage *)res; + + ImageLayouts *layout = NULL; + { + SCOPED_LOCK(m_ImageLayoutsLock); + layout = &m_ImageLayouts[im->id]; + } VkMemoryRequirements immrq = {0}; - ObjDisp(d)->GetImageMemoryRequirements(Unwrap(d), ToHandle(res), &immrq); - - VkDeviceSize dataoffs = record->memOffset; - VkDeviceMemory datamem = Unwrap(record->mem); - VkDeviceSize datasize = immrq.size; - - RDCASSERT(datamem); - - record = GetResourceManager()->GetResourceRecord(record->baseResource); - - RDCASSERT(record->Length > 0); - VkDeviceSize memsize = (VkDeviceSize)record->Length; + ObjDisp(d)->GetImageMemoryRequirements(Unwrap(d), im->real.As(), &immrq); VkDeviceMemory readbackmem = VK_NULL_HANDLE; - // VKTODOMED we just dump the backing memory for this image via an aliased buffer - // copy, instead of doing a proper copy from image to buffer, which would be - // independent of the image memory layout and do any unswizzling/untiling VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, - 0, VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0, + immrq.size, VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0, VK_SHARING_MODE_EXCLUSIVE, 0, NULL, }; - // since these are very short lived, they are not wrapped - VkBuffer srcBuf, dstBuf; + // since this is very short lived, it is not wrapped + VkBuffer dstBuf; - // dstBuf is just over the allocated memory, so only the image's size - bufInfo.size = datasize; vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &dstBuf); RDCASSERT(vkr == VK_SUCCESS); - - // srcBuf spans the entire memory, then we copy out the sub-region we're interested in - bufInfo.size = memsize; - vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &srcBuf); - RDCASSERT(vkr == VK_SUCCESS); VkMemoryRequirements mrq = { 0 }; - vkr = ObjDisp(d)->GetBufferMemoryRequirements(Unwrap(d), srcBuf, &mrq); + vkr = ObjDisp(d)->GetBufferMemoryRequirements(Unwrap(d), dstBuf, &mrq); RDCASSERT(vkr == VK_SUCCESS); VkMemoryAllocInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, NULL, - datasize, GetReadbackMemoryIndex(mrq.memoryTypeBits), + mrq.size, GetReadbackMemoryIndex(mrq.memoryTypeBits), }; - allocInfo.allocationSize = AlignUp(allocInfo.allocationSize, mrq.alignment); - vkr = ObjDisp(d)->AllocMemory(Unwrap(d), &allocInfo, &readbackmem); RDCASSERT(vkr == VK_SUCCESS); GetResourceManager()->WrapResource(Unwrap(d), readbackmem); - vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), srcBuf, datamem, 0); - RDCASSERT(vkr == VK_SUCCESS); vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), dstBuf, Unwrap(readbackmem), 0); RDCASSERT(vkr == VK_SUCCESS); @@ -128,9 +109,55 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) vkr = ObjDisp(d)->BeginCommandBuffer(Unwrap(cmd), &beginInfo); RDCASSERT(vkr == VK_SUCCESS); - VkBufferCopy region = { dataoffs, 0, datasize }; + VkExtent3D extent = layout->extent; + + VkImageLayout origLayout = layout->subresourceStates[0].state; + + VkImageMemoryBarrier srcimTrans = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, NULL, + 0, 0, origLayout, VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + im->real.As(), + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }; - ObjDisp(d)->CmdCopyBuffer(Unwrap(cmd), srcBuf, dstBuf, 1, ®ion); + //for(uint32_t m=0; m < layout->mipLevels; m++) + uint32_t m=0; + { + VkBufferImageCopy region = { + 0, 0, 0, + { VK_IMAGE_ASPECT_COLOR, m, 0, layout->arraySize }, + { 0, 0, 0, }, + extent, + }; + + // ensure all previous writes have completed + srcimTrans.outputMask = + VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT| + VK_MEMORY_OUTPUT_SHADER_WRITE_BIT| + VK_MEMORY_OUTPUT_DEPTH_STENCIL_ATTACHMENT_BIT| + VK_MEMORY_OUTPUT_TRANSFER_BIT; + // before we go reading + srcimTrans.inputMask = VK_MEMORY_INPUT_TRANSFER_BIT; + + void *barrier = (void *)&srcimTrans; + + ObjDisp(d)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + ObjDisp(d)->CmdCopyImageToBuffer(Unwrap(cmd), im->real.As(), VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL, dstBuf, 1, ®ion); + + srcimTrans.oldLayout = srcimTrans.newLayout; + srcimTrans.newLayout = origLayout; + + srcimTrans.outputMask = 0; + srcimTrans.inputMask = 0; + + ObjDisp(d)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + extent.width = RDCMAX(extent.width>>1, 1); + extent.height = RDCMAX(extent.height>>1, 1); + extent.depth = RDCMAX(extent.depth>>1, 1); + } vkr = ObjDisp(d)->EndCommandBuffer(Unwrap(cmd)); RDCASSERT(vkr == VK_SUCCESS); @@ -142,10 +169,9 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) SubmitCmds(); FlushQ(); - ObjDisp(d)->DestroyBuffer(Unwrap(d), srcBuf); ObjDisp(d)->DestroyBuffer(Unwrap(d), dstBuf); - GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(GetWrapped(readbackmem), (uint32_t)datasize, NULL)); + GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(GetWrapped(readbackmem), (uint32_t)mrq.size, NULL)); return true; } @@ -422,56 +448,157 @@ bool WrappedVulkan::Serialise_InitialState(WrappedVkRes *res) size_t dataSize = 0; m_pSerialiser->SerialiseBuffer("data", data, dataSize); + WrappedVkImage *liveim = (WrappedVkImage *)res; + VkResult vkr = VK_SUCCESS; VkDevice d = GetDev(); - VkDeviceMemory mem = VK_NULL_HANDLE; - - // VKTODOMED should get mem requirements for buffer - copy might enforce - // some restrictions? - VkMemoryRequirements mrq = { dataSize, 16, ~0U }; - - VkMemoryAllocInfo allocInfo = { - VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, NULL, - dataSize, GetUploadMemoryIndex(mrq.memoryTypeBits), - }; - - vkr = ObjDisp(d)->AllocMemory(Unwrap(d), &allocInfo, &mem); - RDCASSERT(vkr == VK_SUCCESS); - - GetResourceManager()->WrapResource(Unwrap(d), mem); - VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, dataSize, VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0, VK_SHARING_MODE_EXCLUSIVE, 0, NULL, }; + // short-lived, so not wrapped VkBuffer buf; + VkDeviceMemory uploadmem = VK_NULL_HANDLE; vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &buf); RDCASSERT(vkr == VK_SUCCESS); + + VkMemoryRequirements mrq = { 0 }; - GetResourceManager()->WrapResource(Unwrap(d), buf); + vkr = ObjDisp(d)->GetBufferMemoryRequirements(Unwrap(d), buf, &mrq); + RDCASSERT(vkr == VK_SUCCESS); - vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), Unwrap(buf), Unwrap(mem), 0); + VkMemoryAllocInfo allocInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, NULL, + dataSize, GetUploadMemoryIndex(mrq.memoryTypeBits), + }; + + vkr = ObjDisp(d)->AllocMemory(Unwrap(d), &allocInfo, &uploadmem); + RDCASSERT(vkr == VK_SUCCESS); + + vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), buf, uploadmem, 0); RDCASSERT(vkr == VK_SUCCESS); byte *ptr = NULL; - ObjDisp(d)->MapMemory(Unwrap(d), Unwrap(mem), 0, 0, 0, (void **)&ptr); + ObjDisp(d)->MapMemory(Unwrap(d), uploadmem, 0, 0, 0, (void **)&ptr); // VKTODOLOW could deserialise directly into this ptr if we serialised // size separately. memcpy(ptr, data, dataSize); - ObjDisp(d)->UnmapMemory(Unwrap(d), Unwrap(mem)); + ObjDisp(d)->UnmapMemory(Unwrap(d), uploadmem); SAFE_DELETE_ARRAY(data); + // create image to copy into from the buffer + + VkImageCreateInfo imInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, NULL, + m_CreationInfo.m_Image[liveim->id].type, + m_CreationInfo.m_Image[liveim->id].format, + m_CreationInfo.m_Image[liveim->id].extent, + m_CreationInfo.m_Image[liveim->id].mipLevels, + m_CreationInfo.m_Image[liveim->id].arraySize, + m_CreationInfo.m_Image[liveim->id].samples, + VK_IMAGE_TILING_OPTIMAL, // make this optimal since the format/etc is more likely supported as optimal + VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT|VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, + 0, + VK_SHARING_MODE_EXCLUSIVE, + 0, + NULL, + VK_IMAGE_LAYOUT_UNDEFINED, + }; + + VkImage im = VK_NULL_HANDLE; + + vkr = ObjDisp(d)->CreateImage(Unwrap(d), &imInfo, &im); + RDCASSERT(vkr == VK_SUCCESS); + + GetResourceManager()->WrapResource(Unwrap(d), im); + + vkr = ObjDisp(d)->GetImageMemoryRequirements(Unwrap(d), Unwrap(im), &mrq); + RDCASSERT(vkr == VK_SUCCESS); + + allocInfo.allocationSize = mrq.size; + allocInfo.memoryTypeIndex = GetGPULocalMemoryIndex(mrq.memoryTypeBits); + + VkDeviceMemory mem = VK_NULL_HANDLE; + + vkr = ObjDisp(d)->AllocMemory(Unwrap(d), &allocInfo, &mem); + RDCASSERT(vkr == VK_SUCCESS); + + GetResourceManager()->WrapResource(Unwrap(d), mem); + + vkr = ObjDisp(d)->BindImageMemory(Unwrap(d), Unwrap(im), Unwrap(mem), 0); + RDCASSERT(vkr == VK_SUCCESS); + + VkCmdBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO, NULL, VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT }; + + // VKTODOLOW ideally the prepares could be batched up + // a bit more - maybe not all in one command buffer, but + // at least more than one each + VkCmdBuffer cmd = GetNextCmd(); + + vkr = ObjDisp(d)->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + RDCASSERT(vkr == VK_SUCCESS); + + VkExtent3D extent = imInfo.extent; + + VkImageMemoryBarrier srcimTrans = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, NULL, + 0, 0, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + Unwrap(im), + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }; + + //for(uint32_t m=0; m < layout->mipLevels; m++) + uint32_t m=0; + { + VkBufferImageCopy region = { + 0, 0, 0, + { VK_IMAGE_ASPECT_COLOR, m, 0, imInfo.arraySize }, + { 0, 0, 0, }, + extent, + }; + + void *barrier = (void *)&srcimTrans; + + ObjDisp(d)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + ObjDisp(d)->CmdCopyBufferToImage(Unwrap(cmd), buf, Unwrap(im), VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL, 1, ®ion); + + srcimTrans.oldLayout = srcimTrans.newLayout; + srcimTrans.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL; + + ObjDisp(d)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + extent.width = RDCMAX(extent.width>>1, 1); + extent.height = RDCMAX(extent.height>>1, 1); + extent.depth = RDCMAX(extent.depth>>1, 1); + } + + vkr = ObjDisp(d)->EndCommandBuffer(Unwrap(cmd)); + RDCASSERT(vkr == VK_SUCCESS); + + // VKTODOLOW would be nice to store up all these buffers so that + // we don't have to submit & flush here before destroying, but + // instead could submit all cmds, then flush once, then destroy + // buffers. (or even not flush at all until capture is over) + SubmitCmds(); + FlushQ(); + + ObjDisp(d)->DestroyBuffer(Unwrap(d), buf); + ObjDisp(d)->FreeMemory(Unwrap(d), uploadmem); + + // remember to free this memory on shutdown m_FreeMems.push_back(mem); - GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(GetWrapped(buf), (uint32_t)dataSize, NULL)); + GetResourceManager()->SetInitialContents(id, VulkanResourceManager::InitialContentData(GetWrapped(im), 0, NULL)); } else if(type == eResDeviceMemory) { @@ -748,68 +875,72 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, VulkanResourceManager return; } - VkBuffer srcBuf = (VkBuffer)(uint64_t)initial.resource; - VkDeviceSize datasize = (VkDeviceSize)initial.num; - VkDeviceMemory dstMem = (VkDeviceMemory)(uint64_t)live; // maintain the wrapping, for consistency - VkDeviceSize dstMemOffs = 0; - VkDeviceSize memsize = datasize; - - { - dstMem = m_ImageLayouts[id].mem; - dstMemOffs = m_ImageLayouts[id].memoffs; - - // create buffer over all memory, then copy into sub-region - memsize = m_CreationInfo.m_Memory[GetResID(dstMem)].size; - } + WrappedVkImage *im = (WrappedVkImage *)initial.resource; VkCmdBuffer cmd = GetNextCmd(); vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo); RDCASSERT(vkr == VK_SUCCESS); - VkBufferCreateInfo bufInfo = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, - memsize, VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0, - VK_SHARING_MODE_EXCLUSIVE, 0, NULL, - }; + VkExtent3D extent = m_CreationInfo.m_Image[id].extent; - // since this is short lived it isn't wrapped. Note that we want - // to cache this up front, so it will then be wrapped - VkBuffer dstBuf; + VkImageLayout origLayout = m_ImageLayouts[id].subresourceStates[0].state; - // VKTODOMED this should be created once up front, not every time - vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &dstBuf); - RDCASSERT(vkr == VK_SUCCESS); - - vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), dstBuf, Unwrap(dstMem), 0); - RDCASSERT(vkr == VK_SUCCESS); - - VkBufferCopy region = { 0, dstMemOffs, datasize }; - - ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), dstBuf, 1, ®ion); - - // add memory barrier to ensure this copy completes before any subsequent work - VkMemoryBarrier memBarrier = { - VK_STRUCTURE_TYPE_MEMORY_BARRIER, NULL, - VK_MEMORY_OUTPUT_TRANSFER_BIT | VK_MEMORY_OUTPUT_HOST_WRITE_BIT, - VK_MEMORY_INPUT_HOST_READ_BIT | VK_MEMORY_INPUT_UNIFORM_READ_BIT | VK_MEMORY_INPUT_SHADER_READ_BIT | VK_MEMORY_INPUT_INPUT_ATTACHMENT_BIT | VK_MEMORY_INPUT_TRANSFER_BIT, + VkImageMemoryBarrier dstimTrans = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, NULL, + 0, 0, origLayout, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ToHandle(live), + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, m_CreationInfo.m_Image[id].arraySize } }; - void *barrier = (void *)&memBarrier; + //for(uint32_t m=0; m < layout->mipLevels; m++) + uint32_t m=0; + { + VkImageCopy region = { + { VK_IMAGE_ASPECT_COLOR, m, 0, m_CreationInfo.m_Image[id].arraySize }, + { 0, 0, 0 }, + { VK_IMAGE_ASPECT_COLOR, m, 0, m_CreationInfo.m_Image[id].arraySize }, + { 0, 0, 0 }, + extent, + }; - ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + dstimTrans.subresourceRange.baseMipLevel = m; + + void *barrier = (void *)&dstimTrans; + + ObjDisp(d)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + ObjDisp(cmd)->CmdCopyImage(Unwrap(cmd), + im->real.As(), VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL, + ToHandle(live), VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL, + 1, ®ion); + + dstimTrans.oldLayout = dstimTrans.newLayout; + dstimTrans.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL; + + // make sure the apply completes before any further work + dstimTrans.outputMask = VK_MEMORY_OUTPUT_TRANSFER_BIT; + dstimTrans.inputMask = VK_MEMORY_INPUT_HOST_READ_BIT| + VK_MEMORY_INPUT_INDIRECT_COMMAND_BIT| + VK_MEMORY_INPUT_INDEX_FETCH_BIT| + VK_MEMORY_INPUT_VERTEX_ATTRIBUTE_FETCH_BIT| + VK_MEMORY_INPUT_UNIFORM_READ_BIT| + VK_MEMORY_INPUT_SHADER_READ_BIT| + VK_MEMORY_INPUT_COLOR_ATTACHMENT_BIT| + VK_MEMORY_INPUT_DEPTH_STENCIL_ATTACHMENT_BIT| + VK_MEMORY_INPUT_INPUT_ATTACHMENT_BIT| + VK_MEMORY_INPUT_TRANSFER_BIT; + + ObjDisp(d)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + extent.width = RDCMAX(extent.width>>1, 1); + extent.height = RDCMAX(extent.height>>1, 1); + extent.depth = RDCMAX(extent.depth>>1, 1); + } vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); RDCASSERT(vkr == VK_SUCCESS); - - // VKTODOLOW if this dstBuf was persistent or at least cached - // we could batch these command buffers better and wouldn't - // need to flush at all until application of all init states - // is over - SubmitCmds(); - FlushQ(); - - ObjDisp(d)->DestroyBuffer(Unwrap(d), dstBuf); } else if(type == eResDeviceMemory) { diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index dff3759ac..b6222d485 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -720,6 +720,8 @@ struct ImageLayouts vector subresourceStates; int arraySize, mipLevels; + VkExtent3D extent; + VkFormat format; VkDeviceMemory mem; VkDeviceSize memoffs; }; diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index 853c46bc3..fa7bee1a6 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -920,6 +920,11 @@ bool WrappedVulkan::Serialise_vkCreateImage( ImageLayouts &layouts = m_ImageLayouts[live]; layouts.subresourceStates.clear(); + layouts.arraySize = info.arraySize; + layouts.mipLevels = info.mipLevels; + layouts.extent = info.extent; + layouts.format = info.format; + if(!IsDepthStencilFormat(info.format)) { range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; layouts.subresourceStates.push_back(ImageRegionState(range, UNTRANSITIONED_IMG_STATE, VK_IMAGE_LAYOUT_UNDEFINED)); @@ -976,18 +981,26 @@ VkResult WrappedVulkan::vkCreateImage( if(pCreateInfo->imageType == VK_IMAGE_TYPE_3D) range.arraySize = pCreateInfo->extent.depth; + ImageLayouts *layout = NULL; { SCOPED_LOCK(m_ImageLayoutsLock); - m_ImageLayouts[id].subresourceStates.clear(); - if(!IsDepthStencilFormat(pCreateInfo->format)) - { - range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; m_ImageLayouts[id].subresourceStates.push_back(ImageRegionState(range, UNTRANSITIONED_IMG_STATE, VK_IMAGE_LAYOUT_UNDEFINED)); - } - else - { - range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; m_ImageLayouts[id].subresourceStates.push_back(ImageRegionState(range, UNTRANSITIONED_IMG_STATE, VK_IMAGE_LAYOUT_UNDEFINED)); - range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;m_ImageLayouts[id].subresourceStates.push_back(ImageRegionState(range, UNTRANSITIONED_IMG_STATE, VK_IMAGE_LAYOUT_UNDEFINED)); - } + layout = &m_ImageLayouts[id]; + } + + layout->arraySize = pCreateInfo->arraySize; + layout->mipLevels = pCreateInfo->mipLevels; + layout->extent = pCreateInfo->extent; + layout->format = pCreateInfo->format; + + layout->subresourceStates.clear(); + if(!IsDepthStencilFormat(pCreateInfo->format)) + { + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; layout->subresourceStates.push_back(ImageRegionState(range, UNTRANSITIONED_IMG_STATE, VK_IMAGE_LAYOUT_UNDEFINED)); + } + else + { + range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; layout->subresourceStates.push_back(ImageRegionState(range, UNTRANSITIONED_IMG_STATE, VK_IMAGE_LAYOUT_UNDEFINED)); + range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;layout->subresourceStates.push_back(ImageRegionState(range, UNTRANSITIONED_IMG_STATE, VK_IMAGE_LAYOUT_UNDEFINED)); } }