From 8a5325ca9aaa908bec5ef89b33ea7923189b61cb Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Mon, 15 Jun 2020 09:57:51 +0000 Subject: [PATCH] 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 Commit-Queue: Corentin Wallez --- src/dawn_native/Texture.cpp | 41 ++++++++++---- src/dawn_native/Texture.h | 4 +- src/dawn_native/d3d12/CommandBufferD3D12.cpp | 19 ++----- src/dawn_native/d3d12/TextureD3D12.cpp | 17 ++---- src/dawn_native/d3d12/TextureD3D12.h | 2 - src/dawn_native/metal/TextureMTL.mm | 51 ++++++++--------- src/dawn_native/opengl/TextureGL.cpp | 10 ++-- src/dawn_native/vulkan/TextureVk.cpp | 58 ++++++++++---------- 8 files changed, 100 insertions(+), 102 deletions(-) diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp index d58fb322b1..f029981fb0 100644 --- a/src/dawn_native/Texture.cpp +++ b/src/dawn_native/Texture.cpp @@ -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(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; } diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h index 3beafb641e..2900794134 100644 --- a/src/dawn_native/Texture.h +++ b/src/dawn_native/Texture.h @@ -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; diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 239415ebe9..c2a3282330 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -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 diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index d44014b123..b2021f8cb6 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -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(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(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::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); diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h index fa15412420..7def9becfc 100644 --- a/src/dawn_native/d3d12/TextureD3D12.h +++ b/src/dawn_native/d3d12/TextureD3D12.h @@ -95,8 +95,6 @@ namespace dawn_native { namespace d3d12 { const SubresourceRange& range, TextureBase::ClearValue clearValue); - UINT16 GetDepthOrArraySize(); - void TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext, std::vector* barrier, D3D12_RESOURCE_STATES newState, diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm index 88184ee277..454a14b273 100644 --- a/src/dawn_native/metal/TextureMTL.mm +++ b/src/dawn_native/metal/TextureMTL.mm @@ -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; } diff --git a/src/dawn_native/opengl/TextureGL.cpp b/src/dawn_native/opengl/TextureGL.cpp index 1236d47cc4..029ecca737 100644 --- a/src/dawn_native/opengl/TextureGL.cpp +++ b/src/dawn_native/opengl/TextureGL.cpp @@ -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::max()) { return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer."); } diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp index 3894d5aab9..7b35f14471 100644 --- a/src/dawn_native/vulkan/TextureVk.cpp +++ b/src/dawn_native/vulkan/TextureVk.cpp @@ -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::max()) { return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer."); }