Texture: Change to mArrayLayerCount to mSize.depth

This makes the tracking in TextureBase match the shape of
wgpu::TextureDescriptor.

GetSize() becomes a bit more surprising because the depth can sometimes
be the array size, so new getters GetWidth(), GetHeight() and GetDepth()
are added.

Some simplifications to the backend texture creation code are included
that will make it less error prone to add support for 1D / 3D textures.

Bug: dawn:22

Change-Id: I33b6ca99af9d58fc88f5f626cfd5e2e62a8b45cb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23103
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2020-06-15 09:57:51 +00:00 committed by Commit Bot service account
parent 4234d78201
commit 8a5325ca9a
8 changed files with 100 additions and 102 deletions

View File

@ -372,17 +372,10 @@ namespace dawn_native {
mDimension(descriptor->dimension),
mFormat(device->GetValidInternalFormat(descriptor->format)),
mSize(descriptor->size),
mArrayLayerCount(descriptor->size.depth),
mMipLevelCount(descriptor->mipLevelCount),
mSampleCount(descriptor->sampleCount),
mUsage(descriptor->usage),
mState(state) {
// TODO(cwallez@chromium.org): Store the array layers in size.depth instead if extracting it
// in mArrayLayerCount.
ASSERT(mDimension == wgpu::TextureDimension::e2D);
mArrayLayerCount = mSize.depth;
mSize.depth = 1;
uint32_t subresourceCount = GetSubresourceCount();
mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);
@ -418,9 +411,26 @@ namespace dawn_native {
ASSERT(!IsError());
return mSize;
}
uint32_t TextureBase::GetWidth() const {
ASSERT(!IsError());
return mSize.width;
}
uint32_t TextureBase::GetHeight() const {
ASSERT(!IsError());
ASSERT(mDimension == wgpu::TextureDimension::e2D ||
mDimension == wgpu::TextureDimension::e3D);
return mSize.height;
}
uint32_t TextureBase::GetDepth() const {
ASSERT(!IsError());
ASSERT(mDimension == wgpu::TextureDimension::e3D);
return mSize.depth;
}
uint32_t TextureBase::GetArrayLayers() const {
ASSERT(!IsError());
return mArrayLayerCount;
// TODO(cwallez@chromium.org): Update for 1D / 3D textures when they are supported.
ASSERT(mDimension == wgpu::TextureDimension::e2D);
return mSize.depth;
}
uint32_t TextureBase::GetNumMipLevels() const {
ASSERT(!IsError());
@ -428,7 +438,7 @@ namespace dawn_native {
}
SubresourceRange TextureBase::GetAllSubresources() const {
ASSERT(!IsError());
return {0, mMipLevelCount, 0, mArrayLayerCount};
return {0, mMipLevelCount, 0, GetArrayLayers()};
}
uint32_t TextureBase::GetSampleCount() const {
ASSERT(!IsError());
@ -436,7 +446,7 @@ namespace dawn_native {
}
uint32_t TextureBase::GetSubresourceCount() const {
ASSERT(!IsError());
return mMipLevelCount * mArrayLayerCount;
return mMipLevelCount * mSize.depth;
}
wgpu::TextureUsage TextureBase::GetUsage() const {
ASSERT(!IsError());
@ -501,9 +511,16 @@ namespace dawn_native {
}
Extent3D TextureBase::GetMipLevelVirtualSize(uint32_t level) const {
Extent3D extent;
extent.width = std::max(mSize.width >> level, 1u);
Extent3D extent = {std::max(mSize.width >> level, 1u), 1u, 1u};
if (mDimension == wgpu::TextureDimension::e1D) {
return extent;
}
extent.height = std::max(mSize.height >> level, 1u);
if (mDimension == wgpu::TextureDimension::e2D) {
return extent;
}
extent.depth = std::max(mSize.depth >> level, 1u);
return extent;
}

View File

@ -66,6 +66,9 @@ namespace dawn_native {
wgpu::TextureDimension GetDimension() const;
const Format& GetFormat() const;
const Extent3D& GetSize() const;
uint32_t GetWidth() const;
uint32_t GetHeight() const;
uint32_t GetDepth() const;
uint32_t GetArrayLayers() const;
uint32_t GetNumMipLevels() const;
SubresourceRange GetAllSubresources() const;
@ -105,7 +108,6 @@ namespace dawn_native {
// TODO(cwallez@chromium.org): This should be deduplicated in the Device
const Format& mFormat;
Extent3D mSize;
uint32_t mArrayLayerCount;
uint32_t mMipLevelCount;
uint32_t mSampleCount;
wgpu::TextureUsage mUsage = wgpu::TextureUsage::None;

View File

@ -63,17 +63,6 @@ namespace dawn_native { namespace d3d12 {
const Extent3D& srcSize = src->GetSize();
const Extent3D& dstSize = dst->GetSize();
auto GetCopyDepth = [](const Texture* texture) {
switch (texture->GetDimension()) {
case wgpu::TextureDimension::e1D:
return 1u;
case wgpu::TextureDimension::e2D:
return texture->GetArrayLayers();
case wgpu::TextureDimension::e3D:
return texture->GetSize().depth;
}
};
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-copyresource
// In order to use D3D12's copy resource, the textures must be the same dimensions, and
// the copy must be of the entire resource.
@ -85,10 +74,10 @@ namespace dawn_native { namespace d3d12 {
// cannot use CopyResource.
copySize.width == dstSize.width && //
copySize.width == srcSize.width && //
copySize.height == dstSize.height && //
copySize.height == srcSize.height && //
copySize.depth == GetCopyDepth(src) && //
copySize.depth == GetCopyDepth(dst);
copySize.height == dstSize.height && //
copySize.height == srcSize.height && //
copySize.depth == dstSize.depth && //
copySize.depth == srcSize.depth;
}
} // anonymous namespace

View File

@ -452,6 +452,7 @@ namespace dawn_native { namespace d3d12 {
const Extent3D& size = GetSize();
resourceDescriptor.Width = size.width;
resourceDescriptor.Height = size.height;
resourceDescriptor.DepthOrArraySize = size.depth;
// This will need to be much more nuanced when WebGPU has
// texture view compatibility rules.
@ -462,7 +463,6 @@ namespace dawn_native { namespace d3d12 {
? D3D12TypelessTextureFormat(GetFormat().format)
: D3D12TextureFormat(GetFormat().format);
resourceDescriptor.DepthOrArraySize = GetDepthOrArraySize();
resourceDescriptor.MipLevels = static_cast<UINT16>(GetNumMipLevels());
resourceDescriptor.Format = dxgiFormat;
resourceDescriptor.SampleDesc.Count = GetSampleCount();
@ -547,15 +547,6 @@ namespace dawn_native { namespace d3d12 {
return mResourceAllocation.GetD3D12Resource().Get();
}
UINT16 Texture::GetDepthOrArraySize() {
switch (GetDimension()) {
case wgpu::TextureDimension::e2D:
return static_cast<UINT16>(GetArrayLayers());
default:
UNREACHABLE();
}
}
void Texture::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage,
uint32_t mipLevel,
@ -878,9 +869,9 @@ namespace dawn_native { namespace d3d12 {
// TODO(natlee@microsoft.com): test compressed textures are cleared
// create temp buffer with clear color to copy to the texture image
uint32_t bytesPerRow =
Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
Align((GetWidth() / GetFormat().blockWidth) * GetFormat().blockByteSize,
kTextureBytesPerRowAlignment);
uint64_t bufferSize64 = bytesPerRow * (GetSize().height / GetFormat().blockHeight);
uint64_t bufferSize64 = bytesPerRow * (GetHeight() / GetFormat().blockHeight);
if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
}
@ -900,7 +891,7 @@ namespace dawn_native { namespace d3d12 {
// compute d3d12 texture copy locations for texture and buffer
Extent3D copySize = GetMipLevelVirtualSize(level);
uint32_t rowsPerImage = GetSize().height;
uint32_t rowsPerImage = GetHeight();
TextureCopySplit copySplit =
ComputeTextureCopySplit({0, 0, 0}, copySize, GetFormat(),
uploadHandle.startOffset, bytesPerRow, rowsPerImage);

View File

@ -95,8 +95,6 @@ namespace dawn_native { namespace d3d12 {
const SubresourceRange& range,
TextureBase::ClearValue clearValue);
UINT16 GetDepthOrArraySize();
void TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
std::vector<D3D12_RESOURCE_BARRIER>* barrier,
D3D12_RESOURCE_STATES newState,

View File

@ -54,22 +54,6 @@ namespace dawn_native { namespace metal {
return result;
}
MTLTextureType MetalTextureType(wgpu::TextureDimension dimension,
unsigned int arrayLayers,
unsigned int sampleCount) {
switch (dimension) {
case wgpu::TextureDimension::e2D:
if (sampleCount > 1) {
ASSERT(arrayLayers == 1);
return MTLTextureType2DMultisample;
} else {
return (arrayLayers > 1) ? MTLTextureType2DArray : MTLTextureType2D;
}
default:
UNREACHABLE();
}
}
MTLTextureType MetalTextureViewType(wgpu::TextureViewDimension dimension,
unsigned int sampleCount) {
switch (dimension) {
@ -301,21 +285,38 @@ namespace dawn_native { namespace metal {
MTLTextureDescriptor* CreateMetalTextureDescriptor(const TextureDescriptor* descriptor) {
MTLTextureDescriptor* mtlDesc = [MTLTextureDescriptor new];
mtlDesc.textureType = MetalTextureType(descriptor->dimension, descriptor->size.depth,
descriptor->sampleCount);
mtlDesc.usage = MetalTextureUsage(descriptor->usage);
mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format);
mtlDesc.width = descriptor->size.width;
mtlDesc.height = descriptor->size.height;
ASSERT(descriptor->dimension == wgpu::TextureDimension::e2D);
mtlDesc.depth = 1;
mtlDesc.sampleCount = descriptor->sampleCount;
mtlDesc.usage = MetalTextureUsage(descriptor->usage);
mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format);
mtlDesc.mipmapLevelCount = descriptor->mipLevelCount;
mtlDesc.arrayLength = descriptor->size.depth;
mtlDesc.storageMode = MTLStorageModePrivate;
mtlDesc.sampleCount = descriptor->sampleCount;
// Choose the correct MTLTextureType and paper over differences in how the array layer count
// is specified.
mtlDesc.depth = descriptor->size.depth;
mtlDesc.arrayLength = 1;
switch (descriptor->dimension) {
case wgpu::TextureDimension::e2D:
if (mtlDesc.depth > 1) {
ASSERT(mtlDesc.sampleCount == 1);
mtlDesc.textureType = MTLTextureType2DArray;
mtlDesc.arrayLength = mtlDesc.depth;
mtlDesc.depth = 1;
} else {
if (mtlDesc.sampleCount > 1) {
mtlDesc.textureType = MTLTextureType2DMultisample;
} else {
mtlDesc.textureType = MTLTextureType2D;
}
}
break;
default:
UNREACHABLE();
}
return mtlDesc;
}

View File

@ -108,8 +108,8 @@ namespace dawn_native { namespace opengl {
: Texture(device, descriptor, GenTexture(device->gl), TextureState::OwnedInternal) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
uint32_t width = GetSize().width;
uint32_t height = GetSize().height;
uint32_t width = GetWidth();
uint32_t height = GetHeight();
uint32_t levels = GetNumMipLevels();
uint32_t arrayLayers = GetArrayLayers();
uint32_t sampleCount = GetSampleCount();
@ -292,15 +292,15 @@ namespace dawn_native { namespace opengl {
// create temp buffer with clear color to copy to the texture image
ASSERT(kTextureBytesPerRowAlignment % GetFormat().blockByteSize == 0);
uint32_t bytesPerRow =
Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
Align((GetWidth() / GetFormat().blockWidth) * GetFormat().blockByteSize,
kTextureBytesPerRowAlignment);
// Make sure that we are not rounding
ASSERT(bytesPerRow % GetFormat().blockByteSize == 0);
ASSERT(GetSize().height % GetFormat().blockHeight == 0);
ASSERT(GetHeight() % GetFormat().blockHeight == 0);
dawn_native::BufferDescriptor descriptor;
descriptor.size = bytesPerRow * (GetSize().height / GetFormat().blockHeight);
descriptor.size = bytesPerRow * (GetHeight() / GetFormat().blockHeight);
if (descriptor.size > std::numeric_limits<uint32_t>::max()) {
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
}

View File

@ -32,18 +32,6 @@
namespace dawn_native { namespace vulkan {
namespace {
// Converts an Dawn texture dimension to a Vulkan image type.
// Note that in Vulkan dimensionality is only 1D, 2D, 3D. Arrays and cube maps are expressed
// via the array size and a "cubemap compatible" flag.
VkImageType VulkanImageType(wgpu::TextureDimension dimension) {
switch (dimension) {
case wgpu::TextureDimension::e2D:
return VK_IMAGE_TYPE_2D;
default:
UNREACHABLE();
}
}
// Converts an Dawn texture dimension to a Vulkan image view type.
// Contrary to image types, image view types include arrayness and cubemapness
VkImageViewType VulkanImageViewType(wgpu::TextureViewDimension dimension) {
@ -221,10 +209,6 @@ namespace dawn_native { namespace vulkan {
}
}
VkExtent3D VulkanExtent3D(const Extent3D& extent) {
return {extent.width, extent.height, extent.depth};
}
VkImageMemoryBarrier BuildMemoryBarrier(const Format& format,
const VkImage& image,
wgpu::TextureUsage lastUsage,
@ -252,6 +236,27 @@ namespace dawn_native { namespace vulkan {
return barrier;
}
void FillVulkanCreateInfoSizesAndType(const Texture& texture, VkImageCreateInfo* info) {
const Extent3D& size = texture.GetSize();
info->mipLevels = texture.GetNumMipLevels();
info->samples = VulkanSampleCount(texture.GetSampleCount());
// Fill in the image type, and paper over differences in how the array layer count is
// specified between WebGPU and Vulkan.
switch (texture.GetDimension()) {
case wgpu::TextureDimension::e2D:
info->imageType = VK_IMAGE_TYPE_2D;
info->extent = {size.width, size.height, 1};
info->arrayLayers = size.depth;
break;
default:
UNREACHABLE();
break;
}
}
} // namespace
// Converts Dawn texture format to Vulkan formats.
@ -495,15 +500,12 @@ namespace dawn_native { namespace vulkan {
// combination of sample, usage etc. because validation should have been done in the Dawn
// frontend already based on the minimum supported formats in the Vulkan spec
VkImageCreateInfo createInfo = {};
FillVulkanCreateInfoSizesAndType(*this, &createInfo);
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.imageType = VulkanImageType(GetDimension());
createInfo.format = VulkanImageFormat(device, GetFormat().format);
createInfo.extent = VulkanExtent3D(GetSize());
createInfo.mipLevels = GetNumMipLevels();
createInfo.arrayLayers = GetArrayLayers();
createInfo.samples = VulkanSampleCount(GetSampleCount());
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
createInfo.usage = VulkanImageUsage(GetUsage(), GetFormat());
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
@ -513,7 +515,7 @@ namespace dawn_native { namespace vulkan {
ASSERT(IsSampleCountSupported(device, createInfo));
if (GetArrayLayers() >= 6 && GetSize().width == GetSize().height) {
if (GetArrayLayers() >= 6 && GetWidth() == GetHeight()) {
createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
}
@ -556,15 +558,13 @@ namespace dawn_native { namespace vulkan {
}
mExternalState = ExternalState::PendingAcquire;
VkImageCreateInfo baseCreateInfo = {};
FillVulkanCreateInfoSizesAndType(*this, &baseCreateInfo);
baseCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
baseCreateInfo.pNext = nullptr;
baseCreateInfo.imageType = VulkanImageType(GetDimension());
baseCreateInfo.format = format;
baseCreateInfo.extent = VulkanExtent3D(GetSize());
baseCreateInfo.mipLevels = GetNumMipLevels();
baseCreateInfo.arrayLayers = GetArrayLayers();
baseCreateInfo.samples = VulkanSampleCount(GetSampleCount());
baseCreateInfo.usage = usage;
baseCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
baseCreateInfo.queueFamilyIndexCount = 0;
@ -909,9 +909,9 @@ namespace dawn_native { namespace vulkan {
// TODO(natlee@microsoft.com): test compressed textures are cleared
// create temp buffer with clear color to copy to the texture image
uint32_t bytesPerRow =
Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
Align((GetWidth() / GetFormat().blockWidth) * GetFormat().blockByteSize,
kTextureBytesPerRowAlignment);
uint64_t bufferSize64 = bytesPerRow * (GetSize().height / GetFormat().blockHeight);
uint64_t bufferSize64 = bytesPerRow * (GetHeight() / GetFormat().blockHeight);
if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
}