rhi: avoid backends modifying the frontend depth and arraySize

Buffer and texture sizes (size, pixelSize) may get increased, if needed,
but those actual sizes calculated by the QRhi backends are not written
back to the QRhiBuffer m_size or QRhiTexture m_pixelSize.

In contrast, both m_depth and m_arraySize are clamped in QRhiTexture
by most backends (to ensure a lower bound of 1 and 0, respectively).
This is not great since it means the getters for depth() and arraySize()
may return values different from what the user has provided. To avoid
confusion, do not modify the m_* variables.

Change-Id: I2cc5b9abf41ea108549ffd7f2403306e6e8ebba2
Reviewed-by: Jonas Karlsson <jonas.karlsson@qt.io>
This commit is contained in:
Laszlo Agocs 2023-05-24 14:26:49 +02:00
parent afe0bf0914
commit 09597d05f7
6 changed files with 42 additions and 45 deletions

View File

@ -3235,12 +3235,10 @@ bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
qWarning("Texture cannot be both 1D and 3D");
return false;
}
m_depth = qMax(1, m_depth);
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
m_arraySize = qMax(0, m_arraySize);
if (m_arraySize > 0 && !isArray) {
qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
return false;
@ -3280,7 +3278,7 @@ bool QD3D11Texture::finishCreate()
srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
} else {
srvDesc.Texture1DArray.FirstArraySlice = 0;
srvDesc.Texture1DArray.ArraySize = UINT(m_arraySize);
srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
}
} else {
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
@ -3294,7 +3292,7 @@ bool QD3D11Texture::finishCreate()
srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
} else {
srvDesc.Texture2DMSArray.FirstArraySlice = 0;
srvDesc.Texture2DMSArray.ArraySize = UINT(m_arraySize);
srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
}
} else {
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
@ -3304,7 +3302,7 @@ bool QD3D11Texture::finishCreate()
srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
} else {
srvDesc.Texture2DArray.FirstArraySlice = 0;
srvDesc.Texture2DArray.ArraySize = UINT(m_arraySize);
srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
}
}
} else {
@ -3367,7 +3365,7 @@ bool QD3D11Texture::create()
D3D11_TEXTURE1D_DESC desc = {};
desc.Width = UINT(size.width());
desc.MipLevels = mipLevelCount;
desc.ArraySize = isArray ? UINT(m_arraySize) : 1;
desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
desc.Format = dxgiFormat;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = bindFlags;
@ -3387,7 +3385,7 @@ bool QD3D11Texture::create()
desc.Width = UINT(size.width());
desc.Height = UINT(size.height());
desc.MipLevels = mipLevelCount;
desc.ArraySize = isCube ? 6 : (isArray ? UINT(m_arraySize) : 1);
desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
desc.Format = dxgiFormat;
desc.SampleDesc = sampleDesc;
desc.Usage = D3D11_USAGE_DEFAULT;
@ -3406,7 +3404,7 @@ bool QD3D11Texture::create()
D3D11_TEXTURE3D_DESC desc = {};
desc.Width = UINT(size.width());
desc.Height = UINT(size.height());
desc.Depth = UINT(m_depth);
desc.Depth = UINT(qMax(1, m_depth));
desc.MipLevels = mipLevelCount;
desc.Format = dxgiFormat;
desc.Usage = D3D11_USAGE_DEFAULT;
@ -3479,7 +3477,7 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.MipSlice = UINT(level);
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = UINT(m_arraySize);
desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
} else if (is3D) {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
desc.Texture3D.MipSlice = UINT(level);

View File

@ -870,7 +870,7 @@ void QRhiD3D12::visitStorageImage(QD3D12Stage s,
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
uavDesc.Texture2DArray.MipSlice = UINT(d.level);
uavDesc.Texture2DArray.FirstArraySlice = 0;
uavDesc.Texture2DArray.ArraySize = UINT(texD->m_arraySize);
uavDesc.Texture2DArray.ArraySize = UINT(qMax(0, texD->m_arraySize));
} else if (is3D) {
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
uavDesc.Texture3D.MipSlice = UINT(d.level);
@ -3974,12 +3974,10 @@ bool QD3D12Texture::prepareCreate(QSize *adjustedSize)
qWarning("Texture cannot be both 1D and 3D");
return false;
}
m_depth = qMax(1, m_depth);
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
m_arraySize = qMax(0, m_arraySize);
if (m_arraySize > 0 && !isArray) {
qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
return false;
@ -4021,7 +4019,7 @@ bool QD3D12Texture::finishCreate()
srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
} else {
srvDesc.Texture1DArray.FirstArraySlice = 0;
srvDesc.Texture1DArray.ArraySize = UINT(m_arraySize);
srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
}
} else {
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
@ -4035,7 +4033,7 @@ bool QD3D12Texture::finishCreate()
srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
} else {
srvDesc.Texture2DMSArray.FirstArraySlice = 0;
srvDesc.Texture2DMSArray.ArraySize = UINT(m_arraySize);
srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
}
} else {
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
@ -4045,7 +4043,7 @@ bool QD3D12Texture::finishCreate()
srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
} else {
srvDesc.Texture2DArray.FirstArraySlice = 0;
srvDesc.Texture2DArray.ArraySize = UINT(m_arraySize);
srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
}
}
} else {
@ -4118,7 +4116,10 @@ bool QD3D12Texture::create()
: D3D12_RESOURCE_DIMENSION_TEXTURE2D);
resourceDesc.Width = UINT64(size.width());
resourceDesc.Height = UINT(size.height());
resourceDesc.DepthOrArraySize = isCube ? 6 : (isArray ? UINT(m_arraySize) : (is3D ? m_depth : 1));
resourceDesc.DepthOrArraySize = isCube ? 6
: (isArray ? UINT(qMax(0, m_arraySize))
: (is3D ? qMax(1, m_depth)
: 1));
resourceDesc.MipLevels = mipLevelCount;
resourceDesc.Format = dxgiFormat;
resourceDesc.SampleDesc = sampleDesc;

View File

@ -2239,6 +2239,8 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.subImage.rowLength = 0;
cmd.args.subImage.data = cbD->retainImage(img);
} else if (!rawData.isEmpty() && isCompressed) {
const int depth = qMax(1, texD->m_depth);
const int arraySize = qMax(0, texD->m_arraySize);
if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D || isArray)
&& !texD->zeroInitialized)
{
@ -2250,9 +2252,9 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
quint32 byteSize = 0;
compressedFormatInfo(texD->m_format, texD->m_pixelSize, nullptr, &byteSize, nullptr);
if (is3D)
byteSize *= texD->m_depth;
byteSize *= depth;
if (isArray)
byteSize *= texD->m_arraySize;
byteSize *= arraySize;
QByteArray zeroBuf(byteSize, 0);
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::CompressedImage;
@ -2262,9 +2264,8 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.compressedImage.level = level;
cmd.args.compressedImage.glintformat = texD->glintformat;
cmd.args.compressedImage.w = texD->m_pixelSize.width();
cmd.args.compressedImage.h =
is1D && isArray ? texD->m_arraySize : texD->m_pixelSize.height();
cmd.args.compressedImage.depth = is3D ? texD->m_depth : (isArray ? texD->m_arraySize : 0);
cmd.args.compressedImage.h = is1D && isArray ? arraySize : texD->m_pixelSize.height();
cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
cmd.args.compressedImage.size = byteSize;
cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
texD->zeroInitialized = true;
@ -2296,8 +2297,8 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.args.compressedImage.level = level;
cmd.args.compressedImage.glintformat = texD->glintformat;
cmd.args.compressedImage.w = size.width();
cmd.args.compressedImage.h = is1D && isArray ? texD->m_arraySize : size.height();
cmd.args.compressedImage.depth = is3D ? texD->m_depth : (isArray ? texD->m_arraySize : 0);
cmd.args.compressedImage.h = is1D && isArray ? arraySize : size.height();
cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
cmd.args.compressedImage.size = rawData.size();
cmd.args.compressedImage.data = cbD->retainData(rawData);
}
@ -5209,12 +5210,10 @@ bool QGles2Texture::prepareCreate(QSize *adjustedSize)
return false;
}
m_depth = qMax(1, m_depth);
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
m_arraySize = qMax(0, m_arraySize);
if (m_arraySize > 0 && !isArray) {
qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
return false;
@ -5289,13 +5288,13 @@ bool QGles2Texture::create()
const QSize mipSize = rhiD->q->sizeForMipLevel(level, size);
if (isArray)
rhiD->f->glTexImage2D(target, level, GLint(glintformat), mipSize.width(),
m_arraySize, 0, glformat, gltype, nullptr);
qMax(0, m_arraySize), 0, glformat, gltype, nullptr);
else
rhiD->glTexImage1D(target, level, GLint(glintformat), mipSize.width(), 0,
glformat, gltype, nullptr);
}
} else if (is3D || isArray) {
const int layerCount = is3D ? m_depth : m_arraySize;
const int layerCount = is3D ? qMax(1, m_depth) : qMax(0, m_arraySize);
if (hasMipMaps) {
for (int level = 0; level != mipLevelCount; ++level) {
const QSize mipSize = rhiD->q->sizeForMipLevel(level, size);
@ -5327,10 +5326,11 @@ bool QGles2Texture::create()
if (is1D && !isArray)
rhiD->glTexStorage1D(target, mipLevelCount, glsizedintformat, size.width());
else if (!is1D && (is3D || isArray))
rhiD->f->glTexStorage3D(target, mipLevelCount, glsizedintformat, size.width(), size.height(), is3D ? m_depth : m_arraySize);
rhiD->f->glTexStorage3D(target, mipLevelCount, glsizedintformat, size.width(), size.height(),
is3D ? qMax(1, m_depth) : qMax(0, m_arraySize));
else
rhiD->f->glTexStorage2D(target, mipLevelCount, glsizedintformat, size.width(),
is1D ? m_arraySize : size.height());
is1D ? qMax(0, m_arraySize) : size.height());
}
specified = true;
} else {

View File

@ -3709,12 +3709,10 @@ bool QMetalTexture::prepareCreate(QSize *adjustedSize)
qWarning("Texture cannot be both 1D and cube");
return false;
}
m_depth = qMax(1, m_depth);
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
m_arraySize = qMax(0, m_arraySize);
if (m_arraySize > 0 && !isArray) {
qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
return false;
@ -3764,12 +3762,12 @@ bool QMetalTexture::create()
desc.pixelFormat = d->format;
desc.width = NSUInteger(size.width());
desc.height = NSUInteger(size.height());
desc.depth = is3D ? m_depth : 1;
desc.depth = is3D ? qMax(1, m_depth) : 1;
desc.mipmapLevelCount = NSUInteger(mipLevelCount);
if (samples > 1)
desc.sampleCount = NSUInteger(samples);
if (isArray)
desc.arrayLength = NSUInteger(m_arraySize);
desc.arrayLength = NSUInteger(qMax(0, m_arraySize));
desc.resourceOptions = MTLResourceStorageModePrivate;
desc.storageMode = MTLStorageModePrivate;
desc.usage = MTLTextureUsageShaderRead;
@ -3828,7 +3826,8 @@ id<MTLTexture> QMetalTextureData::viewForLevel(int level)
const bool isCube = q->m_flags.testFlag(QRhiTexture::CubeMap);
const bool isArray = q->m_flags.testFlag(QRhiTexture::TextureArray);
id<MTLTexture> view = [tex newTextureViewWithPixelFormat: format textureType: type
levels: NSMakeRange(NSUInteger(level), 1) slices: NSMakeRange(0, isCube ? 6 : (isArray ? q->m_arraySize : 1))];
levels: NSMakeRange(NSUInteger(level), 1)
slices: NSMakeRange(0, isCube ? 6 : (isArray ? qMax(0, q->m_arraySize) : 1))];
perLevelViews[level] = view;
return view;

View File

@ -676,10 +676,11 @@ bool QNullTexture::create()
const bool is1D = m_flags.testFlags(OneDimensional);
QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
: (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
m_depth = qMax(1, m_depth);
const int mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
m_arraySize = qMax(0, m_arraySize);
const int layerCount = is3D ? m_depth : (isCube ? 6 : (isArray ? m_arraySize : 1));
const int layerCount = is3D ? qMax(1, m_depth)
: (isCube ? 6
: (isArray ? qMax(0, m_arraySize)
: 1));
if (m_format == RGBA8) {
image.resize(layerCount);

View File

@ -3598,10 +3598,10 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
if (!origStage)
origStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
for (int layer = 0; layer < (isCube ? 6 : (isArray ? utexD->m_arraySize : 1)); ++layer) {
for (int layer = 0; layer < (isCube ? 6 : (isArray ? qMax(0, utexD->m_arraySize) : 1)); ++layer) {
int w = utexD->m_pixelSize.width();
int h = utexD->m_pixelSize.height();
int depth = is3D ? utexD->m_depth : 1;
int depth = is3D ? qMax(1, utexD->m_depth) : 1;
for (int level = 1; level < int(utexD->mipLevelCount); ++level) {
if (level == 1) {
subresourceBarrier(cbD, utexD->image,
@ -6112,12 +6112,10 @@ bool QVkTexture::prepareCreate(QSize *adjustedSize)
qWarning("Texture cannot be both 1D and 3D");
return false;
}
m_depth = qMax(1, m_depth);
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
m_arraySize = qMax(0, m_arraySize);
if (m_arraySize > 0 && !isArray) {
qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
return false;
@ -6166,7 +6164,7 @@ bool QVkTexture::finishCreate()
viewInfo.subresourceRange.baseArrayLayer = uint32_t(m_arrayRangeStart);
viewInfo.subresourceRange.layerCount = uint32_t(m_arrayRangeLength);
} else {
viewInfo.subresourceRange.layerCount = isCube ? 6 : (isArray ? m_arraySize : 1);
viewInfo.subresourceRange.layerCount = isCube ? 6 : (isArray ? qMax(0, m_arraySize) : 1);
}
VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &imageView);
@ -6220,9 +6218,9 @@ bool QVkTexture::create()
imageInfo.format = vkformat;
imageInfo.extent.width = uint32_t(size.width());
imageInfo.extent.height = uint32_t(size.height());
imageInfo.extent.depth = is3D ? m_depth : 1;
imageInfo.extent.depth = is3D ? qMax(1, m_depth) : 1;
imageInfo.mipLevels = mipLevelCount;
imageInfo.arrayLayers = isCube ? 6 : (isArray ? m_arraySize : 1);
imageInfo.arrayLayers = isCube ? 6 : (isArray ? qMax(0, m_arraySize) : 1);
imageInfo.samples = samples;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
@ -6323,7 +6321,7 @@ VkImageView QVkTexture::imageViewForLevel(int level)
viewInfo.subresourceRange.baseMipLevel = uint32_t(level);
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = isCube ? 6 : (isArray ? m_arraySize : 1);
viewInfo.subresourceRange.layerCount = isCube ? 6 : (isArray ? qMax(0, m_arraySize) : 1);
VkImageView v = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);