mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 10:49:14 +00:00
Support BC5 formats on Vulkan
This patch supports BC5 formats on Vulkan backends and adds related Dawn end2end tests. For the textures with BC formats, they could have non-multiple-of-4 sizes on the non-zero mipmap levels in sampling, but we are still required to provide texture data in complete 4x4 blocks in texture copies because that is the size of which they are stored in GPU memory. In this patch, we refer the term "physical memory size" as the memory size of the texture subresource in GPU memory, and the term "virtual memory size" as the size used in texture sampling. As Dawn requires the Extent3D in texture copies must fit in the physical memory size, while Vulkan requires it must fit in the virtual memory size, this patch recalculates the imageExtent to ensure it always follow this Vulkan validation rules. For Dawn end2end tests, note that we use pure green and pure red for the textures because BC5 does not support SRGB formats. Furthermore, "CopyPartofTextureSubResourceIntoNonZeroMipmapLevel" is skipped in this patch because there is an issue on the T2T copies from a region within the virtual size of one texture to another one that exceeds the virtual size of another texture in Vulkan SPEC. BUG=dawn:42 TEST=dawn_end2end_tests Change-Id: I17518cd335fb13125cb753bbf879bc06eb20e426 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8260 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
committed by
Commit Bot service account
parent
c246494dbf
commit
72508d6d06
@@ -39,7 +39,7 @@ namespace dawn_native {
|
||||
bool IsCompleteSubresourceCopiedTo(const TextureBase* texture,
|
||||
const Extent3D copySize,
|
||||
const uint32_t mipLevel) {
|
||||
Extent3D extent = texture->GetMipLevelSize(mipLevel);
|
||||
Extent3D extent = texture->GetMipLevelPhysicalSize(mipLevel);
|
||||
|
||||
if (extent.depth == copySize.depth && extent.width == copySize.width &&
|
||||
extent.height == copySize.height) {
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace dawn_native {
|
||||
// overflows.
|
||||
uint64_t level = textureCopy.level;
|
||||
|
||||
Extent3D extent = texture->GetMipLevelSize(level);
|
||||
Extent3D extent = texture->GetMipLevelPhysicalSize(level);
|
||||
|
||||
if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) >
|
||||
static_cast<uint64_t>(extent.width) ||
|
||||
|
||||
@@ -543,11 +543,16 @@ namespace dawn_native {
|
||||
return mSampleCount > 1;
|
||||
}
|
||||
|
||||
Extent3D TextureBase::GetMipLevelSize(uint64_t level) const {
|
||||
Extent3D TextureBase::GetMipLevelVirtualSize(uint64_t level) const {
|
||||
Extent3D extent;
|
||||
extent.width = std::max(mSize.width >> level, 1u);
|
||||
extent.height = std::max(mSize.height >> level, 1u);
|
||||
extent.depth = std::max(mSize.depth >> level, 1u);
|
||||
return extent;
|
||||
}
|
||||
|
||||
Extent3D TextureBase::GetMipLevelPhysicalSize(uint64_t level) const {
|
||||
Extent3D extent = GetMipLevelVirtualSize(level);
|
||||
|
||||
// Compressed Textures will have paddings if their width or height is not a multiple of
|
||||
// 4 at non-zero mipmap levels.
|
||||
|
||||
@@ -99,7 +99,13 @@ namespace dawn_native {
|
||||
|
||||
bool IsMultisampledTexture() const;
|
||||
|
||||
Extent3D GetMipLevelSize(uint64_t level) const;
|
||||
// For a texture with non-block-compressed texture format, its physical size is always equal
|
||||
// to its virtual size. For a texture with block compressed texture format, the physical
|
||||
// size is the one with paddings if necessary, which is always a multiple of the block size
|
||||
// and used in texture copying. The virtual size is the one without paddings, which is not
|
||||
// required to be a multiple of the block size and used in texture sampling.
|
||||
Extent3D GetMipLevelPhysicalSize(uint64_t level) const;
|
||||
Extent3D GetMipLevelVirtualSize(uint64_t level) const;
|
||||
|
||||
// Dawn API
|
||||
TextureViewBase* CreateDefaultView();
|
||||
|
||||
@@ -41,6 +41,28 @@ namespace dawn_native { namespace vulkan {
|
||||
}
|
||||
}
|
||||
|
||||
// Vulkan SPEC requires the source/destination region specified by each element of
|
||||
// pRegions must be a region that is contained within srcImage/dstImage. Here the size of
|
||||
// the image refers to the virtual size, while Dawn validates texture copy extent with the
|
||||
// physical size, so we need to re-calculate the texture copy extent to ensure it should fit
|
||||
// in the virtual size of the subresource.
|
||||
Extent3D ComputeTextureCopyExtent(const TextureCopy& textureCopy,
|
||||
const Extent3D& copySize) {
|
||||
Extent3D validTextureCopyExtent = copySize;
|
||||
const TextureBase* texture = textureCopy.texture.Get();
|
||||
Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(textureCopy.level);
|
||||
if (textureCopy.origin.x + copySize.width > virtualSizeAtLevel.width) {
|
||||
ASSERT(texture->GetFormat().isCompressed);
|
||||
validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
|
||||
}
|
||||
if (textureCopy.origin.y + copySize.height > virtualSizeAtLevel.height) {
|
||||
ASSERT(texture->GetFormat().isCompressed);
|
||||
validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
|
||||
}
|
||||
|
||||
return validTextureCopyExtent;
|
||||
}
|
||||
|
||||
VkBufferImageCopy ComputeBufferImageCopyRegion(const BufferCopy& bufferCopy,
|
||||
const TextureCopy& textureCopy,
|
||||
const Extent3D& copySize) {
|
||||
@@ -50,7 +72,9 @@ namespace dawn_native { namespace vulkan {
|
||||
|
||||
region.bufferOffset = bufferCopy.offset;
|
||||
// In Vulkan the row length is in texels while it is in bytes for Dawn
|
||||
region.bufferRowLength = bufferCopy.rowPitch / texture->GetFormat().blockByteSize;
|
||||
const Format& format = texture->GetFormat();
|
||||
ASSERT(bufferCopy.rowPitch % format.blockByteSize == 0);
|
||||
region.bufferRowLength = bufferCopy.rowPitch / format.blockByteSize * format.blockWidth;
|
||||
region.bufferImageHeight = bufferCopy.imageHeight;
|
||||
|
||||
region.imageSubresource.aspectMask = texture->GetVkAspectMask();
|
||||
@@ -62,8 +86,9 @@ namespace dawn_native { namespace vulkan {
|
||||
region.imageOffset.y = textureCopy.origin.y;
|
||||
region.imageOffset.z = textureCopy.origin.z;
|
||||
|
||||
region.imageExtent.width = copySize.width;
|
||||
region.imageExtent.height = copySize.height;
|
||||
Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize);
|
||||
region.imageExtent.width = imageExtent.width;
|
||||
region.imageExtent.height = imageExtent.height;
|
||||
region.imageExtent.depth = copySize.depth;
|
||||
|
||||
return region;
|
||||
@@ -95,9 +120,14 @@ namespace dawn_native { namespace vulkan {
|
||||
region.dstOffset.y = dstCopy.origin.y;
|
||||
region.dstOffset.z = dstCopy.origin.z;
|
||||
|
||||
region.extent.width = copySize.width;
|
||||
region.extent.height = copySize.height;
|
||||
region.extent.depth = copySize.depth;
|
||||
Extent3D imageExtentDst = ComputeTextureCopyExtent(dstCopy, copySize);
|
||||
// TODO(jiawei.shao@intel.com): add workaround for the case that imageExtentSrc is not
|
||||
// equal to imageExtentDst. For example when copySize fits in the virtual size of the
|
||||
// source image but does not fit in the one of the destination image.
|
||||
Extent3D imageExtent = imageExtentDst;
|
||||
region.extent.width = imageExtent.width;
|
||||
region.extent.height = imageExtent.height;
|
||||
region.extent.depth = imageExtent.depth;
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
@@ -341,6 +341,9 @@ namespace dawn_native { namespace vulkan {
|
||||
// Always require imageCubeArray because it is a core Dawn feature
|
||||
usedKnobs.features.imageCubeArray = VK_TRUE;
|
||||
|
||||
// TODO(jiawei.shao@intel.com): support BC formats as extension
|
||||
usedKnobs.features.textureCompressionBC = VK_TRUE;
|
||||
|
||||
// Find a universal queue family
|
||||
{
|
||||
constexpr uint32_t kUniversalFlags =
|
||||
|
||||
@@ -577,6 +577,12 @@ namespace dawn_native { namespace vulkan {
|
||||
}
|
||||
if (!IsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
|
||||
layerCount)) {
|
||||
// TODO(jiawei.shao@intel.com): initialize textures in BC formats with Buffer-to-Texture
|
||||
// copies.
|
||||
if (GetFormat().isCompressed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If subresource has not been initialized, clear it to black as it could contain dirty
|
||||
// bits from recycled memory
|
||||
ClearTexture(commands, baseMipLevel, levelCount, baseArrayLayer, layerCount);
|
||||
|
||||
Reference in New Issue
Block a user