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"