Cleanup: using the proper Image subregion structure
VkImage use different structures to represent subregions:
- VkImageSubresource (Single mip level, single layer)
- VkImageSubresourceLayers (Single mip level, multiple layers)
- VkImageSubresourceRange (Multiple mip levels, multiple layers)
This cl changes the subregion structure used in vk::Image and in the
Blitter so that it contains the information required for the current
task and no more than that.
Bug: b/159045555
Change-Id: I186a90ff321318319c01a0718a95bbae2d2eb26a
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/45788
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Device/Blitter.cpp b/src/Device/Blitter.cpp
index 3b761d4..5794e52 100644
--- a/src/Device/Blitter.cpp
+++ b/src/Device/Blitter.cpp
@@ -85,11 +85,10 @@
return;
}
- VkImageSubresourceLayers subresLayers = {
+ VkImageSubresource subres = {
subresourceRange.aspectMask,
subresourceRange.baseMipLevel,
- subresourceRange.baseArrayLayer,
- 1
+ subresourceRange.baseArrayLayer
};
uint32_t lastMipLevel = dest->getLastMipLevel(subresourceRange);
@@ -102,9 +101,9 @@
area = *renderArea;
}
- for(; subresLayers.mipLevel <= lastMipLevel; subresLayers.mipLevel++)
+ for(; subres.mipLevel <= lastMipLevel; subres.mipLevel++)
{
- VkExtent3D extent = dest->getMipLevelExtent(aspect, subresLayers.mipLevel);
+ VkExtent3D extent = dest->getMipLevelExtent(aspect, subres.mipLevel);
if(!renderArea)
{
area.extent.width = extent.width;
@@ -114,10 +113,10 @@
BlitData data = {
pixel, nullptr, // source, dest
- format.bytes(), // sPitchB
- dest->rowPitchBytes(aspect, subresLayers.mipLevel), // dPitchB
- 0, // sSliceB (unused in clear operations)
- dest->slicePitchBytes(aspect, subresLayers.mipLevel), // dSliceB
+ format.bytes(), // sPitchB
+ dest->rowPitchBytes(aspect, subres.mipLevel), // dPitchB
+ 0, // sSliceB (unused in clear operations)
+ dest->slicePitchBytes(aspect, subres.mipLevel), // dSliceB
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, // x0, y0, z0, w, h, d
@@ -133,21 +132,20 @@
if(renderArea && dest->is3DSlice())
{
// Reinterpret layers as depth slices
- subresLayers.baseArrayLayer = 0;
- subresLayers.layerCount = 1;
+ subres.arrayLayer = 0;
for(uint32_t depth = subresourceRange.baseArrayLayer; depth <= lastLayer; depth++)
{
- data.dest = dest->getTexelPointer({ 0, 0, static_cast<int32_t>(depth) }, subresLayers);
+ data.dest = dest->getTexelPointer({ 0, 0, static_cast<int32_t>(depth) }, subres);
blitRoutine(&data);
}
}
else
{
- for(subresLayers.baseArrayLayer = subresourceRange.baseArrayLayer; subresLayers.baseArrayLayer <= lastLayer; subresLayers.baseArrayLayer++)
+ for(subres.arrayLayer = subresourceRange.baseArrayLayer; subres.arrayLayer <= lastLayer; subres.arrayLayer++)
{
for(uint32_t depth = 0; depth < extent.depth; depth++)
{
- data.dest = dest->getTexelPointer({ 0, 0, static_cast<int32_t>(depth) }, subresLayers);
+ data.dest = dest->getTexelPointer({ 0, 0, static_cast<int32_t>(depth) }, subres);
blitRoutine(&data);
}
@@ -208,11 +206,10 @@
return false;
}
- VkImageSubresourceLayers subresLayers = {
+ VkImageSubresource subres = {
subresourceRange.aspectMask,
subresourceRange.baseMipLevel,
- subresourceRange.baseArrayLayer,
- 1
+ subresourceRange.baseArrayLayer
};
uint32_t lastMipLevel = dest->getLastMipLevel(subresourceRange);
uint32_t lastLayer = dest->getLastLayerIndex(subresourceRange);
@@ -224,11 +221,11 @@
area = *renderArea;
}
- for(; subresLayers.mipLevel <= lastMipLevel; subresLayers.mipLevel++)
+ for(; subres.mipLevel <= lastMipLevel; subres.mipLevel++)
{
- int rowPitchBytes = dest->rowPitchBytes(aspect, subresLayers.mipLevel);
- int slicePitchBytes = dest->slicePitchBytes(aspect, subresLayers.mipLevel);
- VkExtent3D extent = dest->getMipLevelExtent(aspect, subresLayers.mipLevel);
+ int rowPitchBytes = dest->rowPitchBytes(aspect, subres.mipLevel);
+ int slicePitchBytes = dest->slicePitchBytes(aspect, subres.mipLevel);
+ VkExtent3D extent = dest->getMipLevelExtent(aspect, subres.mipLevel);
if(!renderArea)
{
area.extent.width = extent.width;
@@ -239,12 +236,12 @@
extent.depth = 1; // The 3D image is instead interpreted as a 2D image with layers
}
- for(subresLayers.baseArrayLayer = subresourceRange.baseArrayLayer; subresLayers.baseArrayLayer <= lastLayer; subresLayers.baseArrayLayer++)
+ for(subres.arrayLayer = subresourceRange.baseArrayLayer; subres.arrayLayer <= lastLayer; subres.arrayLayer++)
{
for(uint32_t depth = 0; depth < extent.depth; depth++)
{
uint8_t *slice = (uint8_t *)dest->getTexelPointer(
- { area.offset.x, area.offset.y, static_cast<int32_t>(depth) }, subresLayers);
+ { area.offset.x, area.offset.y, static_cast<int32_t>(depth) }, subres);
for(int j = 0; j < dest->getSampleCountFlagBits(); j++)
{
@@ -1745,8 +1742,11 @@
false, // filter3D
};
- VkImageSubresourceLayers srcSubresLayers = subresource;
- srcSubresLayers.layerCount = 1;
+ VkImageSubresource srcSubres = {
+ subresource.aspectMask,
+ subresource.mipLevel,
+ subresource.baseArrayLayer
+ };
VkImageSubresourceRange srcSubresRange = {
subresource.aspectMask,
@@ -1758,9 +1758,9 @@
uint32_t lastLayer = src->getLastLayerIndex(srcSubresRange);
- for(; srcSubresLayers.baseArrayLayer <= lastLayer; srcSubresLayers.baseArrayLayer++)
+ for(; srcSubres.arrayLayer <= lastLayer; srcSubres.arrayLayer++)
{
- data.source = src->getTexelPointer({ 0, 0, 0 }, srcSubresLayers);
+ data.source = src->getTexelPointer({ 0, 0, 0 }, srcSubres);
ASSERT(data.source < src->end());
blitRoutine(&data);
}
@@ -1807,8 +1807,11 @@
false, // filter3D
};
- VkImageSubresourceLayers dstSubresLayers = subresource;
- dstSubresLayers.layerCount = 1;
+ VkImageSubresource dstSubres = {
+ subresource.aspectMask,
+ subresource.mipLevel,
+ subresource.baseArrayLayer
+ };
VkImageSubresourceRange dstSubresRange = {
subresource.aspectMask,
@@ -1820,9 +1823,9 @@
uint32_t lastLayer = dst->getLastLayerIndex(dstSubresRange);
- for(; dstSubresLayers.baseArrayLayer <= lastLayer; dstSubresLayers.baseArrayLayer++)
+ for(; dstSubres.arrayLayer <= lastLayer; dstSubres.arrayLayer++)
{
- data.dest = dst->getTexelPointer({ 0, 0, 0 }, dstSubresLayers);
+ data.dest = dst->getTexelPointer({ 0, 0, 0 }, dstSubres);
ASSERT(data.dest < dst->end());
blitRoutine(&data);
}
@@ -1927,34 +1930,32 @@
false, // filter3D
};
- VkImageSubresourceLayers srcSubresLayers = {
+ VkImageSubresource srcSubres = {
region.srcSubresource.aspectMask,
region.srcSubresource.mipLevel,
- region.srcSubresource.baseArrayLayer,
- 1
+ region.srcSubresource.baseArrayLayer
};
- VkImageSubresourceLayers dstSubresLayers = {
+ VkImageSubresource dstSubres = {
region.dstSubresource.aspectMask,
region.dstSubresource.mipLevel,
- region.dstSubresource.baseArrayLayer,
- 1
+ region.dstSubresource.baseArrayLayer
};
- VkImageSubresourceRange srcSubresRange = {
- region.srcSubresource.aspectMask,
- region.srcSubresource.mipLevel,
+ VkImageSubresourceRange dstSubresRange = {
+ region.dstSubresource.aspectMask,
+ region.dstSubresource.mipLevel,
1,
- region.srcSubresource.baseArrayLayer,
- region.srcSubresource.layerCount
+ region.dstSubresource.baseArrayLayer,
+ region.dstSubresource.layerCount
};
- uint32_t lastLayer = src->getLastLayerIndex(srcSubresRange);
+ uint32_t lastLayer = src->getLastLayerIndex(dstSubresRange);
- for(; srcSubresLayers.baseArrayLayer <= lastLayer; srcSubresLayers.baseArrayLayer++, dstSubresLayers.baseArrayLayer++)
+ for(; dstSubres.arrayLayer <= lastLayer; srcSubres.arrayLayer++, dstSubres.arrayLayer++)
{
- data.source = src->getTexelPointer({ 0, 0, 0 }, srcSubresLayers);
- data.dest = dst->getTexelPointer({ 0, 0, 0 }, dstSubresLayers);
+ data.source = src->getTexelPointer({ 0, 0, 0 }, srcSubres);
+ data.dest = dst->getTexelPointer({ 0, 0, 0 }, dstSubres);
ASSERT(data.source < src->end());
ASSERT(data.dest < dst->end());
@@ -2011,25 +2012,24 @@
return function("BlitRoutine");
}
-void Blitter::updateBorders(vk::Image *image, const VkImageSubresourceLayers &subresourceLayers)
+void Blitter::updateBorders(vk::Image *image, const VkImageSubresource &subresource)
{
- ASSERT(image->getArrayLayers() >= (subresourceLayers.baseArrayLayer + 6));
+ ASSERT(image->getArrayLayers() >= (subresource.arrayLayer + 6));
// From Vulkan 1.1 spec, section 11.5. Image Views:
// "For cube and cube array image views, the layers of the image view starting
// at baseArrayLayer correspond to faces in the order +X, -X, +Y, -Y, +Z, -Z."
- VkImageSubresourceLayers posX = subresourceLayers;
- posX.layerCount = 1;
- VkImageSubresourceLayers negX = posX;
- negX.baseArrayLayer++;
- VkImageSubresourceLayers posY = negX;
- posY.baseArrayLayer++;
- VkImageSubresourceLayers negY = posY;
- negY.baseArrayLayer++;
- VkImageSubresourceLayers posZ = negY;
- posZ.baseArrayLayer++;
- VkImageSubresourceLayers negZ = posZ;
- negZ.baseArrayLayer++;
+ VkImageSubresource posX = subresource;
+ VkImageSubresource negX = posX;
+ negX.arrayLayer++;
+ VkImageSubresource posY = negX;
+ posY.arrayLayer++;
+ VkImageSubresource negY = posY;
+ negY.arrayLayer++;
+ VkImageSubresource posZ = negY;
+ posZ.arrayLayer++;
+ VkImageSubresource negZ = posZ;
+ negZ.arrayLayer++;
// Copy top / bottom
copyCubeEdge(image, posX, BOTTOM, negY, RIGHT);
@@ -2062,7 +2062,7 @@
copyCubeEdge(image, negZ, LEFT, posX, RIGHT);
// Compute corner colors
- VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresourceLayers.aspectMask);
+ VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
vk::Format format = image->getFormat(aspect);
VkSampleCountFlagBits samples = image->getSampleCountFlagBits();
State state(format, format, samples, samples, Options{ 0xF });
@@ -2077,10 +2077,10 @@
return;
}
- VkExtent3D extent = image->getMipLevelExtent(aspect, subresourceLayers.mipLevel);
+ VkExtent3D extent = image->getMipLevelExtent(aspect, subresource.mipLevel);
CubeBorderData data = {
image->getTexelPointer({ 0, 0, 0 }, posX),
- image->rowPitchBytes(aspect, subresourceLayers.mipLevel),
+ image->rowPitchBytes(aspect, subresource.mipLevel),
static_cast<uint32_t>(image->getLayerSize(aspect)),
extent.width
};
@@ -2088,14 +2088,12 @@
}
void Blitter::copyCubeEdge(vk::Image *image,
- const VkImageSubresourceLayers &dstSubresourceLayers, Edge dstEdge,
- const VkImageSubresourceLayers &srcSubresourceLayers, Edge srcEdge)
+ const VkImageSubresource &dstSubresource, Edge dstEdge,
+ const VkImageSubresource &srcSubresource, Edge srcEdge)
{
- ASSERT(srcSubresourceLayers.aspectMask == dstSubresourceLayers.aspectMask);
- ASSERT(srcSubresourceLayers.mipLevel == dstSubresourceLayers.mipLevel);
- ASSERT(srcSubresourceLayers.baseArrayLayer != dstSubresourceLayers.baseArrayLayer);
- ASSERT(srcSubresourceLayers.layerCount == 1);
- ASSERT(dstSubresourceLayers.layerCount == 1);
+ ASSERT(srcSubresource.aspectMask == dstSubresource.aspectMask);
+ ASSERT(srcSubresource.mipLevel == dstSubresource.mipLevel);
+ ASSERT(srcSubresource.arrayLayer != dstSubresource.arrayLayer);
// Figure out if the edges to be copied in reverse order respectively from one another
// The copy should be reversed whenever the same edges are contiguous or if we're
@@ -2111,11 +2109,11 @@
((srcEdge == BOTTOM) && (dstEdge == LEFT)) ||
((srcEdge == LEFT) && (dstEdge == BOTTOM));
- VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(srcSubresourceLayers.aspectMask);
+ VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(srcSubresource.aspectMask);
int bytes = image->getFormat(aspect).bytes();
- int pitchB = image->rowPitchBytes(aspect, srcSubresourceLayers.mipLevel);
+ int pitchB = image->rowPitchBytes(aspect, srcSubresource.mipLevel);
- VkExtent3D extent = image->getMipLevelExtent(aspect, srcSubresourceLayers.mipLevel);
+ VkExtent3D extent = image->getMipLevelExtent(aspect, srcSubresource.mipLevel);
int w = extent.width;
int h = extent.height;
if(w != h)
@@ -2143,8 +2141,8 @@
dstOffset.y += reverse ? h : 1;
}
- const uint8_t *src = static_cast<const uint8_t *>(image->getTexelPointer(srcOffset, srcSubresourceLayers));
- uint8_t *dst = static_cast<uint8_t *>(image->getTexelPointer(dstOffset, dstSubresourceLayers));
+ const uint8_t *src = static_cast<const uint8_t *>(image->getTexelPointer(srcOffset, srcSubresource));
+ uint8_t *dst = static_cast<uint8_t *>(image->getTexelPointer(dstOffset, dstSubresource));
ASSERT((src < image->end()) && ((src + (w * srcDelta)) < image->end()));
ASSERT((dst < image->end()) && ((dst + (w * dstDelta)) < image->end()));
diff --git a/src/Device/Blitter.hpp b/src/Device/Blitter.hpp
index 2e6f946..316d7ec 100644
--- a/src/Device/Blitter.hpp
+++ b/src/Device/Blitter.hpp
@@ -147,7 +147,7 @@
void blitToBuffer(const vk::Image *src, VkImageSubresourceLayers subresource, VkOffset3D offset, VkExtent3D extent, uint8_t *dst, int bufferRowPitch, int bufferSlicePitch);
void blitFromBuffer(const vk::Image *dst, VkImageSubresourceLayers subresource, VkOffset3D offset, VkExtent3D extent, uint8_t *src, int bufferRowPitch, int bufferSlicePitch);
- void updateBorders(vk::Image *image, const VkImageSubresourceLayers &subresourceLayers);
+ void updateBorders(vk::Image *image, const VkImageSubresource &subresource);
private:
enum Edge
@@ -185,8 +185,8 @@
void computeCubeCorner(Pointer<Byte> &layer, Int &x0, Int &x1, Int &y0, Int &y1, Int &pitchB, const State &state);
void copyCubeEdge(vk::Image *image,
- const VkImageSubresourceLayers &dstSubresourceLayers, Edge dstEdge,
- const VkImageSubresourceLayers &srcSubresourceLayers, Edge srcEdge);
+ const VkImageSubresource &dstSubresource, Edge dstEdge,
+ const VkImageSubresource &srcSubresource, Edge srcEdge);
marl::mutex blitMutex;
RoutineCache<State, BlitFunction::CFunctionType> blitCache GUARDED_BY(blitMutex);
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index e2fbac4..1995d78 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -345,8 +345,8 @@
int srcBytesPerBlock = srcFormat.bytesPerBlock();
ASSERT(srcBytesPerBlock == dstFormat.bytesPerBlock());
- const uint8_t *srcMem = static_cast<const uint8_t *>(getTexelPointer(region.srcOffset, region.srcSubresource));
- uint8_t *dstMem = static_cast<uint8_t *>(dstImage->getTexelPointer(region.dstOffset, region.dstSubresource));
+ const uint8_t *srcMem = static_cast<const uint8_t *>(getTexelPointer(region.srcOffset, { region.srcSubresource.aspectMask, region.srcSubresource.mipLevel, region.srcSubresource.baseArrayLayer }));
+ uint8_t *dstMem = static_cast<uint8_t *>(dstImage->getTexelPointer(region.dstOffset, { region.dstSubresource.aspectMask, region.dstSubresource.mipLevel, region.dstSubresource.baseArrayLayer }));
int srcRowPitchBytes = rowPitchBytes(srcAspect, region.srcSubresource.mipLevel);
int srcSlicePitchBytes = slicePitchBytes(srcAspect, region.srcSubresource.mipLevel);
@@ -460,7 +460,7 @@
int bufferSlicePitchBytes = bufferExtent.height * bufferRowPitchBytes;
uint8_t *bufferMemory = static_cast<uint8_t *>(buffer->getOffsetPointer(region.bufferOffset));
- uint8_t *imageMemory = static_cast<uint8_t *>(getTexelPointer(region.imageOffset, region.imageSubresource));
+ uint8_t *imageMemory = static_cast<uint8_t *>(getTexelPointer(region.imageOffset, { region.imageSubresource.aspectMask, region.imageSubresource.mipLevel, region.imageSubresource.baseArrayLayer }));
uint8_t *srcMemory = bufferIsSource ? bufferMemory : imageMemory;
uint8_t *dstMemory = bufferIsSource ? imageMemory : bufferMemory;
int imageRowPitchBytes = rowPitchBytes(aspect, region.imageSubresource.mipLevel);
@@ -574,11 +574,11 @@
copy(srcBuffer, region, true);
}
-void *Image::getTexelPointer(const VkOffset3D &offset, const VkImageSubresourceLayers &subresource) const
+void *Image::getTexelPointer(const VkOffset3D &offset, const VkImageSubresource &subresource) const
{
VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
return deviceMemory->getOffsetPointer(texelOffsetBytesInStorage(offset, subresource) +
- getMemoryOffset(aspect, subresource.mipLevel, subresource.baseArrayLayer));
+ getMemoryOffset(aspect, subresource.mipLevel, subresource.arrayLayer));
}
VkExtent3D Image::imageExtentInBlocks(const VkExtent3D &extent, VkImageAspectFlagBits aspect) const
@@ -652,7 +652,7 @@
return (isCube() && !format.isCompressed()) ? 1 : 0;
}
-VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D &offset, const VkImageSubresourceLayers &subresource) const
+VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D &offset, const VkImageSubresource &subresource) const
{
VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
VkOffset3D adjustedOffset = imageOffsetInBlocks(offset, aspect);
@@ -1012,6 +1012,40 @@
void Image::prepareForSampling(const VkImageSubresourceRange &subresourceRange)
{
+ uint32_t lastLayer = getLastLayerIndex(subresourceRange);
+ uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
+
+ VkImageSubresource subresource = {
+ subresourceRange.aspectMask,
+ subresourceRange.baseMipLevel,
+ subresourceRange.baseArrayLayer
+ };
+
+ // First, decompress all relevant dirty subregions
+ for(subresource.arrayLayer = subresourceRange.baseArrayLayer;
+ subresource.arrayLayer <= lastLayer;
+ subresource.arrayLayer++)
+ {
+ for(subresource.mipLevel = subresourceRange.baseMipLevel;
+ subresource.mipLevel <= lastMipLevel;
+ subresource.mipLevel++)
+ {
+ decompress(subresource);
+ }
+ }
+
+ // Second, update cubemap borders
+ subresource.arrayLayer = subresourceRange.baseArrayLayer;
+ for(subresource.mipLevel = subresourceRange.baseMipLevel;
+ subresource.mipLevel <= lastMipLevel;
+ subresource.mipLevel++)
+ {
+ updateCube(subresource);
+ }
+}
+
+void Image::decompress(const VkImageSubresource &subresource)
+{
if(decompressedImage)
{
switch(format)
@@ -1026,7 +1060,7 @@
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
- decodeETC2(subresourceRange);
+ decodeETC2(subresource);
break;
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
@@ -1044,7 +1078,7 @@
case VK_FORMAT_BC6H_SFLOAT_BLOCK:
case VK_FORMAT_BC7_UNORM_BLOCK:
case VK_FORMAT_BC7_SRGB_BLOCK:
- decodeBC(subresourceRange);
+ decodeBC(subresource);
break;
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
@@ -1088,119 +1122,91 @@
case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT:
case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT:
- decodeASTC(subresourceRange);
+ decodeASTC(subresource);
break;
default:
break;
}
}
+}
+void Image::updateCube(const VkImageSubresource &subres)
+{
if(isCube() && (arrayLayers >= 6))
{
- VkImageSubresourceLayers subresourceLayers = {
- subresourceRange.aspectMask,
- subresourceRange.baseMipLevel,
- subresourceRange.baseArrayLayer,
- 6
- };
+ VkImageSubresource subresource = subres;
// Update the borders of all the groups of 6 layers that can be part of a cubemaps but don't
// touch leftover layers that cannot be part of cubemaps.
- uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
- for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++)
+ for(subresource.arrayLayer = 0; subresource.arrayLayer < arrayLayers - 5; subresource.arrayLayer += 6)
{
- for(subresourceLayers.baseArrayLayer = 0;
- subresourceLayers.baseArrayLayer < arrayLayers - 5;
- subresourceLayers.baseArrayLayer += 6)
- {
- device->getBlitter()->updateBorders(decompressedImage ? decompressedImage : this, subresourceLayers);
- }
+ device->getBlitter()->updateBorders(decompressedImage ? decompressedImage : this, subresource);
}
}
}
-void Image::decodeETC2(const VkImageSubresourceRange &subresourceRange) const
+void Image::decodeETC2(const VkImageSubresource &subresource)
{
ASSERT(decompressedImage);
ETC_Decoder::InputType inputType = GetInputType(format);
- uint32_t lastLayer = getLastLayerIndex(subresourceRange);
- uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
-
int bytes = decompressedImage->format.bytes();
bool fakeAlpha = (format == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK) || (format == VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK);
size_t sizeToWrite = 0;
- VkImageSubresourceLayers subresourceLayers = { subresourceRange.aspectMask, subresourceRange.baseMipLevel, subresourceRange.baseArrayLayer, 1 };
- for(; subresourceLayers.baseArrayLayer <= lastLayer; subresourceLayers.baseArrayLayer++)
+ VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresource.aspectMask), subresource.mipLevel);
+
+ int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
+
+ if(fakeAlpha)
{
- for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++)
+ // To avoid overflow in case of cube textures, which are offset in memory to account for the border,
+ // compute the size from the first pixel to the last pixel, excluding any padding or border before
+ // the first pixel or after the last pixel.
+ sizeToWrite = ((mipLevelExtent.height - 1) * pitchB) + (mipLevelExtent.width * bytes);
+ }
+
+ for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
+ {
+ uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresource));
+ uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresource));
+
+ if(fakeAlpha)
{
- VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceLayers.aspectMask), subresourceLayers.mipLevel);
-
- int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
-
- if(fakeAlpha)
- {
- // To avoid overflow in case of cube textures, which are offset in memory to account for the border,
- // compute the size from the first pixel to the last pixel, excluding any padding or border before
- // the first pixel or after the last pixel.
- sizeToWrite = ((mipLevelExtent.height - 1) * pitchB) + (mipLevelExtent.width * bytes);
- }
-
- for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
- {
- uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresourceLayers));
- uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresourceLayers));
-
- if(fakeAlpha)
- {
- ASSERT((dest + sizeToWrite) < decompressedImage->end());
- memset(dest, 0xFF, sizeToWrite);
- }
-
- ETC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height,
- pitchB, bytes, inputType);
- }
+ ASSERT((dest + sizeToWrite) < decompressedImage->end());
+ memset(dest, 0xFF, sizeToWrite);
}
+
+ ETC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height,
+ pitchB, bytes, inputType);
}
}
-void Image::decodeBC(const VkImageSubresourceRange &subresourceRange) const
+void Image::decodeBC(const VkImageSubresource &subresource)
{
ASSERT(decompressedImage);
int n = GetBCn(format);
int noAlphaU = GetNoAlphaOrUnsigned(format);
- uint32_t lastLayer = getLastLayerIndex(subresourceRange);
- uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
-
int bytes = decompressedImage->format.bytes();
- VkImageSubresourceLayers subresourceLayers = { subresourceRange.aspectMask, subresourceRange.baseMipLevel, subresourceRange.baseArrayLayer, 1 };
- for(; subresourceLayers.baseArrayLayer <= lastLayer; subresourceLayers.baseArrayLayer++)
+ VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresource.aspectMask), subresource.mipLevel);
+
+ int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
+
+ for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
{
- for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++)
- {
- VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceLayers.aspectMask), subresourceLayers.mipLevel);
+ uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresource));
+ uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresource));
- int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
-
- for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
- {
- uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresourceLayers));
- uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresourceLayers));
-
- BC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height,
- pitchB, bytes, n, noAlphaU);
- }
- }
+ BC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height,
+ pitchB, bytes, n, noAlphaU);
}
}
-void Image::decodeASTC(const VkImageSubresourceRange &subresourceRange) const
+void Image::decodeASTC(const VkImageSubresource &subresource)
{
ASSERT(decompressedImage);
@@ -1209,39 +1215,29 @@
int zBlockSize = 1;
bool isUnsigned = format.isUnsignedComponent(0);
- uint32_t lastLayer = getLastLayerIndex(subresourceRange);
- uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
-
int bytes = decompressedImage->format.bytes();
- VkImageSubresourceLayers subresourceLayers = { subresourceRange.aspectMask, subresourceRange.baseMipLevel, subresourceRange.baseArrayLayer, 1 };
- for(; subresourceLayers.baseArrayLayer <= lastLayer; subresourceLayers.baseArrayLayer++)
+ VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresource.aspectMask), subresource.mipLevel);
+
+ int xblocks = (mipLevelExtent.width + xBlockSize - 1) / xBlockSize;
+ int yblocks = (mipLevelExtent.height + yBlockSize - 1) / yBlockSize;
+ int zblocks = (zBlockSize > 1) ? (mipLevelExtent.depth + zBlockSize - 1) / zBlockSize : 1;
+
+ if(xblocks <= 0 || yblocks <= 0 || zblocks <= 0)
{
- for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++)
- {
- VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceLayers.aspectMask), subresourceLayers.mipLevel);
+ return;
+ }
- int xblocks = (mipLevelExtent.width + xBlockSize - 1) / xBlockSize;
- int yblocks = (mipLevelExtent.height + yBlockSize - 1) / yBlockSize;
- int zblocks = (zBlockSize > 1) ? (mipLevelExtent.depth + zBlockSize - 1) / zBlockSize : 1;
+ int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
+ int sliceB = decompressedImage->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
- if(xblocks <= 0 || yblocks <= 0 || zblocks <= 0)
- {
- continue;
- }
+ for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
+ {
+ uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresource));
+ uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresource));
- int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
- int sliceB = decompressedImage->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
-
- for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
- {
- uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresourceLayers));
- uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresourceLayers));
-
- ASTC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height, mipLevelExtent.depth, bytes, pitchB, sliceB,
- xBlockSize, yBlockSize, zBlockSize, xblocks, yblocks, zblocks, isUnsigned);
- }
- }
+ ASTC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height, mipLevelExtent.depth, bytes, pitchB, sliceB,
+ xBlockSize, yBlockSize, zBlockSize, xblocks, yblocks, zblocks, isUnsigned);
}
}
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index 0401df3..e29efb0 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -77,7 +77,7 @@
VkExtent3D getMipLevelExtent(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
int rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
- void *getTexelPointer(const VkOffset3D &offset, const VkImageSubresourceLayers &subresource) const;
+ void *getTexelPointer(const VkOffset3D &offset, const VkImageSubresource &subresource) const;
bool isCube() const;
bool is3DSlice() const;
uint8_t *end() const;
@@ -104,7 +104,7 @@
VkDeviceSize getLayerOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
VkDeviceSize getMemoryOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const;
VkDeviceSize getMemoryOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) const;
- VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D &offset, const VkImageSubresourceLayers &subresource) const;
+ VkDeviceSize texelOffsetBytesInStorage(const VkOffset3D &offset, const VkImageSubresource &subresource) const;
VkDeviceSize getMemoryOffset(VkImageAspectFlagBits aspect) const;
VkExtent3D imageExtentInBlocks(const VkExtent3D &extent, VkImageAspectFlagBits aspect) const;
VkOffset3D imageOffsetInBlocks(const VkOffset3D &offset, VkImageAspectFlagBits aspect) const;
@@ -112,9 +112,11 @@
VkFormat getClearFormat() const;
void clear(void *pixelData, VkFormat pixelFormat, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D &renderArea);
int borderSize() const;
- void decodeETC2(const VkImageSubresourceRange &subresourceRange) const;
- void decodeBC(const VkImageSubresourceRange &subresourceRange) const;
- void decodeASTC(const VkImageSubresourceRange &subresourceRange) const;
+ void decompress(const VkImageSubresource &subresource);
+ void updateCube(const VkImageSubresource &subresource);
+ void decodeETC2(const VkImageSubresource &subresource);
+ void decodeBC(const VkImageSubresource &subresource);
+ void decodeASTC(const VkImageSubresource &subresource);
const Device *const device = nullptr;
DeviceMemory *deviceMemory = nullptr;
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
index 4b8880d..37a8aa0 100644
--- a/src/Vulkan/VkImageView.cpp
+++ b/src/Vulkan/VkImageView.cpp
@@ -296,14 +296,13 @@
{
ASSERT(mipLevel < subresourceRange.levelCount);
- VkImageSubresourceLayers imageSubresourceLayers = {
+ VkImageSubresource imageSubresource = {
static_cast<VkImageAspectFlags>(aspect),
subresourceRange.baseMipLevel + mipLevel,
subresourceRange.baseArrayLayer + layer,
- subresourceRange.layerCount
};
- return getImage(usage)->getTexelPointer(offset, imageSubresourceLayers);
+ return getImage(usage)->getTexelPointer(offset, imageSubresource);
}
} // namespace vk