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."); }