Add additional fields to ImageInfo

Three new fields are added to `ImageInfo`
- `VkImageType imageType`: this is used to distinguish 2D and 3D images,
  to correctly handle access through 2D image views.
- `VkImageLayout initialLayout`: this is the `initialLayout` in which
  the image was created (`UNDEFINED` or `PREINITIALIZED`). This is used
  to correctly initialize `PREINITIALIZED` images (See: TODO).
- `VkSharingMode sharingMode`: This is needed to correctly generate
  queue family transfers, because we must *not* generate queue family
  transfers for images with `CONCURRENT` sharing mode.

This also refactors `SwapchainInfo` to use `ImageInfo`, rather than
duplicating some of `ImageInfo`s fields.

Change-Id: Ic42077c382e4055cb27af069045c46eacbd122cc
This commit is contained in:
Benson Joeris
2019-12-17 10:25:26 -05:00
committed by Baldur Karlsson
parent 687f12f492
commit e7303660d7
4 changed files with 123 additions and 96 deletions
+40 -20
View File
@@ -36,56 +36,65 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
{
SECTION("unsplit")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 0);
};
SECTION("split aspect")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
imgRefs.Split(true, false, false);
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 1);
};
SECTION("split levels")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
imgRefs.Split(false, true, false);
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 2);
};
SECTION("split layers")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
imgRefs.Split(false, false, true);
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 5);
};
SECTION("split aspect and levels")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
imgRefs.Split(true, true, false);
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 11 + 2);
};
SECTION("split aspect and layers")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
imgRefs.Split(true, false, true);
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 17 + 5);
};
SECTION("split levels and layers")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
imgRefs.Split(false, true, true);
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) ==
2 * 17 + 5);
};
SECTION("split aspect and levels and layers")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
imgRefs.Split(true, true, true);
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) ==
11 * 17 + 2 * 17 + 5);
};
SECTION("update unsplit")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
imgRefs.Update(range, eFrameRef_Read);
rdcarray<FrameRefType> expected = {eFrameRef_Read};
@@ -93,7 +102,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
};
SECTION("update split aspect")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
imgRefs.Update(range, eFrameRef_Read);
@@ -102,7 +112,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
};
SECTION("update split levels")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.baseMipLevel = 1;
range.levelCount = 3;
@@ -115,7 +126,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
};
SECTION("update split layers")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.baseArrayLayer = 7;
imgRefs.Update(range, eFrameRef_Read);
@@ -128,7 +140,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
};
SECTION("update split aspect then levels")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range0;
range0.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
imgRefs.Update(range0, eFrameRef_Read);
@@ -150,7 +163,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
}
SECTION("update split layers then aspects and levels")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 7, 5, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 7, 5, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range0;
range0.baseArrayLayer = 1;
range0.layerCount = 2;
@@ -198,7 +212,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
}
SECTION("update 3D image default view")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.layerCount = 1;
imgRefs.Update(range, eFrameRef_Read);
@@ -207,7 +222,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
}
SECTION("update 3D image 3D view")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.layerCount = 1;
range.viewType = VK_IMAGE_VIEW_TYPE_3D;
@@ -217,7 +233,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
}
SECTION("update 3D image 2D view")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.layerCount = 1;
range.viewType = VK_IMAGE_VIEW_TYPE_2D;
@@ -228,7 +245,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
}
SECTION("update 3D image 2D array view")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.baseArrayLayer = 1;
range.layerCount = 2;
@@ -240,7 +258,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
}
SECTION("update 3D image 2D array view full")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
imgRefs.Update(range, eFrameRef_Read);
@@ -249,7 +268,8 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
}
SECTION("update 3D image 3D view full")
{
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1));
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 5}, 11, 1, 1,
VK_IMAGE_LAYOUT_UNDEFINED, VK_SHARING_MODE_EXCLUSIVE));
ImageRange range;
range.viewType = VK_IMAGE_VIEW_TYPE_3D;
imgRefs.Update(range, eFrameRef_Read);
+9 -9
View File
@@ -1795,10 +1795,9 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
// create readback buffer
VkBufferCreateInfo bufInfo = {
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
NULL,
0,
GetByteSize(swapInfo.extent.width, swapInfo.extent.height, 1, swapInfo.format, 0),
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, 0,
GetByteSize(swapInfo.imageInfo.extent.width, swapInfo.imageInfo.extent.height, 1,
swapInfo.imageInfo.format, 0),
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
};
vt->CreateBuffer(Unwrap(device), &bufInfo, NULL, &readbackBuf);
@@ -1820,7 +1819,8 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
uint32_t rowPitch = GetByteSize(swapInfo.extent.width, 1, 1, swapInfo.format, 0);
uint32_t rowPitch =
GetByteSize(swapInfo.imageInfo.extent.width, 1, 1, swapInfo.imageInfo.format, 0);
VkBufferImageCopy cpy = {
0,
@@ -1830,7 +1830,7 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
{
0, 0, 0,
},
{swapInfo.extent.width, swapInfo.extent.height, 1},
{swapInfo.imageInfo.extent.width, swapInfo.imageInfo.extent.height, 1},
};
uint32_t swapQueueIndex = m_ImageLayouts[GetResID(backbuffer)].queueFamilyIndex;
@@ -1938,9 +1938,9 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd)
vt->DestroyBuffer(Unwrap(device), Unwrap(readbackBuf), NULL);
GetResourceManager()->ReleaseWrappedResource(readbackBuf);
ResourceFormat fmt = MakeResourceFormat(swapInfo.format);
fp.width = swapInfo.extent.width;
fp.height = swapInfo.extent.height;
ResourceFormat fmt = MakeResourceFormat(swapInfo.imageInfo.format);
fp.width = swapInfo.imageInfo.extent.width;
fp.height = swapInfo.imageInfo.extent.height;
fp.pitch = rowPitch;
fp.stride = fmt.compByteWidth * fmt.compCount;
fp.bpc = fmt.compByteWidth;
+67 -56
View File
@@ -863,11 +863,75 @@ struct ImageRegionState
DECLARE_REFLECTION_STRUCT(ImageRegionState);
VkImageAspectFlags FormatImageAspects(VkFormat f);
struct ImageSubresourceRange;
struct ImageInfo
{
int layerCount = 0;
int levelCount = 0;
int sampleCount = 0;
VkExtent3D extent = {0, 0, 0};
VkImageType imageType = VK_IMAGE_TYPE_2D;
VkFormat format = VK_FORMAT_UNDEFINED;
VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkSharingMode sharingMode = VK_SHARING_MODE_EXCLUSIVE;
ImageInfo() {}
ImageInfo(VkFormat format, VkExtent3D extent, int levelCount, int layerCount, int sampleCount,
VkImageLayout initialLayout, VkSharingMode sharingMode)
: format(format),
extent(extent),
levelCount(levelCount),
layerCount(layerCount),
sampleCount(sampleCount),
initialLayout(initialLayout),
sharingMode(sharingMode)
{
}
ImageInfo(const VkImageCreateInfo &ci)
: layerCount(ci.arrayLayers),
levelCount(ci.mipLevels),
sampleCount((int)ci.samples),
extent(ci.extent),
imageType(ci.imageType),
format(ci.format),
initialLayout(ci.initialLayout),
sharingMode(ci.sharingMode)
{
// The Vulkan spec Valid Usage for `VkImageCreateInfo` specifies that the height and depth of 1D
// images, and the depth of 2D images must equal 1. We need to ensure this holds, even if the
// application is invalid, since we rely on `depth>1` to detect 3D images and correctly handle
// 2D views of 3D images.
if(ci.imageType == VK_IMAGE_TYPE_1D)
{
extent.height = extent.depth = 1;
}
else if(ci.imageType == VK_IMAGE_TYPE_2D)
{
extent.depth = 1;
}
}
ImageInfo(const VkSwapchainCreateInfoKHR &ci)
: layerCount(ci.imageArrayLayers),
levelCount(1),
sampleCount(1),
format(ci.imageFormat),
sharingMode(ci.imageSharingMode)
{
extent.width = ci.imageExtent.width;
extent.height = ci.imageExtent.height;
extent.depth = 1;
}
VkImageAspectFlags Aspects() const { return FormatImageAspects(format); }
ImageSubresourceRange FullRange() const;
};
DECLARE_REFLECTION_STRUCT(ImageInfo);
struct SwapchainInfo
{
VkFormat format;
VkExtent2D extent;
int arraySize;
ImageInfo imageInfo;
bool shared;
@@ -886,59 +950,6 @@ struct SwapchainInfo
uint32_t lastPresent;
};
VkImageAspectFlags FormatImageAspects(VkFormat f);
struct ImageSubresourceRange;
struct ImageInfo
{
int layerCount = 0;
int levelCount = 0;
int sampleCount = 0;
VkExtent3D extent = {0, 0, 0};
VkFormat format = VK_FORMAT_UNDEFINED;
ImageInfo() {}
ImageInfo(VkFormat format, VkExtent3D extent, int levelCount, int layerCount, int sampleCount)
: format(format),
extent(extent),
levelCount(levelCount),
layerCount(layerCount),
sampleCount(sampleCount)
{
}
ImageInfo(const VkImageCreateInfo &ci)
: layerCount(ci.arrayLayers),
levelCount(ci.mipLevels),
sampleCount((int)ci.samples),
extent(ci.extent),
format(ci.format)
{
// The Vulkan spec Valid Usage for `VkImageCreateInfo` specifies that the height and depth of 1D
// images, and the depth of 2D images must equal 1. We need to ensure this holds, even if the
// application is invalid, since we rely on `depth>1` to detect 3D images and correctly handle
// 2D views of 3D images.
if(ci.imageType == VK_IMAGE_TYPE_1D)
{
extent.height = extent.depth = 1;
}
else if(ci.imageType == VK_IMAGE_TYPE_2D)
{
extent.depth = 1;
}
}
ImageInfo(const SwapchainInfo &swapInfo)
: layerCount(swapInfo.arraySize), levelCount(1), sampleCount(1), format(swapInfo.format)
{
extent.width = swapInfo.extent.width;
extent.height = swapInfo.extent.height;
extent.depth = 1;
}
VkImageAspectFlags Aspects() const { return FormatImageAspects(format); }
ImageSubresourceRange FullRange() const;
};
DECLARE_REFLECTION_STRUCT(ImageInfo);
// these structs are allocated for images and buffers, then pointed to (non-owning) by views
struct ResourceInfo
{
@@ -299,7 +299,7 @@ VkResult WrappedVulkan::vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR
record->AddParent(swaprecord);
record->resInfo = new ResourceInfo();
record->resInfo->imageInfo = ImageInfo(*swaprecord->swapInfo);
record->resInfo->imageInfo = swaprecord->swapInfo->imageInfo;
// note we add the chunk to the swap record, that way when the swapchain is created it will
// always create all of its images on replay. The image's record is kept around for
@@ -356,9 +356,7 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice
AddResource(SwapChain, ResourceType::SwapchainImage, "Swapchain");
DerivedResource(device, SwapChain);
swapinfo.format = CreateInfo.imageFormat;
swapinfo.extent = CreateInfo.imageExtent;
swapinfo.arraySize = CreateInfo.imageArrayLayers;
swapinfo.imageInfo = ImageInfo(CreateInfo);
swapinfo.shared = (CreateInfo.presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
CreateInfo.presentMode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
@@ -451,7 +449,7 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(SerialiserType &ser, VkDevice
ImageLayouts &layouts = m_ImageLayouts[liveId];
layouts.imageInfo = ImageInfo(swapinfo);
layouts.imageInfo = swapinfo.imageInfo;
layouts.isMemoryBound = true;
layouts.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -500,9 +498,7 @@ void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device,
RenderDoc::Inst().AddFrameCapturer(LayerDisp(m_Instance), swapInfo.wndHandle, this);
swapInfo.format = pCreateInfo->imageFormat;
swapInfo.extent = pCreateInfo->imageExtent;
swapInfo.arraySize = pCreateInfo->imageArrayLayers;
swapInfo.imageInfo = ImageInfo(*pCreateInfo);
VkResult vkr = VK_SUCCESS;
@@ -786,9 +782,9 @@ VkResult WrappedVulkan::vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR
GetNextCmd(),
rp,
fb,
RDCMAX(1U, swapInfo.extent.width),
RDCMAX(1U, swapInfo.extent.height),
swapInfo.format,
RDCMAX(1U, swapInfo.imageInfo.extent.width),
RDCMAX(1U, swapInfo.imageInfo.extent.height),
swapInfo.imageInfo.format,
};
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,