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 <enga@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2019-07-18 09:25:04 +00:00 committed by Commit Bot service account
parent d6cc1fe099
commit 1546bfbdec
16 changed files with 358 additions and 224 deletions

View File

@ -133,6 +133,8 @@ source_set("libdawn_native_sources") {
"src/dawn_native/Fence.h", "src/dawn_native/Fence.h",
"src/dawn_native/FenceSignalTracker.cpp", "src/dawn_native/FenceSignalTracker.cpp",
"src/dawn_native/FenceSignalTracker.h", "src/dawn_native/FenceSignalTracker.h",
"src/dawn_native/Format.cpp",
"src/dawn_native/Format.h",
"src/dawn_native/Forward.h", "src/dawn_native/Forward.h",
"src/dawn_native/Instance.cpp", "src/dawn_native/Instance.cpp",
"src/dawn_native/Instance.h", "src/dawn_native/Instance.h",

View File

@ -63,6 +63,8 @@ namespace dawn_native {
mFenceSignalTracker = std::make_unique<FenceSignalTracker>(this); mFenceSignalTracker = std::make_unique<FenceSignalTracker>(this);
mDynamicUploader = std::make_unique<DynamicUploader>(this); mDynamicUploader = std::make_unique<DynamicUploader>(this);
SetDefaultToggles(); SetDefaultToggles();
mFormatTable = BuildFormatTable(this);
} }
DeviceBase::~DeviceBase() { DeviceBase::~DeviceBase() {
@ -100,6 +102,27 @@ namespace dawn_native {
return mFenceSignalTracker.get(); return mFenceSignalTracker.get();
} }
ResultOrError<const Format*> 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<BindGroupLayoutBase*> DeviceBase::GetOrCreateBindGroupLayout( ResultOrError<BindGroupLayoutBase*> DeviceBase::GetOrCreateBindGroupLayout(
const BindGroupLayoutDescriptor* descriptor) { const BindGroupLayoutDescriptor* descriptor) {
BindGroupLayoutBase blueprint(this, descriptor, true); BindGroupLayoutBase blueprint(this, descriptor, true);

View File

@ -17,6 +17,7 @@
#include "common/Serial.h" #include "common/Serial.h"
#include "dawn_native/Error.h" #include "dawn_native/Error.h"
#include "dawn_native/Format.h"
#include "dawn_native/Forward.h" #include "dawn_native/Forward.h"
#include "dawn_native/ObjectBase.h" #include "dawn_native/ObjectBase.h"
#include "dawn_native/Toggles.h" #include "dawn_native/Toggles.h"
@ -56,6 +57,16 @@ namespace dawn_native {
FenceSignalTracker* GetFenceSignalTracker() const; 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<const Format*> 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( virtual CommandBufferBase* CreateCommandBuffer(
CommandEncoderBase* encoder, CommandEncoderBase* encoder,
const CommandBufferDescriptor* descriptor) = 0; const CommandBufferDescriptor* descriptor) = 0;
@ -218,6 +229,8 @@ namespace dawn_native {
void* mErrorUserdata = 0; void* mErrorUserdata = 0;
uint32_t mRefCount = 1; uint32_t mRefCount = 1;
FormatTable mFormatTable;
TogglesSet mTogglesSet; TogglesSet mTogglesSet;
}; };

195
src/dawn_native/Format.cpp Normal file
View File

@ -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 <bitset>
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<size_t>(static_cast<uint32_t>(format));
}
FormatTable BuildFormatTable(const DeviceBase*) {
FormatTable table;
std::bitset<kKnownFormatCount> 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

73
src/dawn_native/Format.h Normal file
View File

@ -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 <array>
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<Format, kKnownFormatCount>;
// 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_

View File

@ -48,6 +48,9 @@ namespace dawn_native {
template <typename T> template <typename T>
class PerStage; class PerStage;
struct Format;
} // namespace dawn_native } // namespace dawn_native
#endif // DAWNNATIVE_FORWARD_H_ #endif // DAWNNATIVE_FORWARD_H_

View File

@ -20,7 +20,7 @@
namespace dawn_native { namespace dawn_native {
MaybeError ValidatePipelineStageDescriptor(DeviceBase* device, MaybeError ValidatePipelineStageDescriptor(const DeviceBase* device,
const PipelineStageDescriptor* descriptor, const PipelineStageDescriptor* descriptor,
const PipelineLayoutBase* layout, const PipelineLayoutBase* layout,
ShaderStage stage) { ShaderStage stage) {

View File

@ -28,7 +28,7 @@
namespace dawn_native { namespace dawn_native {
MaybeError ValidatePipelineStageDescriptor(DeviceBase* device, MaybeError ValidatePipelineStageDescriptor(const DeviceBase* device,
const PipelineStageDescriptor* descriptor, const PipelineStageDescriptor* descriptor,
const PipelineLayoutBase* layout, const PipelineLayoutBase* layout,
ShaderStage stage); ShaderStage stage);

View File

@ -18,7 +18,6 @@
#include "common/HashUtils.h" #include "common/HashUtils.h"
#include "dawn_native/Commands.h" #include "dawn_native/Commands.h"
#include "dawn_native/Device.h" #include "dawn_native/Device.h"
#include "dawn_native/Texture.h"
#include "dawn_native/ValidationUtils_autogen.h" #include "dawn_native/ValidationUtils_autogen.h"
namespace dawn_native { namespace dawn_native {
@ -112,7 +111,8 @@ namespace dawn_native {
return {}; return {};
} }
MaybeError ValidateColorStateDescriptor(const ColorStateDescriptor* descriptor) { MaybeError ValidateColorStateDescriptor(const DeviceBase* device,
const ColorStateDescriptor* descriptor) {
if (descriptor->nextInChain != nullptr) { if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
} }
@ -124,9 +124,9 @@ namespace dawn_native {
DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.dstFactor)); DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.dstFactor));
DAWN_TRY(ValidateColorWriteMask(descriptor->writeMask)); DAWN_TRY(ValidateColorWriteMask(descriptor->writeMask));
Format format; const Format* format;
DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
if (!format.IsColor() || !format.isRenderable) { if (!format->IsColor() || !format->isRenderable) {
return DAWN_VALIDATION_ERROR("Color format must be color renderable"); return DAWN_VALIDATION_ERROR("Color format must be color renderable");
} }
@ -134,6 +134,7 @@ namespace dawn_native {
} }
MaybeError ValidateDepthStencilStateDescriptor( MaybeError ValidateDepthStencilStateDescriptor(
const DeviceBase* device,
const DepthStencilStateDescriptor* descriptor) { const DepthStencilStateDescriptor* descriptor) {
if (descriptor->nextInChain != nullptr) { if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be 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.depthFailOp));
DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp)); DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp));
Format format; const Format* format;
DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
if (!format.HasDepthOrStencil() || !format.isRenderable) { if (!format->HasDepthOrStencil() || !format->isRenderable) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"Depth stencil format must be depth-stencil renderable"); "Depth stencil format must be depth-stencil renderable");
} }
@ -258,7 +259,7 @@ namespace dawn_native {
return VertexFormatNumComponents(format) * VertexFormatComponentSize(format); return VertexFormatNumComponents(format) * VertexFormatComponentSize(format);
} }
MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device, MaybeError ValidateRenderPipelineDescriptor(const DeviceBase* device,
const RenderPipelineDescriptor* descriptor) { const RenderPipelineDescriptor* descriptor) {
if (descriptor->nextInChain != nullptr) { if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be 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) { 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) { if (descriptor->depthStencilState) {
DAWN_TRY(ValidateDepthStencilStateDescriptor(descriptor->depthStencilState)); DAWN_TRY(ValidateDepthStencilStateDescriptor(device, descriptor->depthStencilState));
} }
if (descriptor->sampleMask != 0xFFFFFFFF) { if (descriptor->sampleMask != 0xFFFFFFFF) {

View File

@ -28,7 +28,7 @@ namespace dawn_native {
class DeviceBase; class DeviceBase;
MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device, MaybeError ValidateRenderPipelineDescriptor(const DeviceBase* device,
const RenderPipelineDescriptor* descriptor); const RenderPipelineDescriptor* descriptor);
size_t IndexFormatSize(dawn::IndexFormat format); size_t IndexFormatSize(dawn::IndexFormat format);
uint32_t VertexFormatNumComponents(dawn::VertexFormat format); uint32_t VertexFormatNumComponents(dawn::VertexFormat format);

View File

@ -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. // 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)) { if (!IsValidSampleCount(descriptor->sampleCount)) {
return DAWN_VALIDATION_ERROR("The sample count of the texture is not supported."); 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."); return DAWN_VALIDATION_ERROR("Multisampled 2D array texture is not supported.");
} }
if (format.isCompressed) { if (format->isCompressed) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"The sample counts of the textures in BC formats must be 1."); "The sample counts of the textures in BC formats must be 1.");
} }
@ -289,7 +163,7 @@ namespace dawn_native {
return descriptor; 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); ASSERT(descriptor->size.width != 0 && descriptor->size.height != 0);
if (Log2(std::max(descriptor->size.width, descriptor->size.height)) + 1 < 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"); return DAWN_VALIDATION_ERROR("Texture has too many mip levels");
} }
if (format.isCompressed && (descriptor->size.width % format.blockWidth != 0 || if (format->isCompressed && (descriptor->size.width % format->blockWidth != 0 ||
descriptor->size.height % format.blockHeight != 0)) { descriptor->size.height % format->blockHeight != 0)) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"The size of the texture is incompatible with the texture format"); "The size of the texture is incompatible with the texture format");
} }
@ -306,18 +180,18 @@ namespace dawn_native {
return {}; return {};
} }
MaybeError ValidateTextureUsage(const TextureDescriptor* descriptor, const Format& format) { MaybeError ValidateTextureUsage(const TextureDescriptor* descriptor, const Format* format) {
DAWN_TRY(ValidateTextureUsageBit(descriptor->usage)); DAWN_TRY(ValidateTextureUsageBit(descriptor->usage));
constexpr dawn::TextureUsageBit kValidCompressedUsages = constexpr dawn::TextureUsageBit kValidCompressedUsages =
dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::CopySrc | dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::CopySrc |
dawn::TextureUsageBit::CopyDst; dawn::TextureUsageBit::CopyDst;
if (format.isCompressed && (descriptor->usage & (~kValidCompressedUsages))) { if (format->isCompressed && (descriptor->usage & (~kValidCompressedUsages))) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"Compressed texture format is incompatible with the texture usage"); "Compressed texture format is incompatible with the texture usage");
} }
if (!format.isRenderable && if (!format->isRenderable &&
(descriptor->usage & dawn::TextureUsageBit::OutputAttachment)) { (descriptor->usage & dawn::TextureUsageBit::OutputAttachment)) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"Non-renderable format used with OutputAttachment usage"); "Non-renderable format used with OutputAttachment usage");
@ -332,13 +206,14 @@ namespace dawn_native {
} // anonymous namespace } // anonymous namespace
MaybeError ValidateTextureDescriptor(DeviceBase*, const TextureDescriptor* descriptor) { MaybeError ValidateTextureDescriptor(const DeviceBase* device,
const TextureDescriptor* descriptor) {
if (descriptor->nextInChain != nullptr) { if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
} }
Format format; const Format* format;
DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
DAWN_TRY(ValidateTextureUsage(descriptor, format)); DAWN_TRY(ValidateTextureUsage(descriptor, format));
DAWN_TRY(ValidateTextureDimension(descriptor->dimension)); DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
@ -412,36 +287,6 @@ namespace dawn_native {
} }
} }
ResultOrError<Format> 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::TextureBase(DeviceBase* device, TextureBase::TextureBase(DeviceBase* device,
@ -449,7 +294,7 @@ namespace dawn_native {
TextureState state) TextureState state)
: ObjectBase(device), : ObjectBase(device),
mDimension(descriptor->dimension), mDimension(descriptor->dimension),
mFormat(ConvertValidFormat(descriptor->format)), mFormat(device->GetValidInternalFormat(descriptor->format)),
mSize(descriptor->size), mSize(descriptor->size),
mArrayLayerCount(descriptor->arrayLayerCount), mArrayLayerCount(descriptor->arrayLayerCount),
mMipLevelCount(descriptor->mipLevelCount), mMipLevelCount(descriptor->mipLevelCount),
@ -461,8 +306,10 @@ namespace dawn_native {
mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false); mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);
} }
static Format kUnusedFormat;
TextureBase::TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag) TextureBase::TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ObjectBase(device, tag) { : ObjectBase(device, tag), mFormat(kUnusedFormat) {
} }
// static // static
@ -627,7 +474,7 @@ namespace dawn_native {
TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor) TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor)
: ObjectBase(texture->GetDevice()), : ObjectBase(texture->GetDevice()),
mTexture(texture), mTexture(texture),
mFormat(ConvertValidFormat(descriptor->format)), mFormat(GetDevice()->GetValidInternalFormat(descriptor->format)),
mBaseMipLevel(descriptor->baseMipLevel), mBaseMipLevel(descriptor->baseMipLevel),
mMipLevelCount(descriptor->mipLevelCount), mMipLevelCount(descriptor->mipLevelCount),
mBaseArrayLayer(descriptor->baseArrayLayer), mBaseArrayLayer(descriptor->baseArrayLayer),
@ -635,7 +482,7 @@ namespace dawn_native {
} }
TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag) TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ObjectBase(device, tag) { : ObjectBase(device, tag), mFormat(kUnusedFormat) {
} }
// static // static

View File

@ -24,7 +24,8 @@
#include <vector> #include <vector>
namespace dawn_native { namespace dawn_native {
MaybeError ValidateTextureDescriptor(DeviceBase* device, const TextureDescriptor* descriptor); MaybeError ValidateTextureDescriptor(const DeviceBase* device,
const TextureDescriptor* descriptor);
MaybeError ValidateTextureViewDescriptor(const DeviceBase* device, MaybeError ValidateTextureViewDescriptor(const DeviceBase* device,
const TextureBase* texture, const TextureBase* texture,
const TextureViewDescriptor* descriptor); const TextureViewDescriptor* descriptor);
@ -39,36 +40,6 @@ namespace dawn_native {
dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Storage | dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Storage |
dawn::TextureUsageBit::OutputAttachment; 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<Format> 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 { class TextureBase : public ObjectBase {
public: public:
enum class TextureState { OwnedInternal, OwnedExternal, Destroyed }; enum class TextureState { OwnedInternal, OwnedExternal, Destroyed };
@ -122,7 +93,7 @@ namespace dawn_native {
MaybeError ValidateDestroy() const; MaybeError ValidateDestroy() const;
dawn::TextureDimension mDimension; dawn::TextureDimension mDimension;
// TODO(cwallez@chromium.org): This should be deduplicated in the Device // TODO(cwallez@chromium.org): This should be deduplicated in the Device
Format mFormat; const Format& mFormat;
Extent3D mSize; Extent3D mSize;
uint32_t mArrayLayerCount; uint32_t mArrayLayerCount;
uint32_t mMipLevelCount; uint32_t mMipLevelCount;
@ -155,7 +126,7 @@ namespace dawn_native {
Ref<TextureBase> mTexture; Ref<TextureBase> mTexture;
// TODO(cwallez@chromium.org): This should be deduplicated in the Device // TODO(cwallez@chromium.org): This should be deduplicated in the Device
Format mFormat; const Format& mFormat;
uint32_t mBaseMipLevel; uint32_t mBaseMipLevel;
uint32_t mMipLevelCount; uint32_t mMipLevelCount;
uint32_t mBaseArrayLayer; uint32_t mBaseArrayLayer;

View File

@ -15,12 +15,13 @@
#include "dawn_native/d3d12/TextureCopySplitter.h" #include "dawn_native/d3d12/TextureCopySplitter.h"
#include "common/Assert.h" #include "common/Assert.h"
#include "dawn_native/Format.h"
#include "dawn_native/d3d12/d3d12_platform.h" #include "dawn_native/d3d12/d3d12_platform.h"
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
namespace { namespace {
Origin3D ComputeTexelOffsets(Format format, Origin3D ComputeTexelOffsets(const Format& format,
uint32_t offset, uint32_t offset,
uint32_t rowPitch, uint32_t rowPitch,
uint32_t slicePitch) { uint32_t slicePitch) {
@ -36,7 +37,7 @@ namespace dawn_native { namespace d3d12 {
TextureCopySplit ComputeTextureCopySplit(Origin3D origin, TextureCopySplit ComputeTextureCopySplit(Origin3D origin,
Extent3D copySize, Extent3D copySize,
Format format, const Format& format,
uint64_t offset, uint64_t offset,
uint32_t rowPitch, uint32_t rowPitch,
uint32_t imageHeight) { uint32_t imageHeight) {

View File

@ -15,11 +15,16 @@
#ifndef DAWNNATIVE_D3D12_TEXTURECOPYSPLITTER_H_ #ifndef DAWNNATIVE_D3D12_TEXTURECOPYSPLITTER_H_
#define DAWNNATIVE_D3D12_TEXTURECOPYSPLITTER_H_ #define DAWNNATIVE_D3D12_TEXTURECOPYSPLITTER_H_
#include "dawn_native/Texture.h"
#include "dawn_native/dawn_platform.h" #include "dawn_native/dawn_platform.h"
#include <array> #include <array>
namespace dawn_native {
struct Format;
} // namespace dawn_native
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
struct TextureCopySplit { struct TextureCopySplit {
@ -40,7 +45,7 @@ namespace dawn_native { namespace d3d12 {
TextureCopySplit ComputeTextureCopySplit(Origin3D origin, TextureCopySplit ComputeTextureCopySplit(Origin3D origin,
Extent3D copySize, Extent3D copySize,
Format format, const Format& format,
uint64_t offset, uint64_t offset,
uint32_t rowPitch, uint32_t rowPitch,
uint32_t imageHeight); uint32_t imageHeight);

View File

@ -93,7 +93,7 @@ namespace dawn_native { namespace vulkan {
createInfo.imageExtent.height = height; createInfo.imageExtent.height = height;
createInfo.imageArrayLayers = 1; createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VulkanImageUsage(static_cast<dawn::TextureUsageBit>(usage), createInfo.imageUsage = VulkanImageUsage(static_cast<dawn::TextureUsageBit>(usage),
ConvertValidFormat(mConfig.format)); mDevice->GetValidInternalFormat(mConfig.format));
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0; createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr; createInfo.pQueueFamilyIndices = nullptr;

View File

@ -17,7 +17,7 @@
#include "common/Assert.h" #include "common/Assert.h"
#include "common/Constants.h" #include "common/Constants.h"
#include "common/Math.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/TextureCopySplitter.h"
#include "dawn_native/d3d12/d3d12_platform.h" #include "dawn_native/d3d12/d3d12_platform.h"