From 1546bfbdecf26566b9042235e70feb19c2652958 Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Thu, 18 Jul 2019 09:25:04 +0000 Subject: [PATCH] Precompute all the Formats at Device creation in the FormatTable This is needed for two reasons: - TextureBase and TextureViewBase stored Formats by value which isn't too much overhead at this time but will get bigger in the future. - The OpenGL backends needs its own GLFormat structure to store data about each format which will eventually contain complicated logic to detect support in the GL driver so it shouldn't be duplicated in Textures. The computations of the information about Format is moved from being done whenever they are needed to being precomputed at DeviceBase initialization. This makes each format have a constant "index" in that can be used in the backends to address their own structure, for example a GLFormat table. Also some DeviceBase pointers were made const for validation. BUG=dawn:128 Change-Id: I37d1e9c739b87cddcea09cb1759e175704d90f9e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9101 Reviewed-by: Austin Eng Reviewed-by: Jiawei Shao Commit-Queue: Corentin Wallez --- BUILD.gn | 2 + src/dawn_native/Device.cpp | 23 +++ src/dawn_native/Device.h | 13 ++ src/dawn_native/Format.cpp | 195 ++++++++++++++++++ src/dawn_native/Format.h | 73 +++++++ src/dawn_native/Forward.h | 3 + src/dawn_native/Pipeline.cpp | 2 +- src/dawn_native/Pipeline.h | 2 +- src/dawn_native/RenderPipeline.cpp | 23 ++- src/dawn_native/RenderPipeline.h | 2 +- src/dawn_native/Texture.cpp | 189 ++--------------- src/dawn_native/Texture.h | 37 +--- src/dawn_native/d3d12/TextureCopySplitter.cpp | 5 +- src/dawn_native/d3d12/TextureCopySplitter.h | 9 +- .../vulkan/NativeSwapChainImplVk.cpp | 2 +- src/tests/unittests/d3d12/CopySplitTests.cpp | 2 +- 16 files changed, 358 insertions(+), 224 deletions(-) create mode 100644 src/dawn_native/Format.cpp create mode 100644 src/dawn_native/Format.h diff --git a/BUILD.gn b/BUILD.gn index 3c76769b31..2c687bb167 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -133,6 +133,8 @@ source_set("libdawn_native_sources") { "src/dawn_native/Fence.h", "src/dawn_native/FenceSignalTracker.cpp", "src/dawn_native/FenceSignalTracker.h", + "src/dawn_native/Format.cpp", + "src/dawn_native/Format.h", "src/dawn_native/Forward.h", "src/dawn_native/Instance.cpp", "src/dawn_native/Instance.h", diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp index ae373bf467..8be70b0283 100644 --- a/src/dawn_native/Device.cpp +++ b/src/dawn_native/Device.cpp @@ -63,6 +63,8 @@ namespace dawn_native { mFenceSignalTracker = std::make_unique(this); mDynamicUploader = std::make_unique(this); SetDefaultToggles(); + + mFormatTable = BuildFormatTable(this); } DeviceBase::~DeviceBase() { @@ -100,6 +102,27 @@ namespace dawn_native { return mFenceSignalTracker.get(); } + ResultOrError DeviceBase::GetInternalFormat(dawn::TextureFormat format) const { + size_t index = ComputeFormatIndex(format); + if (index >= mFormatTable.size()) { + return DAWN_VALIDATION_ERROR("Unknown texture format"); + } + + const Format* internalFormat = &mFormatTable[index]; + if (!internalFormat->isSupported) { + return DAWN_VALIDATION_ERROR("Unsupported texture format"); + } + + return internalFormat; + } + + const Format& DeviceBase::GetValidInternalFormat(dawn::TextureFormat format) const { + size_t index = ComputeFormatIndex(format); + ASSERT(index < mFormatTable.size()); + ASSERT(mFormatTable[index].isSupported); + return mFormatTable[index]; + } + ResultOrError DeviceBase::GetOrCreateBindGroupLayout( const BindGroupLayoutDescriptor* descriptor) { BindGroupLayoutBase blueprint(this, descriptor, true); diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h index 197a87c4d1..d99f0f985c 100644 --- a/src/dawn_native/Device.h +++ b/src/dawn_native/Device.h @@ -17,6 +17,7 @@ #include "common/Serial.h" #include "dawn_native/Error.h" +#include "dawn_native/Format.h" #include "dawn_native/Forward.h" #include "dawn_native/ObjectBase.h" #include "dawn_native/Toggles.h" @@ -56,6 +57,16 @@ namespace dawn_native { FenceSignalTracker* GetFenceSignalTracker() const; + // Returns the Format corresponding to the dawn::TextureFormat or an error if the format + // isn't a valid dawn::TextureFormat or isn't supported by this device. + // The pointer returned has the same lifetime as the device. + ResultOrError GetInternalFormat(dawn::TextureFormat format) const; + + // Returns the Format corresponding to the dawn::TextureFormat and assumes the format is + // valid and supported. + // The reference returned has the same lifetime as the device. + const Format& GetValidInternalFormat(dawn::TextureFormat format) const; + virtual CommandBufferBase* CreateCommandBuffer( CommandEncoderBase* encoder, const CommandBufferDescriptor* descriptor) = 0; @@ -218,6 +229,8 @@ namespace dawn_native { void* mErrorUserdata = 0; uint32_t mRefCount = 1; + FormatTable mFormatTable; + TogglesSet mTogglesSet; }; diff --git a/src/dawn_native/Format.cpp b/src/dawn_native/Format.cpp new file mode 100644 index 0000000000..da2946aae4 --- /dev/null +++ b/src/dawn_native/Format.cpp @@ -0,0 +1,195 @@ +// Copyright 2019 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/Format.h" + +#include + +namespace dawn_native { + + // Format + + bool Format::IsColor() const { + return aspect == Aspect::Color; + } + + bool Format::HasDepth() const { + return aspect == Depth || aspect == DepthStencil; + } + + bool Format::HasStencil() const { + return aspect == Stencil || aspect == DepthStencil; + } + + bool Format::HasDepthOrStencil() const { + return aspect != Color; + } + + size_t Format::GetIndex() const { + return ComputeFormatIndex(format); + } + + // Implementation details of the format table of the DeviceBase + + // For the enum for formats are packed but this might change when we have a broader extension + // mechanism for webgpu.h + size_t ComputeFormatIndex(dawn::TextureFormat format) { + return static_cast(static_cast(format)); + } + + FormatTable BuildFormatTable(const DeviceBase*) { + FormatTable table; + std::bitset formatsSet; + + auto AddFormat = [&table, &formatsSet](Format format) { + size_t index = ComputeFormatIndex(format.format); + ASSERT(index < table.size()); + + // This checks that each format is set at most once, the first part of checking that all + // formats are set exactly once. + ASSERT(!formatsSet[index]); + + table[index] = format; + formatsSet.set(index); + }; + + auto AddColorFormat = [&AddFormat](dawn::TextureFormat format, bool renderable, + uint32_t byteSize) { + Format internalFormat; + internalFormat.format = format; + internalFormat.isRenderable = renderable; + internalFormat.isCompressed = false; + internalFormat.isSupported = true; + internalFormat.aspect = Format::Aspect::Color; + internalFormat.blockByteSize = byteSize; + internalFormat.blockWidth = 1; + internalFormat.blockHeight = 1; + AddFormat(internalFormat); + }; + + auto AddDepthStencilFormat = [&AddFormat](dawn::TextureFormat format, Format::Aspect aspect, + uint32_t byteSize) { + Format internalFormat; + internalFormat.format = format; + internalFormat.isRenderable = true; + internalFormat.isCompressed = false; + internalFormat.isSupported = true; + internalFormat.aspect = aspect; + internalFormat.blockByteSize = byteSize; + internalFormat.blockWidth = 1; + internalFormat.blockHeight = 1; + AddFormat(internalFormat); + }; + + auto AddCompressedFormat = [&AddFormat](dawn::TextureFormat format, uint32_t byteSize, + uint32_t width, uint32_t height) { + Format internalFormat; + internalFormat.format = format; + internalFormat.isRenderable = false; + internalFormat.isCompressed = true; + internalFormat.isSupported = true; + internalFormat.aspect = Format::Aspect::Color; + internalFormat.blockByteSize = byteSize; + internalFormat.blockWidth = width; + internalFormat.blockHeight = height; + AddFormat(internalFormat); + }; + + // clang-format off + + // 1 byte color formats + AddColorFormat(dawn::TextureFormat::R8Unorm, true, 1); + AddColorFormat(dawn::TextureFormat::R8Snorm, true, 1); + AddColorFormat(dawn::TextureFormat::R8Uint, true, 1); + AddColorFormat(dawn::TextureFormat::R8Sint, true, 1); + + // 2 bytes color formats + AddColorFormat(dawn::TextureFormat::R16Unorm, true, 2); + AddColorFormat(dawn::TextureFormat::R16Snorm, true, 2); + AddColorFormat(dawn::TextureFormat::R16Uint, true, 2); + AddColorFormat(dawn::TextureFormat::R16Sint, true, 2); + AddColorFormat(dawn::TextureFormat::R16Float, true, 2); + AddColorFormat(dawn::TextureFormat::RG8Unorm, true, 2); + AddColorFormat(dawn::TextureFormat::RG8Snorm, true, 2); + AddColorFormat(dawn::TextureFormat::RG8Uint, true, 2); + AddColorFormat(dawn::TextureFormat::RG8Sint, true, 2); + + // 4 bytes color formats + AddColorFormat(dawn::TextureFormat::R32Uint, true, 4); + AddColorFormat(dawn::TextureFormat::R32Sint, true, 4); + AddColorFormat(dawn::TextureFormat::R32Float, true, 4); + AddColorFormat(dawn::TextureFormat::RG16Unorm, true, 4); + AddColorFormat(dawn::TextureFormat::RG16Snorm, true, 4); + AddColorFormat(dawn::TextureFormat::RG16Uint, true, 4); + AddColorFormat(dawn::TextureFormat::RG16Sint, true, 4); + AddColorFormat(dawn::TextureFormat::RG16Float, true, 4); + AddColorFormat(dawn::TextureFormat::RGBA8Unorm, true, 4); + AddColorFormat(dawn::TextureFormat::RGBA8UnormSrgb, true, 4); + AddColorFormat(dawn::TextureFormat::RGBA8Snorm, true, 4); + AddColorFormat(dawn::TextureFormat::RGBA8Uint, true, 4); + AddColorFormat(dawn::TextureFormat::RGBA8Sint, true, 4); + AddColorFormat(dawn::TextureFormat::BGRA8Unorm, true, 4); + AddColorFormat(dawn::TextureFormat::BGRA8UnormSrgb, true, 4); + AddColorFormat(dawn::TextureFormat::RGB10A2Unorm, true, 4); + + AddColorFormat(dawn::TextureFormat::RG11B10Float, false, 4); + + // 8 bytes color formats + AddColorFormat(dawn::TextureFormat::RG32Uint, true, 8); + AddColorFormat(dawn::TextureFormat::RG32Sint, true, 8); + AddColorFormat(dawn::TextureFormat::RG32Float, true, 8); + AddColorFormat(dawn::TextureFormat::RGBA16Unorm, true, 8); + AddColorFormat(dawn::TextureFormat::RGBA16Snorm, true, 8); + AddColorFormat(dawn::TextureFormat::RGBA16Uint, true, 8); + AddColorFormat(dawn::TextureFormat::RGBA16Sint, true, 8); + AddColorFormat(dawn::TextureFormat::RGBA16Float, true, 8); + + // 16 bytes color formats + AddColorFormat(dawn::TextureFormat::RGBA32Uint, true, 16); + AddColorFormat(dawn::TextureFormat::RGBA32Sint, true, 16); + AddColorFormat(dawn::TextureFormat::RGBA32Float, true, 16); + + // Depth stencil formats + AddDepthStencilFormat(dawn::TextureFormat::Depth32Float, Format::Aspect::Depth, 4); + AddDepthStencilFormat(dawn::TextureFormat::Depth24Plus, Format::Aspect::Depth, 4); + // TODO(cwallez@chromium.org): It isn't clear if this format should be copyable + // because its size isn't well defined, is it 4, 5 or 8? + AddDepthStencilFormat(dawn::TextureFormat::Depth24PlusStencil8, Format::Aspect::DepthStencil, 4); + + // BC compressed formats + AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnorm, 8, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC4RSnorm, 8, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC4RUnorm, 8, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnorm, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnorm, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC5RGSnorm, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC5RGUnorm, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC6HRGBSfloat, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC6HRGBUfloat, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnorm, 16, 4, 4); + AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4); + + // clang-format on + + // This checks that each format is set at least once, the second part of checking that all + // formats are checked exactly once. + ASSERT(formatsSet.all()); + + return table; + } + +} // namespace dawn_native diff --git a/src/dawn_native/Format.h b/src/dawn_native/Format.h new file mode 100644 index 0000000000..334198cb98 --- /dev/null +++ b/src/dawn_native/Format.h @@ -0,0 +1,73 @@ +// Copyright 2019 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef DAWNNATIVE_FORMAT_H_ +#define DAWNNATIVE_FORMAT_H_ + +#include "dawn_native/dawn_platform.h" + +#include "dawn_native/Error.h" + +#include + +namespace dawn_native { + + class DeviceBase; + + // The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the + // exact number of known format. + static constexpr size_t kKnownFormatCount = 58; + + // A dawn::TextureFormat along with all the information about it necessary for validation. + struct Format { + enum Aspect { + Color, + Depth, + Stencil, + DepthStencil, + }; + + dawn::TextureFormat format; + bool isRenderable; + bool isCompressed; + // A format can be known but not supported because it is part of a disabled extension. + bool isSupported; + Aspect aspect; + + uint32_t blockByteSize; + uint32_t blockWidth; + uint32_t blockHeight; + + bool IsColor() const; + bool HasDepth() const; + bool HasStencil() const; + bool HasDepthOrStencil() const; + + // The index of the format in the list of all known formats: a unique number for each format + // in [0, kKnownFormatCount) + size_t GetIndex() const; + }; + + // Implementation details of the format table in the device. + + using FormatTable = std::array; + + // Returns the index of a format in the FormatTable. + size_t ComputeFormatIndex(dawn::TextureFormat format); + // Builds the format table with the extensions enabled on the device. + FormatTable BuildFormatTable(const DeviceBase* device); + +} // namespace dawn_native + +#endif // DAWNNATIVE_FORMAT_H_ diff --git a/src/dawn_native/Forward.h b/src/dawn_native/Forward.h index db539048ab..b4c3e837be 100644 --- a/src/dawn_native/Forward.h +++ b/src/dawn_native/Forward.h @@ -48,6 +48,9 @@ namespace dawn_native { template class PerStage; + + struct Format; + } // namespace dawn_native #endif // DAWNNATIVE_FORWARD_H_ diff --git a/src/dawn_native/Pipeline.cpp b/src/dawn_native/Pipeline.cpp index 639df34fd5..6551e178c4 100644 --- a/src/dawn_native/Pipeline.cpp +++ b/src/dawn_native/Pipeline.cpp @@ -20,7 +20,7 @@ namespace dawn_native { - MaybeError ValidatePipelineStageDescriptor(DeviceBase* device, + MaybeError ValidatePipelineStageDescriptor(const DeviceBase* device, const PipelineStageDescriptor* descriptor, const PipelineLayoutBase* layout, ShaderStage stage) { diff --git a/src/dawn_native/Pipeline.h b/src/dawn_native/Pipeline.h index c72a724932..209fadecb1 100644 --- a/src/dawn_native/Pipeline.h +++ b/src/dawn_native/Pipeline.h @@ -28,7 +28,7 @@ namespace dawn_native { - MaybeError ValidatePipelineStageDescriptor(DeviceBase* device, + MaybeError ValidatePipelineStageDescriptor(const DeviceBase* device, const PipelineStageDescriptor* descriptor, const PipelineLayoutBase* layout, ShaderStage stage); diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp index b8b2d2bf07..421abf2a45 100644 --- a/src/dawn_native/RenderPipeline.cpp +++ b/src/dawn_native/RenderPipeline.cpp @@ -18,7 +18,6 @@ #include "common/HashUtils.h" #include "dawn_native/Commands.h" #include "dawn_native/Device.h" -#include "dawn_native/Texture.h" #include "dawn_native/ValidationUtils_autogen.h" namespace dawn_native { @@ -112,7 +111,8 @@ namespace dawn_native { return {}; } - MaybeError ValidateColorStateDescriptor(const ColorStateDescriptor* descriptor) { + MaybeError ValidateColorStateDescriptor(const DeviceBase* device, + const ColorStateDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } @@ -124,9 +124,9 @@ namespace dawn_native { DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.dstFactor)); DAWN_TRY(ValidateColorWriteMask(descriptor->writeMask)); - Format format; - DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); - if (!format.IsColor() || !format.isRenderable) { + const Format* format; + DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format)); + if (!format->IsColor() || !format->isRenderable) { return DAWN_VALIDATION_ERROR("Color format must be color renderable"); } @@ -134,6 +134,7 @@ namespace dawn_native { } MaybeError ValidateDepthStencilStateDescriptor( + const DeviceBase* device, const DepthStencilStateDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); @@ -148,9 +149,9 @@ namespace dawn_native { DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.depthFailOp)); DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp)); - Format format; - DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); - if (!format.HasDepthOrStencil() || !format.isRenderable) { + const Format* format; + DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format)); + if (!format->HasDepthOrStencil() || !format->isRenderable) { return DAWN_VALIDATION_ERROR( "Depth stencil format must be depth-stencil renderable"); } @@ -258,7 +259,7 @@ namespace dawn_native { return VertexFormatNumComponents(format) * VertexFormatComponentSize(format); } - MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device, + MaybeError ValidateRenderPipelineDescriptor(const DeviceBase* device, const RenderPipelineDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); @@ -301,11 +302,11 @@ namespace dawn_native { } for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) { - DAWN_TRY(ValidateColorStateDescriptor(descriptor->colorStates[i])); + DAWN_TRY(ValidateColorStateDescriptor(device, descriptor->colorStates[i])); } if (descriptor->depthStencilState) { - DAWN_TRY(ValidateDepthStencilStateDescriptor(descriptor->depthStencilState)); + DAWN_TRY(ValidateDepthStencilStateDescriptor(device, descriptor->depthStencilState)); } if (descriptor->sampleMask != 0xFFFFFFFF) { diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h index aedf699417..dfc46f75ab 100644 --- a/src/dawn_native/RenderPipeline.h +++ b/src/dawn_native/RenderPipeline.h @@ -28,7 +28,7 @@ namespace dawn_native { class DeviceBase; - MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device, + MaybeError ValidateRenderPipelineDescriptor(const DeviceBase* device, const RenderPipelineDescriptor* descriptor); size_t IndexFormatSize(dawn::IndexFormat format); uint32_t VertexFormatNumComponents(dawn::VertexFormat format); diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp index d3c034ea77..f2f35a6af2 100644 --- a/src/dawn_native/Texture.cpp +++ b/src/dawn_native/Texture.cpp @@ -86,134 +86,8 @@ namespace dawn_native { } } - // Returns a format with a blockByteSize of 0 for an invalid input format - Format ConvertFormatInternal(dawn::TextureFormat format) { - auto MakeColorFormat = [](dawn::TextureFormat format, bool renderable, - uint32_t byteSize) -> Format { - Format result; - result.format = format; - result.isRenderable = renderable; - result.isCompressed = false; - result.aspect = Format::Aspect::Color; - result.blockByteSize = byteSize; - result.blockWidth = 1; - result.blockHeight = 1; - return result; - }; - - auto MakeDepthStencilFormat = [](dawn::TextureFormat format, Format::Aspect aspect, - uint32_t byteSize) -> Format { - Format result; - result.format = format; - result.isRenderable = true; - result.isCompressed = false; - result.aspect = aspect; - result.blockByteSize = byteSize; - result.blockWidth = 1; - result.blockHeight = 1; - return result; - }; - - auto MakeCompressedFormat = [](dawn::TextureFormat format, uint32_t byteSize, - uint32_t width, uint32_t height) -> Format { - Format result; - result.format = format; - result.isRenderable = false; - result.isCompressed = true; - result.aspect = Format::Aspect::Color; - result.blockByteSize = byteSize; - result.blockWidth = width; - result.blockHeight = height; - return result; - }; - - switch (format) { - case dawn::TextureFormat::R8Unorm: - case dawn::TextureFormat::R8Snorm: - case dawn::TextureFormat::R8Uint: - case dawn::TextureFormat::R8Sint: - return MakeColorFormat(format, true, 1); - - case dawn::TextureFormat::R16Unorm: - case dawn::TextureFormat::R16Snorm: - case dawn::TextureFormat::R16Uint: - case dawn::TextureFormat::R16Sint: - case dawn::TextureFormat::R16Float: - case dawn::TextureFormat::RG8Unorm: - case dawn::TextureFormat::RG8Snorm: - case dawn::TextureFormat::RG8Uint: - case dawn::TextureFormat::RG8Sint: - return MakeColorFormat(format, true, 2); - - case dawn::TextureFormat::R32Uint: - case dawn::TextureFormat::R32Sint: - case dawn::TextureFormat::R32Float: - case dawn::TextureFormat::RG16Unorm: - case dawn::TextureFormat::RG16Snorm: - case dawn::TextureFormat::RG16Uint: - case dawn::TextureFormat::RG16Sint: - case dawn::TextureFormat::RG16Float: - case dawn::TextureFormat::RGBA8Unorm: - case dawn::TextureFormat::RGBA8UnormSrgb: - case dawn::TextureFormat::RGBA8Snorm: - case dawn::TextureFormat::RGBA8Uint: - case dawn::TextureFormat::RGBA8Sint: - case dawn::TextureFormat::BGRA8Unorm: - case dawn::TextureFormat::BGRA8UnormSrgb: - case dawn::TextureFormat::RGB10A2Unorm: - return MakeColorFormat(format, true, 4); - case dawn::TextureFormat::RG11B10Float: - return MakeColorFormat(format, false, 4); - - case dawn::TextureFormat::RG32Uint: - case dawn::TextureFormat::RG32Sint: - case dawn::TextureFormat::RG32Float: - case dawn::TextureFormat::RGBA16Unorm: - case dawn::TextureFormat::RGBA16Snorm: - case dawn::TextureFormat::RGBA16Uint: - case dawn::TextureFormat::RGBA16Sint: - case dawn::TextureFormat::RGBA16Float: - return MakeColorFormat(format, true, 8); - - case dawn::TextureFormat::RGBA32Uint: - case dawn::TextureFormat::RGBA32Sint: - case dawn::TextureFormat::RGBA32Float: - return MakeColorFormat(format, true, 16); - - case dawn::TextureFormat::Depth32Float: - case dawn::TextureFormat::Depth24Plus: - return MakeDepthStencilFormat(format, Format::Aspect::Depth, 4); - case dawn::TextureFormat::Depth24PlusStencil8: - // TODO(cwallez@chromium.org): It isn't clear if this format should be copyable - // because its size isn't well defined, is it 4, 5 or 8? - return MakeDepthStencilFormat(format, Format::Aspect::DepthStencil, 4); - - case dawn::TextureFormat::BC1RGBAUnorm: - case dawn::TextureFormat::BC1RGBAUnormSrgb: - case dawn::TextureFormat::BC4RSnorm: - case dawn::TextureFormat::BC4RUnorm: - return MakeCompressedFormat(format, 8, 4, 4); - case dawn::TextureFormat::BC2RGBAUnorm: - case dawn::TextureFormat::BC2RGBAUnormSrgb: - case dawn::TextureFormat::BC3RGBAUnorm: - case dawn::TextureFormat::BC3RGBAUnormSrgb: - case dawn::TextureFormat::BC5RGSnorm: - case dawn::TextureFormat::BC5RGUnorm: - case dawn::TextureFormat::BC6HRGBSfloat: - case dawn::TextureFormat::BC6HRGBUfloat: - case dawn::TextureFormat::BC7RGBAUnorm: - case dawn::TextureFormat::BC7RGBAUnormSrgb: - return MakeCompressedFormat(format, 16, 4, 4); - - default: - Format result = {}; - result.blockByteSize = 0; - return result; - } - } - // TODO(jiawei.shao@intel.com): support more sample count. - MaybeError ValidateSampleCount(const TextureDescriptor* descriptor, const Format& format) { + MaybeError ValidateSampleCount(const TextureDescriptor* descriptor, const Format* format) { if (!IsValidSampleCount(descriptor->sampleCount)) { return DAWN_VALIDATION_ERROR("The sample count of the texture is not supported."); } @@ -230,7 +104,7 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Multisampled 2D array texture is not supported."); } - if (format.isCompressed) { + if (format->isCompressed) { return DAWN_VALIDATION_ERROR( "The sample counts of the textures in BC formats must be 1."); } @@ -289,7 +163,7 @@ namespace dawn_native { return descriptor; } - MaybeError ValidateTextureSize(const TextureDescriptor* descriptor, const Format& format) { + MaybeError ValidateTextureSize(const TextureDescriptor* descriptor, const Format* format) { ASSERT(descriptor->size.width != 0 && descriptor->size.height != 0); if (Log2(std::max(descriptor->size.width, descriptor->size.height)) + 1 < @@ -297,8 +171,8 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Texture has too many mip levels"); } - if (format.isCompressed && (descriptor->size.width % format.blockWidth != 0 || - descriptor->size.height % format.blockHeight != 0)) { + if (format->isCompressed && (descriptor->size.width % format->blockWidth != 0 || + descriptor->size.height % format->blockHeight != 0)) { return DAWN_VALIDATION_ERROR( "The size of the texture is incompatible with the texture format"); } @@ -306,18 +180,18 @@ namespace dawn_native { return {}; } - MaybeError ValidateTextureUsage(const TextureDescriptor* descriptor, const Format& format) { + MaybeError ValidateTextureUsage(const TextureDescriptor* descriptor, const Format* format) { DAWN_TRY(ValidateTextureUsageBit(descriptor->usage)); constexpr dawn::TextureUsageBit kValidCompressedUsages = dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::CopySrc | dawn::TextureUsageBit::CopyDst; - if (format.isCompressed && (descriptor->usage & (~kValidCompressedUsages))) { + if (format->isCompressed && (descriptor->usage & (~kValidCompressedUsages))) { return DAWN_VALIDATION_ERROR( "Compressed texture format is incompatible with the texture usage"); } - if (!format.isRenderable && + if (!format->isRenderable && (descriptor->usage & dawn::TextureUsageBit::OutputAttachment)) { return DAWN_VALIDATION_ERROR( "Non-renderable format used with OutputAttachment usage"); @@ -332,13 +206,14 @@ namespace dawn_native { } // anonymous namespace - MaybeError ValidateTextureDescriptor(DeviceBase*, const TextureDescriptor* descriptor) { + MaybeError ValidateTextureDescriptor(const DeviceBase* device, + const TextureDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } - Format format; - DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); + const Format* format; + DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format)); DAWN_TRY(ValidateTextureUsage(descriptor, format)); DAWN_TRY(ValidateTextureDimension(descriptor->dimension)); @@ -412,36 +287,6 @@ namespace dawn_native { } } - ResultOrError ConvertFormat(dawn::TextureFormat format) { - Format result = ConvertFormatInternal(format); - if (result.blockByteSize == 0) { - return DAWN_VALIDATION_ERROR("Invalid texture format"); - } - return result; - } - - Format ConvertValidFormat(dawn::TextureFormat format) { - Format result = ConvertFormatInternal(format); - ASSERT(result.blockByteSize != 0); - return result; - } - - bool Format::IsColor() const { - return aspect == Aspect::Color; - } - - bool Format::HasDepth() const { - return aspect == Depth || aspect == DepthStencil; - } - - bool Format::HasStencil() const { - return aspect == Stencil || aspect == DepthStencil; - } - - bool Format::HasDepthOrStencil() const { - return aspect != Color; - } - // TextureBase TextureBase::TextureBase(DeviceBase* device, @@ -449,7 +294,7 @@ namespace dawn_native { TextureState state) : ObjectBase(device), mDimension(descriptor->dimension), - mFormat(ConvertValidFormat(descriptor->format)), + mFormat(device->GetValidInternalFormat(descriptor->format)), mSize(descriptor->size), mArrayLayerCount(descriptor->arrayLayerCount), mMipLevelCount(descriptor->mipLevelCount), @@ -461,8 +306,10 @@ namespace dawn_native { mIsSubresourceContentInitializedAtIndex = std::vector(subresourceCount, false); } + static Format kUnusedFormat; + TextureBase::TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag) - : ObjectBase(device, tag) { + : ObjectBase(device, tag), mFormat(kUnusedFormat) { } // static @@ -627,7 +474,7 @@ namespace dawn_native { TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor) : ObjectBase(texture->GetDevice()), mTexture(texture), - mFormat(ConvertValidFormat(descriptor->format)), + mFormat(GetDevice()->GetValidInternalFormat(descriptor->format)), mBaseMipLevel(descriptor->baseMipLevel), mMipLevelCount(descriptor->mipLevelCount), mBaseArrayLayer(descriptor->baseArrayLayer), @@ -635,7 +482,7 @@ namespace dawn_native { } TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag) - : ObjectBase(device, tag) { + : ObjectBase(device, tag), mFormat(kUnusedFormat) { } // static diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h index 02cefe3ee5..fa32758530 100644 --- a/src/dawn_native/Texture.h +++ b/src/dawn_native/Texture.h @@ -24,7 +24,8 @@ #include namespace dawn_native { - MaybeError ValidateTextureDescriptor(DeviceBase* device, const TextureDescriptor* descriptor); + MaybeError ValidateTextureDescriptor(const DeviceBase* device, + const TextureDescriptor* descriptor); MaybeError ValidateTextureViewDescriptor(const DeviceBase* device, const TextureBase* texture, const TextureViewDescriptor* descriptor); @@ -39,36 +40,6 @@ namespace dawn_native { dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Storage | dawn::TextureUsageBit::OutputAttachment; - struct Format { - enum Aspect { - Color, - Depth, - Stencil, - DepthStencil, - }; - - dawn::TextureFormat format; - bool isRenderable; - bool isCompressed; - Aspect aspect; - - uint32_t blockByteSize; - uint32_t blockWidth; - uint32_t blockHeight; - - bool IsColor() const; - bool HasDepth() const; - bool HasStencil() const; - bool HasDepthOrStencil() const; - }; - - // Returns the Format corresponding to the dawn::TextureFormat or an error if the format - // isn't valid. - ResultOrError ConvertFormat(dawn::TextureFormat format); - - // Returns the Format corresponding to the dawn::TextureFormat and assumes the format is valid. - Format ConvertValidFormat(dawn::TextureFormat format); - class TextureBase : public ObjectBase { public: enum class TextureState { OwnedInternal, OwnedExternal, Destroyed }; @@ -122,7 +93,7 @@ namespace dawn_native { MaybeError ValidateDestroy() const; dawn::TextureDimension mDimension; // TODO(cwallez@chromium.org): This should be deduplicated in the Device - Format mFormat; + const Format& mFormat; Extent3D mSize; uint32_t mArrayLayerCount; uint32_t mMipLevelCount; @@ -155,7 +126,7 @@ namespace dawn_native { Ref mTexture; // TODO(cwallez@chromium.org): This should be deduplicated in the Device - Format mFormat; + const Format& mFormat; uint32_t mBaseMipLevel; uint32_t mMipLevelCount; uint32_t mBaseArrayLayer; diff --git a/src/dawn_native/d3d12/TextureCopySplitter.cpp b/src/dawn_native/d3d12/TextureCopySplitter.cpp index aa76517912..c206fe2351 100644 --- a/src/dawn_native/d3d12/TextureCopySplitter.cpp +++ b/src/dawn_native/d3d12/TextureCopySplitter.cpp @@ -15,12 +15,13 @@ #include "dawn_native/d3d12/TextureCopySplitter.h" #include "common/Assert.h" +#include "dawn_native/Format.h" #include "dawn_native/d3d12/d3d12_platform.h" namespace dawn_native { namespace d3d12 { namespace { - Origin3D ComputeTexelOffsets(Format format, + Origin3D ComputeTexelOffsets(const Format& format, uint32_t offset, uint32_t rowPitch, uint32_t slicePitch) { @@ -36,7 +37,7 @@ namespace dawn_native { namespace d3d12 { TextureCopySplit ComputeTextureCopySplit(Origin3D origin, Extent3D copySize, - Format format, + const Format& format, uint64_t offset, uint32_t rowPitch, uint32_t imageHeight) { diff --git a/src/dawn_native/d3d12/TextureCopySplitter.h b/src/dawn_native/d3d12/TextureCopySplitter.h index 540702f9ca..0e06ebd5a9 100644 --- a/src/dawn_native/d3d12/TextureCopySplitter.h +++ b/src/dawn_native/d3d12/TextureCopySplitter.h @@ -15,11 +15,16 @@ #ifndef DAWNNATIVE_D3D12_TEXTURECOPYSPLITTER_H_ #define DAWNNATIVE_D3D12_TEXTURECOPYSPLITTER_H_ -#include "dawn_native/Texture.h" #include "dawn_native/dawn_platform.h" #include +namespace dawn_native { + + struct Format; + +} // namespace dawn_native + namespace dawn_native { namespace d3d12 { struct TextureCopySplit { @@ -40,7 +45,7 @@ namespace dawn_native { namespace d3d12 { TextureCopySplit ComputeTextureCopySplit(Origin3D origin, Extent3D copySize, - Format format, + const Format& format, uint64_t offset, uint32_t rowPitch, uint32_t imageHeight); diff --git a/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp b/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp index 95b53e5485..0b037dbd88 100644 --- a/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp +++ b/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp @@ -93,7 +93,7 @@ namespace dawn_native { namespace vulkan { createInfo.imageExtent.height = height; createInfo.imageArrayLayers = 1; createInfo.imageUsage = VulkanImageUsage(static_cast(usage), - ConvertValidFormat(mConfig.format)); + mDevice->GetValidInternalFormat(mConfig.format)); createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; createInfo.queueFamilyIndexCount = 0; createInfo.pQueueFamilyIndices = nullptr; diff --git a/src/tests/unittests/d3d12/CopySplitTests.cpp b/src/tests/unittests/d3d12/CopySplitTests.cpp index 527ee07f64..da703a0e21 100644 --- a/src/tests/unittests/d3d12/CopySplitTests.cpp +++ b/src/tests/unittests/d3d12/CopySplitTests.cpp @@ -17,7 +17,7 @@ #include "common/Assert.h" #include "common/Constants.h" #include "common/Math.h" -#include "dawn_native/Texture.h" +#include "dawn_native/Format.h" #include "dawn_native/d3d12/TextureCopySplitter.h" #include "dawn_native/d3d12/d3d12_platform.h"