Commit 46159715 by Alexis Hetu Committed by Alexis Hétu

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: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 9b152366
......@@ -85,11 +85,10 @@ void Blitter::clear(void *pixel, vk::Format format, vk::Image *dest, const vk::F
return;
}
VkImageSubresourceLayers subresLayers = {
VkImageSubresource subres = {
subresourceRange.aspectMask,
subresourceRange.baseMipLevel,
subresourceRange.baseArrayLayer,
1
subresourceRange.baseArrayLayer
};
uint32_t lastMipLevel = dest->getLastMipLevel(subresourceRange);
......@@ -102,9 +101,9 @@ void Blitter::clear(void *pixel, vk::Format format, vk::Image *dest, const vk::F
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 @@ void Blitter::clear(void *pixel, vk::Format format, vk::Image *dest, const vk::F
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 @@ void Blitter::clear(void *pixel, vk::Format format, vk::Image *dest, const vk::F
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 @@ bool Blitter::fastClear(void *pixel, vk::Format format, vk::Image *dest, const v
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 @@ bool Blitter::fastClear(void *pixel, vk::Format format, vk::Image *dest, const v
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 @@ bool Blitter::fastClear(void *pixel, vk::Format format, vk::Image *dest, const v
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 @@ void Blitter::blitToBuffer(const vk::Image *src, VkImageSubresourceLayers subres
false, // filter3D
};
VkImageSubresourceLayers srcSubresLayers = subresource;
srcSubresLayers.layerCount = 1;
VkImageSubresource srcSubres = {
subresource.aspectMask,
subresource.mipLevel,
subresource.baseArrayLayer
};
VkImageSubresourceRange srcSubresRange = {
subresource.aspectMask,
......@@ -1758,9 +1758,9 @@ void Blitter::blitToBuffer(const vk::Image *src, VkImageSubresourceLayers subres
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 @@ void Blitter::blitFromBuffer(const vk::Image *dst, VkImageSubresourceLayers subr
false, // filter3D
};
VkImageSubresourceLayers dstSubresLayers = subresource;
dstSubresLayers.layerCount = 1;
VkImageSubresource dstSubres = {
subresource.aspectMask,
subresource.mipLevel,
subresource.baseArrayLayer
};
VkImageSubresourceRange dstSubresRange = {
subresource.aspectMask,
......@@ -1820,9 +1823,9 @@ void Blitter::blitFromBuffer(const vk::Image *dst, VkImageSubresourceLayers subr
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 @@ void Blitter::blit(const vk::Image *src, vk::Image *dst, VkImageBlit region, VkF
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 @@ Blitter::CornerUpdateRoutineType Blitter::generateCornerUpdate(const State &stat
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 @@ void Blitter::updateBorders(vk::Image *image, const VkImageSubresourceLayers &su
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 @@ void Blitter::updateBorders(vk::Image *image, const VkImageSubresourceLayers &su
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::updateBorders(vk::Image *image, const VkImageSubresourceLayers &su
}
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 @@ void Blitter::copyCubeEdge(vk::Image *image,
((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 @@ void Blitter::copyCubeEdge(vk::Image *image,
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()));
......
......@@ -147,7 +147,7 @@ public:
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 @@ private:
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);
......
......@@ -345,8 +345,8 @@ void Image::copyTo(Image *dstImage, const VkImageCopy &region) const
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 @@ void Image::copy(Buffer *buffer, const VkBufferImageCopy &region, bool bufferIsS
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 @@ void Image::copyFrom(Buffer *srcBuffer, const VkBufferImageCopy &region)
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 @@ int Image::borderSize() const
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::clear(const VkClearValue &clearValue, const vk::Format &viewFormat,
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 @@ void Image::prepareForSampling(const VkImageSubresourceRange &subresourceRange)
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 @@ void Image::prepareForSampling(const VkImageSubresourceRange &subresourceRange)
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 @@ void Image::prepareForSampling(const VkImageSubresourceRange &subresourceRange)
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++)
{
for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++)
{
VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceLayers.aspectMask), subresourceLayers.mipLevel);
VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresource.aspectMask), subresource.mipLevel);
int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.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)
{
// 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);
}
if(fakeAlpha)
{
ASSERT((dest + sizeToWrite) < decompressedImage->end());
memset(dest, 0xFF, sizeToWrite);
}
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));
ETC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height,
pitchB, bytes, inputType);
}
if(fakeAlpha)
{
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++)
{
for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++)
{
VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceLayers.aspectMask), subresourceLayers.mipLevel);
VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresource.aspectMask), subresource.mipLevel);
int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.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++)
{
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));
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));
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 @@ void Image::decodeASTC(const VkImageSubresourceRange &subresourceRange) const
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++)
{
for(; subresourceLayers.mipLevel <= lastMipLevel; subresourceLayers.mipLevel++)
{
VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceLayers.aspectMask), subresourceLayers.mipLevel);
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;
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)
{
continue;
}
if(xblocks <= 0 || yblocks <= 0 || zblocks <= 0)
{
return;
}
int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
int sliceB = decompressedImage->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresourceLayers.mipLevel);
int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
int sliceB = decompressedImage->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.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));
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));
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);
}
}
......
......@@ -77,7 +77,7 @@ public:
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 @@ private:
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 @@ private:
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;
......
......@@ -296,14 +296,13 @@ void *ImageView::getOffsetPointer(const VkOffset3D &offset, VkImageAspectFlagBit
{
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment