Skip to content

Commit

Permalink
Vulkan: Correctly handle 3D images with 2D views
Browse files Browse the repository at this point in the history
The spec allows 2D `VkImageView`s of 3D `VkImage`s. The array layers of the 2D
view correspond to depth in the 3D image. For example, the valid usage for
VkImageViewCreateInfo specifies:

> If subresourceRange::layerCount is not VK_REMAINING_ARRAY_LAYERS, image is a
> 3D image created with VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT set, and
> viewType is VK_IMAGE_VIEW_TYPE_2D or VK_IMAGE_VIEW_TYPE_2D_ARRAY,
> subresourceRange::layerCount must be non-zero and
> subresourceRange::baseArrayLayer + subresourceRange::layerCount must be less
> than or equal to the extent.depth specified in VkImageCreateInfo when image
> was created
  • Loading branch information
bjoeris committed Dec 19, 2018
1 parent 14713bd commit 4e1d040
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 32 deletions.
126 changes: 100 additions & 26 deletions gapis/api/vulkan/api/coherent_memory.api
Original file line number Diff line number Diff line change
Expand Up @@ -180,38 +180,114 @@ sub void readCoherentMemoryInImage(ref!ImageObject image) {
// VkImageSubresourceRange data

@spy_disabled
sub void readImageSubresource(ref!ImageObject image, VkImageSubresourceRange rng) {
readCoherentMemoryInImage(image)
sub void accessImageSubresourceSlice(ref!ImageObject image, VkImageSubresourceRange rng, u32 baseDepth, u32 depthCount, bool isWrite) {
VK_REMAINING_ARRAY_LAYERS := as!u32(0xFFFFFFFF)
layerCount := imageSubresourceLayerCount(image, rng)
levelCount := imageSubresourceLevelCount(image, rng)

z0 := as!u64(baseDepth)
z1 := switch (depthCount == VK_REMAINING_ARRAY_LAYERS) {
case true:
as!u64(image.Info.Extent.Depth)
case false:
as!u64(baseDepth + depthCount)
}

format := image.Info.Format
elementAndTexelBlockSize := getElementAndTexelBlockSize(format)
depthElementSize := getDepthElementSize(format, false)
blockWidth := as!u64(elementAndTexelBlockSize.TexelBlockSize.Width)
blockHeight := as!u64(elementAndTexelBlockSize.TexelBlockSize.Height)

for _ , _ , aspectBit in unpackImageAspectFlags(rng.aspectMask) {
elementSize := switch (aspectBit) {
case VK_IMAGE_ASPECT_COLOR_BIT:
as!u64(elementAndTexelBlockSize.ElementSize)
case VK_IMAGE_ASPECT_DEPTH_BIT:
as!u64(depthElementSize)
case VK_IMAGE_ASPECT_STENCIL_BIT:
as!u64(1)
}
for _, i, layer in image.Aspects[aspectBit].Layers {
if (i >= rng.baseArrayLayer) && (i < rng.baseArrayLayer + layerCount) {
for _, k, level in layer.Levels {
if (k >= rng.baseMipLevel) && (k < rng.baseMipLevel + levelCount) {
read(level.Data)
imageLevelWidthInBlocks := as!u64(roundUpTo(level.Width, as!u32(blockWidth)))
imageLevelHeightInBlocks := as!u64(roundUpTo(level.Height, as!u32(blockHeight)))
start := as!u64(z0) * imageLevelHeightInBlocks * imageLevelWidthInBlocks * elementSize
end := as!u64(z1) * imageLevelHeightInBlocks * imageLevelWidthInBlocks * elementSize
if isWrite {
write(level.Data[start:end])
} else {
read(level.Data[start:end])
}
}
}
}
}
}
}

@spy_disabled
sub void accessImageSubresource(ref!ImageObject image, VkImageSubresourceRange rng, bool isWrite) {
VK_REMAINING_ARRAY_LAYERS := as!u32(0xFFFFFFFF)
accessImageSubresourceSlice(image, rng, 0, VK_REMAINING_ARRAY_LAYERS, isWrite)
}

@spy_disabled
sub void readImageSubresource(ref!ImageObject image, VkImageSubresourceRange rng) {
accessImageSubresource(image, rng, false)
}

@spy_disabled
sub void writeImageSubresource(ref!ImageObject image, VkImageSubresourceRange rng) {
layerCount := imageSubresourceLayerCount(image, rng)
levelCount := imageSubresourceLevelCount(image, rng)
for _ , _ , aspectBit in unpackImageAspectFlags(rng.aspectMask) {
if aspectBit in image.Aspects {
aspect := image.Aspects[aspectBit]
for layerIndex in (rng.baseArrayLayer .. rng.baseArrayLayer + layerCount) {
layer := aspect.Layers[layerIndex]
for mipLevel in (rng.baseMipLevel .. rng.baseMipLevel + levelCount) {
level := layer.Levels[mipLevel]
write(level.Data)
}
}
}
accessImageSubresource(image, rng, true)
}

sub bool is2DView3DImage(ref!ImageViewObject view) {
return ((view.Image.Info.ImageType == VK_IMAGE_TYPE_3D) &&
((view.Type == VK_IMAGE_VIEW_TYPE_2D) || (view.Type == VK_IMAGE_VIEW_TYPE_2D_ARRAY)))
}

@spy_disabled
sub void accessImageView(ref!ImageViewObject view, bool isWrite) {
if is2DView3DImage(view) {
rng := VkImageSubresourceRange(
aspectMask: view.SubresourceRange.aspectMask,
baseMipLevel: view.SubresourceRange.baseMipLevel,
levelCount: view.SubresourceRange.levelCount,
baseArrayLayer: 0,
layerCount: 1)
baseDepth := view.SubresourceRange.baseArrayLayer
depthCount := view.SubresourceRange.layerCount
accessImageSubresourceSlice(view.Image, rng, baseDepth, depthCount, isWrite)
} else {
accessImageSubresource(view.Image, view.SubresourceRange, isWrite)
}
}

@spy_disabled
sub void readImageView(ref!ImageViewObject view) {
accessImageView(view, false)
}

@spy_disabled
sub void writeImageView(ref!ImageViewObject view) {
accessImageView(view, true)
}

@spy_disabled
sub void updateImageViewQueue(ref!ImageViewObject view) {
if is2DView3DImage(view) {
rng := VkImageSubresourceRange(
aspectMask: view.SubresourceRange.aspectMask,
baseMipLevel: view.SubresourceRange.baseMipLevel,
levelCount: view.SubresourceRange.levelCount,
baseArrayLayer: 0,
layerCount: 1)
updateImageQueue(view.Image, rng)
} else {
updateImageQueue(view.Image, view.SubresourceRange)
}
}

Expand All @@ -226,11 +302,9 @@ sub void readMemoryInImageBindings(map!(u32, ref!VkDescriptorImageInfo) imageBin
_ = Samplers[v.Sampler]
if v.ImageView != as!VkImageView(0) {
if (v.ImageView in ImageViews) {
imageViewObj := ImageViews[v.ImageView]
imageObj := imageViewObj.Image
rng := imageViewObj.SubresourceRange
updateImageQueue(imageObj, rng)
readImageSubresource(imageObj, rng)
view := ImageViews[v.ImageView]
updateImageViewQueue(view)
readImageView(view)
}
}
}
Expand All @@ -241,11 +315,11 @@ sub void writeMemoryInImageBindings(map!(u32, ref!VkDescriptorImageInfo) imageBi
for _, _, v in imageBindings {
_ = Samplers[v.Sampler]
if v.ImageView != as!VkImageView(0) {
imageViewObj := ImageViews[v.ImageView]
imageObj := imageViewObj.Image
rng := imageViewObj.SubresourceRange
writeImageSubresource(imageObj, rng)
updateImageQueue(imageObj, rng)
if (v.ImageView in ImageViews) {
view := ImageViews[v.ImageView]
updateImageViewQueue(view)
writeImageView(view)
}
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions gapis/api/vulkan/api/renderpass_framebuffer.api
Original file line number Diff line number Diff line change
Expand Up @@ -412,13 +412,13 @@ sub void loadImageAttachment(u32 attachmentID) {
if attachment.Image != null {
switch desc.loadOp {
case VK_ATTACHMENT_LOAD_OP_LOAD: {
readImageSubresource(attachment.Image, attachment.SubresourceRange)
updateImageQueue(attachment.Image, attachment.SubresourceRange)
readImageView(attachment)
updateImageViewQueue(attachment)
}
default: {
// write to the attachment image, to prevent any dependencies on previous writes
updateImageQueue(attachment.Image, attachment.SubresourceRange)
writeImageSubresource(attachment.Image, attachment.SubresourceRange)
updateImageViewQueue(attachment)
writeImageView(attachment)
}
}
}
Expand All @@ -437,8 +437,8 @@ sub void storeImageAttachment(u32 attachmentID) {
}
switch desc.storeOp {
case VK_ATTACHMENT_STORE_OP_STORE: {
writeImageSubresource(attachment.Image, attachment.SubresourceRange)
updateImageQueue(attachment.Image, attachment.SubresourceRange)
writeImageView(attachment)
updateImageViewQueue(attachment)
}
default: {
// do nothing
Expand Down

0 comments on commit 4e1d040

Please sign in to comment.