Support BC formats as the first extension in Dawn

This patch refactors the current implementation of BC formats to treat
it as the first extension in Dawn and adds all the related tests.

Note that in Dawn all the extensions are disabled unless we enable them
when we create the device, which means the BC formats can only be used
when we enable the related extension on the creation of the device, and
the creation of the device will fail if the adapter does not support the
extension

BUG=dawn:42
TEST=dawn_end2end_tests
TEST=dawn_unittests

Change-Id: I04d818b0218ebb3b1b7a70a4fea71779f308f85f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9520
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Jiawei Shao 2019-08-02 00:06:38 +00:00 committed by Commit Bot service account
parent 56f3a7b90d
commit 574b951188
28 changed files with 566 additions and 43 deletions

View File

@ -140,6 +140,8 @@ source_set("libdawn_native_sources") {
"src/dawn_native/Error.h", "src/dawn_native/Error.h",
"src/dawn_native/ErrorData.cpp", "src/dawn_native/ErrorData.cpp",
"src/dawn_native/ErrorData.h", "src/dawn_native/ErrorData.h",
"src/dawn_native/Extensions.cpp",
"src/dawn_native/Extensions.h",
"src/dawn_native/Fence.cpp", "src/dawn_native/Fence.cpp",
"src/dawn_native/Fence.h", "src/dawn_native/Fence.h",
"src/dawn_native/FenceSignalTracker.cpp", "src/dawn_native/FenceSignalTracker.cpp",
@ -605,6 +607,7 @@ test("dawn_unittests") {
"src/tests/unittests/CommandAllocatorTests.cpp", "src/tests/unittests/CommandAllocatorTests.cpp",
"src/tests/unittests/EnumClassBitmasksTests.cpp", "src/tests/unittests/EnumClassBitmasksTests.cpp",
"src/tests/unittests/ErrorTests.cpp", "src/tests/unittests/ErrorTests.cpp",
"src/tests/unittests/ExtensionTests.cpp",
"src/tests/unittests/MathTests.cpp", "src/tests/unittests/MathTests.cpp",
"src/tests/unittests/ObjectBaseTests.cpp", "src/tests/unittests/ObjectBaseTests.cpp",
"src/tests/unittests/PerStageTests.cpp", "src/tests/unittests/PerStageTests.cpp",

View File

@ -38,6 +38,24 @@ namespace dawn_native {
return mInstance; return mInstance;
} }
ExtensionsSet AdapterBase::GetSupportedExtensions() const {
return mSupportedExtensions;
}
bool AdapterBase::SupportsAllRequestedExtensions(
const std::vector<const char*>& requestedExtensions) const {
for (const char* extensionStr : requestedExtensions) {
Extension extensionEnum = mInstance->ExtensionNameToEnum(extensionStr);
if (extensionEnum == Extension::InvalidEnum) {
return false;
}
if (!mSupportedExtensions.IsEnabled(extensionEnum)) {
return false;
}
}
return true;
}
DeviceBase* AdapterBase::CreateDevice(const DeviceDescriptor* descriptor) { DeviceBase* AdapterBase::CreateDevice(const DeviceDescriptor* descriptor) {
DeviceBase* result = nullptr; DeviceBase* result = nullptr;
@ -50,6 +68,12 @@ namespace dawn_native {
MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result, MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result,
const DeviceDescriptor* descriptor) { const DeviceDescriptor* descriptor) {
if (descriptor != nullptr) {
if (!SupportsAllRequestedExtensions(descriptor->requiredExtensions)) {
return DAWN_VALIDATION_ERROR("One or more requested extensions are not supported");
}
}
// TODO(cwallez@chromium.org): This will eventually have validation that the device // TODO(cwallez@chromium.org): This will eventually have validation that the device
// descriptor is valid and is a subset what's allowed on this adapter. // descriptor is valid and is a subset what's allowed on this adapter.
DAWN_TRY_ASSIGN(*result, CreateDeviceImpl(descriptor)); DAWN_TRY_ASSIGN(*result, CreateDeviceImpl(descriptor));

View File

@ -18,6 +18,7 @@
#include "dawn_native/DawnNative.h" #include "dawn_native/DawnNative.h"
#include "dawn_native/Error.h" #include "dawn_native/Error.h"
#include "dawn_native/Extensions.h"
namespace dawn_native { namespace dawn_native {
@ -35,9 +36,14 @@ namespace dawn_native {
DeviceBase* CreateDevice(const DeviceDescriptor* descriptor = nullptr); DeviceBase* CreateDevice(const DeviceDescriptor* descriptor = nullptr);
ExtensionsSet GetSupportedExtensions() const;
bool SupportsAllRequestedExtensions(
const std::vector<const char*>& requestedExtensions) const;
protected: protected:
PCIInfo mPCIInfo = {}; PCIInfo mPCIInfo = {};
DeviceType mDeviceType = DeviceType::Unknown; DeviceType mDeviceType = DeviceType::Unknown;
ExtensionsSet mSupportedExtensions;
private: private:
virtual ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) = 0; virtual ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) = 0;

View File

@ -55,6 +55,11 @@ namespace dawn_native {
return mImpl->GetPCIInfo(); return mImpl->GetPCIInfo();
} }
std::vector<const char*> Adapter::GetSupportedExtensions() const {
ExtensionsSet supportedExtensionsSet = mImpl->GetSupportedExtensions();
return supportedExtensionsSet.GetEnabledExtensionNames();
}
Adapter::operator bool() const { Adapter::operator bool() const {
return mImpl != nullptr; return mImpl != nullptr;
} }

View File

@ -66,6 +66,10 @@ namespace dawn_native {
mDynamicUploader = std::make_unique<DynamicUploader>(this); mDynamicUploader = std::make_unique<DynamicUploader>(this);
SetDefaultToggles(); SetDefaultToggles();
if (descriptor != nullptr) {
ApplyExtensions(descriptor);
}
mFormatTable = BuildFormatTable(this); mFormatTable = BuildFormatTable(this);
} }
@ -505,10 +509,26 @@ namespace dawn_native {
} }
} }
void DeviceBase::ApplyExtensions(const DeviceDescriptor* deviceDescriptor) {
ASSERT(deviceDescriptor);
ASSERT(GetAdapter()->SupportsAllRequestedExtensions(deviceDescriptor->requiredExtensions));
mEnabledExtensions = GetAdapter()->GetInstance()->ExtensionNamesToExtensionsSet(
deviceDescriptor->requiredExtensions);
}
std::vector<const char*> DeviceBase::GetEnabledExtensions() const {
return mEnabledExtensions.GetEnabledExtensionNames();
}
std::vector<const char*> DeviceBase::GetTogglesUsed() const { std::vector<const char*> DeviceBase::GetTogglesUsed() const {
return mTogglesSet.GetEnabledToggleNames(); return mTogglesSet.GetEnabledToggleNames();
} }
bool DeviceBase::IsExtensionEnabled(Extension extension) const {
return mEnabledExtensions.IsEnabled(extension);
}
bool DeviceBase::IsToggleEnabled(Toggle toggle) const { bool DeviceBase::IsToggleEnabled(Toggle toggle) const {
return mTogglesSet.IsEnabled(toggle); return mTogglesSet.IsEnabled(toggle);
} }

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/Extensions.h"
#include "dawn_native/Format.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"
@ -154,7 +155,9 @@ namespace dawn_native {
ResultOrError<DynamicUploader*> GetDynamicUploader() const; ResultOrError<DynamicUploader*> GetDynamicUploader() const;
std::vector<const char*> GetEnabledExtensions() const;
std::vector<const char*> GetTogglesUsed() const; std::vector<const char*> GetTogglesUsed() const;
bool IsExtensionEnabled(Extension extension) const;
bool IsToggleEnabled(Toggle toggle) const; bool IsToggleEnabled(Toggle toggle) const;
size_t GetLazyClearCountForTesting(); size_t GetLazyClearCountForTesting();
void IncrementLazyClearCountForTesting(); void IncrementLazyClearCountForTesting();
@ -212,6 +215,8 @@ namespace dawn_native {
TextureBase* texture, TextureBase* texture,
const TextureViewDescriptor* descriptor); const TextureViewDescriptor* descriptor);
void ApplyExtensions(const DeviceDescriptor* deviceDescriptor);
void ConsumeError(ErrorData* error); void ConsumeError(ErrorData* error);
void SetDefaultToggles(); void SetDefaultToggles();
@ -240,6 +245,8 @@ namespace dawn_native {
TogglesSet mTogglesSet; TogglesSet mTogglesSet;
size_t mLazyClearCountForTesting = 0; size_t mLazyClearCountForTesting = 0;
ExtensionsSet mEnabledExtensions;
}; };
} // namespace dawn_native } // namespace dawn_native

View File

@ -0,0 +1,113 @@
// 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 <array>
#include "common/Assert.h"
#include "common/BitSetIterator.h"
#include "dawn_native/Extensions.h"
namespace dawn_native {
namespace {
struct ExtensionEnumAndInfo {
Extension extension;
ExtensionInfo info;
};
using ExtensionEnumAndInfoList =
std::array<ExtensionEnumAndInfo, static_cast<size_t>(Extension::EnumCount)>;
static constexpr ExtensionEnumAndInfoList kExtensionNameAndInfoList = {
{{Extension::TextureCompressionBC,
{"texture_compression_bc", "Support Block Compressed (BC) texture formats",
"https://bugs.chromium.org/p/dawn/issues/detail?id=42"}}}};
} // anonymous namespace
void ExtensionsSet::EnableExtension(Extension extension) {
ASSERT(extension != Extension::InvalidEnum);
const size_t extensionIndex = static_cast<size_t>(extension);
extensionsBitSet.set(extensionIndex);
}
bool ExtensionsSet::IsEnabled(Extension extension) const {
ASSERT(extension != Extension::InvalidEnum);
const size_t extensionIndex = static_cast<size_t>(extension);
return extensionsBitSet[extensionIndex];
}
std::vector<const char*> ExtensionsSet::GetEnabledExtensionNames() const {
std::vector<const char*> enabledExtensionNames(extensionsBitSet.count());
uint32_t index = 0;
for (uint32_t i : IterateBitSet(extensionsBitSet)) {
const char* extensionName = ExtensionEnumToName(static_cast<Extension>(i));
enabledExtensionNames[index] = extensionName;
++index;
}
return enabledExtensionNames;
}
const char* ExtensionEnumToName(Extension extension) {
ASSERT(extension != Extension::InvalidEnum);
const ExtensionEnumAndInfo& extensionNameAndInfo =
kExtensionNameAndInfoList[static_cast<size_t>(extension)];
ASSERT(extensionNameAndInfo.extension == extension);
return extensionNameAndInfo.info.name;
}
ExtensionsInfo::ExtensionsInfo() {
for (size_t index = 0; index < kExtensionNameAndInfoList.size(); ++index) {
const ExtensionEnumAndInfo& extensionNameAndInfo = kExtensionNameAndInfoList[index];
ASSERT(index == static_cast<size_t>(extensionNameAndInfo.extension));
mExtensionNameToEnumMap[extensionNameAndInfo.info.name] =
extensionNameAndInfo.extension;
}
}
const ExtensionInfo* ExtensionsInfo::GetExtensionInfo(const char* extensionName) const {
ASSERT(extensionName);
const auto& iter = mExtensionNameToEnumMap.find(extensionName);
if (iter != mExtensionNameToEnumMap.cend()) {
return &kExtensionNameAndInfoList[static_cast<size_t>(iter->second)].info;
}
return nullptr;
}
Extension ExtensionsInfo::ExtensionNameToEnum(const char* extensionName) const {
ASSERT(extensionName);
const auto& iter = mExtensionNameToEnumMap.find(extensionName);
if (iter != mExtensionNameToEnumMap.cend()) {
return kExtensionNameAndInfoList[static_cast<size_t>(iter->second)].extension;
}
return Extension::InvalidEnum;
}
ExtensionsSet ExtensionsInfo::ExtensionNamesToExtensionsSet(
const std::vector<const char*>& requiredExtensions) const {
ExtensionsSet extensionsSet;
for (const char* extensionName : requiredExtensions) {
Extension extensionEnum = ExtensionNameToEnum(extensionName);
ASSERT(extensionEnum != Extension::InvalidEnum);
extensionsSet.EnableExtension(extensionEnum);
}
return extensionsSet;
}
} // namespace dawn_native

View File

@ -0,0 +1,63 @@
// 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_EXTENSIONS_H_
#define DAWNNATIVE_EXTENSIONS_H_
#include <bitset>
#include <unordered_map>
#include <vector>
#include "dawn_native/DawnNative.h"
namespace dawn_native {
enum class Extension {
TextureCompressionBC,
EnumCount,
InvalidEnum = EnumCount,
ExtensionMin = TextureCompressionBC,
};
// A wrapper of the bitset to store if an extension is enabled or not. This wrapper provides the
// convenience to convert the enums of enum class Extension to the indices of a bitset.
struct ExtensionsSet {
std::bitset<static_cast<size_t>(Extension::EnumCount)> extensionsBitSet;
void EnableExtension(Extension extension);
bool IsEnabled(Extension extension) const;
std::vector<const char*> GetEnabledExtensionNames() const;
};
const char* ExtensionEnumToName(Extension extension);
class ExtensionsInfo {
public:
ExtensionsInfo();
// Used to query the details of an extension. Return nullptr if extensionName is not a valid
// name of an extension supported in Dawn
const ExtensionInfo* GetExtensionInfo(const char* extensionName) const;
Extension ExtensionNameToEnum(const char* extensionName) const;
ExtensionsSet ExtensionNamesToExtensionsSet(
const std::vector<const char*>& requiredExtensions) const;
private:
std::unordered_map<std::string, Extension> mExtensionNameToEnumMap;
};
} // namespace dawn_native
#endif // DAWNNATIVE_EXTENSIONS_H_

View File

@ -13,6 +13,8 @@
// limitations under the License. // limitations under the License.
#include "dawn_native/Format.h" #include "dawn_native/Format.h"
#include "dawn_native/Device.h"
#include "dawn_native/Extensions.h"
#include <bitset> #include <bitset>
@ -48,7 +50,7 @@ namespace dawn_native {
return static_cast<size_t>(static_cast<uint32_t>(format)); return static_cast<size_t>(static_cast<uint32_t>(format));
} }
FormatTable BuildFormatTable(const DeviceBase*) { FormatTable BuildFormatTable(const DeviceBase* device) {
FormatTable table; FormatTable table;
std::bitset<kKnownFormatCount> formatsSet; std::bitset<kKnownFormatCount> formatsSet;
@ -93,12 +95,12 @@ namespace dawn_native {
}; };
auto AddCompressedFormat = [&AddFormat](dawn::TextureFormat format, uint32_t byteSize, auto AddCompressedFormat = [&AddFormat](dawn::TextureFormat format, uint32_t byteSize,
uint32_t width, uint32_t height) { uint32_t width, uint32_t height, bool isSupported) {
Format internalFormat; Format internalFormat;
internalFormat.format = format; internalFormat.format = format;
internalFormat.isRenderable = false; internalFormat.isRenderable = false;
internalFormat.isCompressed = true; internalFormat.isCompressed = true;
internalFormat.isSupported = true; internalFormat.isSupported = isSupported;
internalFormat.aspect = Format::Aspect::Color; internalFormat.aspect = Format::Aspect::Color;
internalFormat.blockByteSize = byteSize; internalFormat.blockByteSize = byteSize;
internalFormat.blockWidth = width; internalFormat.blockWidth = width;
@ -168,20 +170,21 @@ namespace dawn_native {
AddDepthStencilFormat(dawn::TextureFormat::Depth24PlusStencil8, Format::Aspect::DepthStencil, 4); AddDepthStencilFormat(dawn::TextureFormat::Depth24PlusStencil8, Format::Aspect::DepthStencil, 4);
// BC compressed formats // BC compressed formats
AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnorm, 8, 4, 4); bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC4RSnorm, 8, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC4RUnorm, 8, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnorm, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnorm, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC5RGSnorm, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC5RGUnorm, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC6HRGBSfloat, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC6HRGBUfloat, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC6HRGBSfloat, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnorm, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4); AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported);
AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
// clang-format on // clang-format on

View File

@ -86,6 +86,19 @@ namespace dawn_native {
return mTogglesInfo.ToggleNameToEnum(toggleName); return mTogglesInfo.ToggleNameToEnum(toggleName);
} }
const ExtensionInfo* InstanceBase::GetExtensionInfo(const char* extensionName) {
return mExtensionsInfo.GetExtensionInfo(extensionName);
}
Extension InstanceBase::ExtensionNameToEnum(const char* extensionName) {
return mExtensionsInfo.ExtensionNameToEnum(extensionName);
}
ExtensionsSet InstanceBase::ExtensionNamesToExtensionsSet(
const std::vector<const char*>& requiredExtensions) {
return mExtensionsInfo.ExtensionNamesToExtensionsSet(requiredExtensions);
}
const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const { const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const {
return mAdapters; return mAdapters;
} }

View File

@ -17,6 +17,7 @@
#include "dawn_native/Adapter.h" #include "dawn_native/Adapter.h"
#include "dawn_native/BackendConnection.h" #include "dawn_native/BackendConnection.h"
#include "dawn_native/Extensions.h"
#include "dawn_native/Toggles.h" #include "dawn_native/Toggles.h"
#include <array> #include <array>
@ -47,9 +48,15 @@ namespace dawn_native {
// Used to query the details of a toggle. Return nullptr if toggleName is not a valid name // Used to query the details of a toggle. Return nullptr if toggleName is not a valid name
// of a toggle supported in Dawn. // of a toggle supported in Dawn.
const ToggleInfo* GetToggleInfo(const char* toggleName); const ToggleInfo* GetToggleInfo(const char* toggleName);
Toggle ToggleNameToEnum(const char* toggleName); Toggle ToggleNameToEnum(const char* toggleName);
// Used to query the details of an extension. Return nullptr if extensionName is not a valid
// name of an extension supported in Dawn.
const ExtensionInfo* GetExtensionInfo(const char* extensionName);
Extension ExtensionNameToEnum(const char* extensionName);
ExtensionsSet ExtensionNamesToExtensionsSet(
const std::vector<const char*>& requiredExtensions);
void EnableBackendValidation(bool enableBackendValidation); void EnableBackendValidation(bool enableBackendValidation);
bool IsBackendValidationEnabled() const; bool IsBackendValidationEnabled() const;
@ -74,6 +81,7 @@ namespace dawn_native {
std::vector<std::unique_ptr<BackendConnection>> mBackends; std::vector<std::unique_ptr<BackendConnection>> mBackends;
std::vector<std::unique_ptr<AdapterBase>> mAdapters; std::vector<std::unique_ptr<AdapterBase>> mAdapters;
ExtensionsInfo mExtensionsInfo;
TogglesInfo mTogglesInfo; TogglesInfo mTogglesInfo;
}; };

View File

@ -84,9 +84,15 @@ namespace dawn_native { namespace d3d12 {
"Error converting"); "Error converting");
mPCIInfo.name = converter.to_bytes(adapterDesc.Description); mPCIInfo.name = converter.to_bytes(adapterDesc.Description);
InitializeSupportedExtensions();
return {}; return {};
} }
void Adapter::InitializeSupportedExtensions() {
mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
}
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) { ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
std::unique_ptr<Device> device = std::make_unique<Device>(this, descriptor); std::unique_ptr<Device> device = std::make_unique<Device>(this, descriptor);
DAWN_TRY(device->Initialize()); DAWN_TRY(device->Initialize());

View File

@ -38,6 +38,7 @@ namespace dawn_native { namespace d3d12 {
private: private:
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override; ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
void InitializeSupportedExtensions();
ComPtr<IDXGIAdapter1> mHardwareAdapter; ComPtr<IDXGIAdapter1> mHardwareAdapter;
ComPtr<ID3D12Device> mD3d12Device; ComPtr<ID3D12Device> mD3d12Device;

View File

@ -182,6 +182,11 @@ namespace dawn_native { namespace metal {
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override { ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
return {new Device(this, mDevice, descriptor)}; return {new Device(this, mDevice, descriptor)};
} }
void InitializeSupportedExtensions() {
if ([mDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
}
}
id<MTLDevice> mDevice = nil; id<MTLDevice> mDevice = nil;
}; };

View File

@ -17,6 +17,7 @@
#include "dawn_native/BackendConnection.h" #include "dawn_native/BackendConnection.h"
#include "dawn_native/Commands.h" #include "dawn_native/Commands.h"
#include "dawn_native/DynamicUploader.h" #include "dawn_native/DynamicUploader.h"
#include "dawn_native/Instance.h"
#include <spirv-cross/spirv_cross.hpp> #include <spirv-cross/spirv_cross.hpp>
@ -24,19 +25,24 @@ namespace dawn_native { namespace null {
// Implementation of pre-Device objects: the null adapter, null backend connection and Connect() // Implementation of pre-Device objects: the null adapter, null backend connection and Connect()
class Adapter : public AdapterBase { Adapter::Adapter(InstanceBase* instance) : AdapterBase(instance, BackendType::Null) {
public: mPCIInfo.name = "Null backend";
Adapter(InstanceBase* instance) : AdapterBase(instance, BackendType::Null) { mDeviceType = DeviceType::CPU;
mPCIInfo.name = "Null backend";
mDeviceType = DeviceType::CPU;
}
virtual ~Adapter() = default;
private: // Enable all extensions by default for the convenience of tests.
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override { mSupportedExtensions.extensionsBitSet.flip();
return {new Device(this, descriptor)}; }
}
}; Adapter::~Adapter() = default;
// Used for the tests that intend to use an adapter without all extensions enabled.
void Adapter::SetSupportedExtensions(const std::vector<const char*>& requiredExtensions) {
mSupportedExtensions = GetInstance()->ExtensionNamesToExtensionsSet(requiredExtensions);
}
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
return {new Device(this, descriptor)};
}
class Backend : public BackendConnection { class Backend : public BackendConnection {
public: public:

View File

@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_NULL_DEVICENULL_H_ #ifndef DAWNNATIVE_NULL_DEVICENULL_H_
#define DAWNNATIVE_NULL_DEVICENULL_H_ #define DAWNNATIVE_NULL_DEVICENULL_H_
#include "dawn_native/Adapter.h"
#include "dawn_native/BindGroup.h" #include "dawn_native/BindGroup.h"
#include "dawn_native/BindGroupLayout.h" #include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Buffer.h" #include "dawn_native/Buffer.h"
@ -137,6 +138,18 @@ namespace dawn_native { namespace null {
size_t mMemoryUsage = 0; size_t mMemoryUsage = 0;
}; };
class Adapter : public AdapterBase {
public:
Adapter(InstanceBase* instance);
virtual ~Adapter();
// Used for the tests that intend to use an adapter without all extensions enabled.
void SetSupportedExtensions(const std::vector<const char*>& requiredExtensions);
private:
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
};
class Buffer : public BufferBase { class Buffer : public BufferBase {
public: public:
Buffer(Device* device, const BufferDescriptor* descriptor); Buffer(Device* device, const BufferDescriptor* descriptor);

View File

@ -40,6 +40,8 @@ namespace dawn_native { namespace vulkan {
MaybeError Adapter::Initialize() { MaybeError Adapter::Initialize() {
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this)); DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
InitializeSupportedExtensions();
mPCIInfo.deviceId = mDeviceInfo.properties.deviceID; mPCIInfo.deviceId = mDeviceInfo.properties.deviceID;
mPCIInfo.vendorId = mDeviceInfo.properties.vendorID; mPCIInfo.vendorId = mDeviceInfo.properties.vendorID;
mPCIInfo.name = mDeviceInfo.properties.deviceName; mPCIInfo.name = mDeviceInfo.properties.deviceName;
@ -62,6 +64,12 @@ namespace dawn_native { namespace vulkan {
return {}; return {};
} }
void Adapter::InitializeSupportedExtensions() {
if (mDeviceInfo.features.textureCompressionBC == VK_TRUE) {
mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
}
}
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) { ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
std::unique_ptr<Device> device = std::make_unique<Device>(this, descriptor); std::unique_ptr<Device> device = std::make_unique<Device>(this, descriptor);
DAWN_TRY(device->Initialize()); DAWN_TRY(device->Initialize());

View File

@ -37,6 +37,7 @@ namespace dawn_native { namespace vulkan {
private: private:
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override; ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
void InitializeSupportedExtensions();
VkPhysicalDevice mPhysicalDevice; VkPhysicalDevice mPhysicalDevice;
Backend* mBackend; Backend* mBackend;

View File

@ -344,8 +344,11 @@ namespace dawn_native { namespace vulkan {
// Always require fragmentStoresAndAtomics because it is required by end2end tests. // Always require fragmentStoresAndAtomics because it is required by end2end tests.
usedKnobs.features.fragmentStoresAndAtomics = VK_TRUE; usedKnobs.features.fragmentStoresAndAtomics = VK_TRUE;
// TODO(jiawei.shao@intel.com): support BC formats as extension if (IsExtensionEnabled(Extension::TextureCompressionBC)) {
usedKnobs.features.textureCompressionBC = VK_TRUE; ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.textureCompressionBC ==
VK_TRUE);
usedKnobs.features.textureCompressionBC = VK_TRUE;
}
// Find a universal queue family // Find a universal queue family
{ {

View File

@ -50,6 +50,7 @@ namespace dawn_native {
// An optional parameter of Adapter::CreateDevice() to send additional information when creating // An optional parameter of Adapter::CreateDevice() to send additional information when creating
// a Device. For example, we can use it to enable a workaround, optimization or feature. // a Device. For example, we can use it to enable a workaround, optimization or feature.
struct DAWN_NATIVE_EXPORT DeviceDescriptor { struct DAWN_NATIVE_EXPORT DeviceDescriptor {
std::vector<const char*> requiredExtensions;
std::vector<const char*> forceEnabledToggles; std::vector<const char*> forceEnabledToggles;
std::vector<const char*> forceDisabledToggles; std::vector<const char*> forceDisabledToggles;
}; };
@ -63,6 +64,11 @@ namespace dawn_native {
const char* url; const char* url;
}; };
// A struct to record the information of an extension. An extension is a GPU feature that is not
// required to be supported by all Dawn backends and can only be used when it is enabled on the
// creation of device.
using ExtensionInfo = ToggleInfo;
// An adapter is an object that represent on possibility of creating devices in the system. // An adapter is an object that represent on possibility of creating devices in the system.
// Most of the time it will represent a combination of a physical GPU and an API. Not that the // Most of the time it will represent a combination of a physical GPU and an API. Not that the
// same GPU can be represented by multiple adapters but on different APIs. // same GPU can be represented by multiple adapters but on different APIs.
@ -78,6 +84,7 @@ namespace dawn_native {
BackendType GetBackendType() const; BackendType GetBackendType() const;
DeviceType GetDeviceType() const; DeviceType GetDeviceType() const;
const PCIInfo& GetPCIInfo() const; const PCIInfo& GetPCIInfo() const;
std::vector<const char*> GetSupportedExtensions() const;
explicit operator bool() const; explicit operator bool() const;

View File

@ -333,9 +333,31 @@ uint32_t DawnTest::GetVendorIdFilter() const {
return gTestEnv->GetVendorIdFilter(); return gTestEnv->GetVendorIdFilter();
} }
std::vector<const char*> DawnTest::GetRequiredExtensions() {
return {};
}
// This function can only be called after SetUp() because it requires mBackendAdapter to be
// initialized.
bool DawnTest::SupportsExtensions(const std::vector<const char*>& extensions) {
ASSERT(mBackendAdapter);
std::set<std::string> supportedExtensionsSet;
for (const char* supportedExtensionName : mBackendAdapter.GetSupportedExtensions()) {
supportedExtensionsSet.insert(supportedExtensionName);
}
for (const char* extensionName : extensions) {
if (supportedExtensionsSet.find(extensionName) == supportedExtensionsSet.end()) {
return false;
}
}
return true;
}
void DawnTest::SetUp() { void DawnTest::SetUp() {
// Get an adapter for the backend to use, and create the device. // Initialize mBackendAdapter, and create the device.
dawn_native::Adapter backendAdapter;
const dawn_native::BackendType backendType = GetParam().backendType; const dawn_native::BackendType backendType = GetParam().backendType;
{ {
dawn_native::Instance* instance = gTestEnv->GetInstance(); dawn_native::Instance* instance = gTestEnv->GetInstance();
@ -345,11 +367,11 @@ void DawnTest::SetUp() {
if (adapter.GetBackendType() == backendType) { if (adapter.GetBackendType() == backendType) {
if (HasVendorIdFilter()) { if (HasVendorIdFilter()) {
if (adapter.GetPCIInfo().vendorId == GetVendorIdFilter()) { if (adapter.GetPCIInfo().vendorId == GetVendorIdFilter()) {
backendAdapter = adapter; mBackendAdapter = adapter;
break; break;
} }
} else { } else {
backendAdapter = adapter; mBackendAdapter = adapter;
// On Metal, select the last adapter so that the discrete GPU is tested on // On Metal, select the last adapter so that the discrete GPU is tested on
// multi-GPU systems. // multi-GPU systems.
@ -363,10 +385,10 @@ void DawnTest::SetUp() {
} }
} }
ASSERT(backendAdapter); ASSERT(mBackendAdapter);
} }
mPCIInfo = backendAdapter.GetPCIInfo(); mPCIInfo = mBackendAdapter.GetPCIInfo();
for (const char* forceEnabledWorkaround : GetParam().forceEnabledWorkarounds) { for (const char* forceEnabledWorkaround : GetParam().forceEnabledWorkarounds) {
ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceEnabledWorkaround) != nullptr); ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceEnabledWorkaround) != nullptr);
@ -377,7 +399,9 @@ void DawnTest::SetUp() {
dawn_native::DeviceDescriptor deviceDescriptor; dawn_native::DeviceDescriptor deviceDescriptor;
deviceDescriptor.forceEnabledToggles = GetParam().forceEnabledWorkarounds; deviceDescriptor.forceEnabledToggles = GetParam().forceEnabledWorkarounds;
deviceDescriptor.forceDisabledToggles = GetParam().forceDisabledWorkarounds; deviceDescriptor.forceDisabledToggles = GetParam().forceDisabledWorkarounds;
backendDevice = backendAdapter.CreateDevice(&deviceDescriptor); deviceDescriptor.requiredExtensions = GetRequiredExtensions();
backendDevice = mBackendAdapter.CreateDevice(&deviceDescriptor);
ASSERT_NE(nullptr, backendDevice);
backendProcs = dawn_native::GetProcs(); backendProcs = dawn_native::GetProcs();

View File

@ -206,6 +206,14 @@ class DawnTest : public ::testing::TestWithParam<DawnTestParam> {
void SwapBuffersForCapture(); void SwapBuffersForCapture();
bool SupportsExtensions(const std::vector<const char*>& extensions);
// Called in SetUp() to get the extensions required to be enabled in the tests. The tests must
// check if the required extensions are supported by the adapter in this function and guarantee
// the returned extensions are all supported by the adapter. The tests may provide different
// code path to handle the situation when not all extensions are supported.
virtual std::vector<const char*> GetRequiredExtensions();
private: private:
// Things used to set up testing through the Wire. // Things used to set up testing through the Wire.
std::unique_ptr<dawn_wire::WireServer> mWireServer; std::unique_ptr<dawn_wire::WireServer> mWireServer;
@ -263,6 +271,8 @@ class DawnTest : public ::testing::TestWithParam<DawnTestParam> {
std::unique_ptr<utils::BackendBinding> mBinding; std::unique_ptr<utils::BackendBinding> mBinding;
dawn_native::PCIInfo mPCIInfo; dawn_native::PCIInfo mPCIInfo;
dawn_native::Adapter mBackendAdapter;
}; };
// Instantiate the test once for each backend provided after the first argument. Use it like this: // Instantiate the test once for each backend provided after the first argument. Use it like this:

View File

@ -67,9 +67,24 @@ class CompressedTextureBCFormatTest : public DawnTest {
{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture}}); {1, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture}});
} }
std::vector<const char*> GetRequiredExtensions() override {
mIsBCFormatSupported = SupportsExtensions({"texture_compression_bc"});
if (!mIsBCFormatSupported) {
return {};
}
return {"texture_compression_bc"};
}
bool IsBCFormatSupported() const {
return mIsBCFormatSupported;
}
// Copy the compressed texture data into the destination texture as is specified in copyConfig. // Copy the compressed texture data into the destination texture as is specified in copyConfig.
void CopyDataIntoCompressedTexture(dawn::Texture bcCompressedTexture, void CopyDataIntoCompressedTexture(dawn::Texture bcCompressedTexture,
const CopyConfig& copyConfig) { const CopyConfig& copyConfig) {
ASSERT(IsBCFormatSupported());
// Compute the upload buffer size with rowPitchAlignment and the copy region. // Compute the upload buffer size with rowPitchAlignment and the copy region.
uint32_t actualWidthAtLevel = copyConfig.textureWidthLevel0 >> copyConfig.baseMipmapLevel; uint32_t actualWidthAtLevel = copyConfig.textureWidthLevel0 >> copyConfig.baseMipmapLevel;
uint32_t actualHeightAtLevel = copyConfig.textureHeightLevel0 >> copyConfig.baseMipmapLevel; uint32_t actualHeightAtLevel = copyConfig.textureHeightLevel0 >> copyConfig.baseMipmapLevel;
@ -121,6 +136,8 @@ class CompressedTextureBCFormatTest : public DawnTest {
dawn::TextureFormat bcFormat, dawn::TextureFormat bcFormat,
uint32_t baseArrayLayer = 0, uint32_t baseArrayLayer = 0,
uint32_t baseMipLevel = 0) { uint32_t baseMipLevel = 0) {
ASSERT(IsBCFormatSupported());
dawn::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor(); dawn::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor();
samplerDesc.minFilter = dawn::FilterMode::Nearest; samplerDesc.minFilter = dawn::FilterMode::Nearest;
samplerDesc.magFilter = dawn::FilterMode::Nearest; samplerDesc.magFilter = dawn::FilterMode::Nearest;
@ -140,6 +157,8 @@ class CompressedTextureBCFormatTest : public DawnTest {
// Create a render pipeline for sampling from a BC texture and rendering into the render target. // Create a render pipeline for sampling from a BC texture and rendering into the render target.
dawn::RenderPipeline CreateRenderPipelineForTest() { dawn::RenderPipeline CreateRenderPipelineForTest() {
ASSERT(IsBCFormatSupported());
dawn::PipelineLayout pipelineLayout = dawn::PipelineLayout pipelineLayout =
utils::MakeBasicPipelineLayout(device, &mBindGroupLayout); utils::MakeBasicPipelineLayout(device, &mBindGroupLayout);
@ -183,6 +202,8 @@ class CompressedTextureBCFormatTest : public DawnTest {
const dawn::Origin3D& expectedOrigin, const dawn::Origin3D& expectedOrigin,
const dawn::Extent3D& expectedExtent, const dawn::Extent3D& expectedExtent,
const std::vector<RGBA8>& expected) { const std::vector<RGBA8>& expected) {
ASSERT(IsBCFormatSupported());
ASSERT(expected.size() == renderTargetSize.width * renderTargetSize.height); ASSERT(expected.size() == renderTargetSize.width * renderTargetSize.height);
utils::BasicRenderPass renderPass = utils::BasicRenderPass renderPass =
utils::CreateBasicRenderPass(device, renderTargetSize.width, renderTargetSize.height); utils::CreateBasicRenderPass(device, renderTargetSize.width, renderTargetSize.height);
@ -207,6 +228,8 @@ class CompressedTextureBCFormatTest : public DawnTest {
// Run the tests that copies pre-prepared BC format data into a BC texture and verifies if we // Run the tests that copies pre-prepared BC format data into a BC texture and verifies if we
// can render correctly with the pixel values sampled from the BC texture. // can render correctly with the pixel values sampled from the BC texture.
void TestCopyRegionIntoBCFormatTextures(const CopyConfig& config) { void TestCopyRegionIntoBCFormatTextures(const CopyConfig& config) {
ASSERT(IsBCFormatSupported());
dawn::Texture bcTexture = Create2DTexture(device, config.format, config.textureWidthLevel0, dawn::Texture bcTexture = Create2DTexture(device, config.format, config.textureWidthLevel0,
config.textureHeightLevel0, config.textureHeightLevel0,
config.arrayLayerCount, config.mipmapLevelCount); config.arrayLayerCount, config.mipmapLevelCount);
@ -416,10 +439,14 @@ class CompressedTextureBCFormatTest : public DawnTest {
static constexpr uint32_t kBCBlockHeightInTexels = 4; static constexpr uint32_t kBCBlockHeightInTexels = 4;
dawn::BindGroupLayout mBindGroupLayout; dawn::BindGroupLayout mBindGroupLayout;
bool mIsBCFormatSupported = false;
}; };
// Test copying into the whole BC texture with 2x2 blocks and sampling from it. // Test copying into the whole BC texture with 2x2 blocks and sampling from it.
TEST_P(CompressedTextureBCFormatTest, Basic) { TEST_P(CompressedTextureBCFormatTest, Basic) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureWidthLevel0 = 8; config.textureWidthLevel0 = 8;
config.textureHeightLevel0 = 8; config.textureHeightLevel0 = 8;
@ -433,6 +460,8 @@ TEST_P(CompressedTextureBCFormatTest, Basic) {
// Test copying into a sub-region of a texture with BC formats works correctly. // Test copying into a sub-region of a texture with BC formats works correctly.
TEST_P(CompressedTextureBCFormatTest, CopyIntoSubRegion) { TEST_P(CompressedTextureBCFormatTest, CopyIntoSubRegion) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureHeightLevel0 = 8; config.textureHeightLevel0 = 8;
config.textureWidthLevel0 = 8; config.textureWidthLevel0 = 8;
@ -451,6 +480,8 @@ TEST_P(CompressedTextureBCFormatTest, CopyIntoSubRegion) {
// Test using rowPitch == 0 in the copies with BC formats works correctly. // Test using rowPitch == 0 in the copies with BC formats works correctly.
TEST_P(CompressedTextureBCFormatTest, CopyWithZeroRowPitch) { TEST_P(CompressedTextureBCFormatTest, CopyWithZeroRowPitch) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureHeightLevel0 = 8; config.textureHeightLevel0 = 8;
@ -468,6 +499,8 @@ TEST_P(CompressedTextureBCFormatTest, CopyWithZeroRowPitch) {
// Test copying into the non-zero layer of a 2D array texture with BC formats works correctly. // Test copying into the non-zero layer of a 2D array texture with BC formats works correctly.
TEST_P(CompressedTextureBCFormatTest, CopyIntoNonZeroArrayLayer) { TEST_P(CompressedTextureBCFormatTest, CopyIntoNonZeroArrayLayer) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureHeightLevel0 = 8; config.textureHeightLevel0 = 8;
config.textureWidthLevel0 = 8; config.textureWidthLevel0 = 8;
@ -486,6 +519,8 @@ TEST_P(CompressedTextureBCFormatTest, CopyIntoNonZeroArrayLayer) {
// Test copying into a non-zero mipmap level of a texture with BC texture formats. // Test copying into a non-zero mipmap level of a texture with BC texture formats.
TEST_P(CompressedTextureBCFormatTest, CopyBufferIntoNonZeroMipmapLevel) { TEST_P(CompressedTextureBCFormatTest, CopyBufferIntoNonZeroMipmapLevel) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureHeightLevel0 = 60; config.textureHeightLevel0 = 60;
config.textureWidthLevel0 = 60; config.textureWidthLevel0 = 60;
@ -517,6 +552,8 @@ TEST_P(CompressedTextureBCFormatTest, CopyBufferIntoNonZeroMipmapLevel) {
// Test texture-to-texture whole-size copies with BC formats. // Test texture-to-texture whole-size copies with BC formats.
TEST_P(CompressedTextureBCFormatTest, CopyWholeTextureSubResourceIntoNonZeroMipmapLevel) { TEST_P(CompressedTextureBCFormatTest, CopyWholeTextureSubResourceIntoNonZeroMipmapLevel) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
// TODO(cwallez@chromium.org): This consistently fails on with the 12th pixel being opaque black // TODO(cwallez@chromium.org): This consistently fails on with the 12th pixel being opaque black
// instead of opaque red on Win10 FYI Release (NVIDIA GeForce GTX 1660). See // instead of opaque red on Win10 FYI Release (NVIDIA GeForce GTX 1660). See
// https://bugs.chromium.org/p/chromium/issues/detail?id=981393 // https://bugs.chromium.org/p/chromium/issues/detail?id=981393
@ -576,6 +613,8 @@ TEST_P(CompressedTextureBCFormatTest, CopyWholeTextureSubResourceIntoNonZeroMipm
// Test BC format texture-to-texture partial copies. // Test BC format texture-to-texture partial copies.
TEST_P(CompressedTextureBCFormatTest, CopyPartofTextureSubResourceIntoNonZeroMipmapLevel) { TEST_P(CompressedTextureBCFormatTest, CopyPartofTextureSubResourceIntoNonZeroMipmapLevel) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
// TODO(jiawei.shao@intel.com): add workaround on the T2T copies where Extent3D fits in one // TODO(jiawei.shao@intel.com): add workaround on the T2T copies where Extent3D fits in one
// subresource and does not fit in another one on Vulkan. Currently this test causes an error if // subresource and does not fit in another one on Vulkan. Currently this test causes an error if
// Vulkan validation layer is enabled. // Vulkan validation layer is enabled.
@ -652,6 +691,8 @@ TEST_P(CompressedTextureBCFormatTest, CopyPartofTextureSubResourceIntoNonZeroMip
// Test the special case of the B2T copies on the D3D12 backend that the buffer offset and texture // Test the special case of the B2T copies on the D3D12 backend that the buffer offset and texture
// extent exactly fit the RowPitch. // extent exactly fit the RowPitch.
TEST_P(CompressedTextureBCFormatTest, BufferOffsetAndExtentFitRowPitch) { TEST_P(CompressedTextureBCFormatTest, BufferOffsetAndExtentFitRowPitch) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureWidthLevel0 = 8; config.textureWidthLevel0 = 8;
config.textureHeightLevel0 = 8; config.textureHeightLevel0 = 8;
@ -677,6 +718,8 @@ TEST_P(CompressedTextureBCFormatTest, BufferOffsetAndExtentFitRowPitch) {
// backend the texelOffset.y will be greater than 0 after calcuting the texelOffset in the function // backend the texelOffset.y will be greater than 0 after calcuting the texelOffset in the function
// ComputeTexelOffsets(). // ComputeTexelOffsets().
TEST_P(CompressedTextureBCFormatTest, BufferOffsetExceedsSlicePitch) { TEST_P(CompressedTextureBCFormatTest, BufferOffsetExceedsSlicePitch) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureWidthLevel0 = 8; config.textureWidthLevel0 = 8;
config.textureHeightLevel0 = 8; config.textureHeightLevel0 = 8;
@ -703,6 +746,8 @@ TEST_P(CompressedTextureBCFormatTest, BufferOffsetExceedsSlicePitch) {
// Test the special case of the B2T copies on the D3D12 backend that the buffer offset and texture // Test the special case of the B2T copies on the D3D12 backend that the buffer offset and texture
// extent exceed the RowPitch. On D3D12 backend two copies are required for this case. // extent exceed the RowPitch. On D3D12 backend two copies are required for this case.
TEST_P(CompressedTextureBCFormatTest, CopyWithBufferOffsetAndExtentExceedRowPitch) { TEST_P(CompressedTextureBCFormatTest, CopyWithBufferOffsetAndExtentExceedRowPitch) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureWidthLevel0 = 8; config.textureWidthLevel0 = 8;
config.textureHeightLevel0 = 8; config.textureHeightLevel0 = 8;
@ -729,6 +774,8 @@ TEST_P(CompressedTextureBCFormatTest, CopyWithBufferOffsetAndExtentExceedRowPitc
// rowPitch. On D3D12 backend the texelOffset.z will be greater than 0 after calcuting the // rowPitch. On D3D12 backend the texelOffset.z will be greater than 0 after calcuting the
// texelOffset in the function ComputeTexelOffsets(). // texelOffset in the function ComputeTexelOffsets().
TEST_P(CompressedTextureBCFormatTest, RowPitchEqualToSlicePitch) { TEST_P(CompressedTextureBCFormatTest, RowPitchEqualToSlicePitch) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureWidthLevel0 = 8; config.textureWidthLevel0 = 8;
config.textureHeightLevel0 = kBCBlockHeightInTexels; config.textureHeightLevel0 = kBCBlockHeightInTexels;
@ -755,6 +802,8 @@ TEST_P(CompressedTextureBCFormatTest, RowPitchEqualToSlicePitch) {
// copyExtent.depth) on Metal backends. As copyExtent.depth can only be 1 for BC formats, on Metal // copyExtent.depth) on Metal backends. As copyExtent.depth can only be 1 for BC formats, on Metal
// backend we will use two copies to implement such copy. // backend we will use two copies to implement such copy.
TEST_P(CompressedTextureBCFormatTest, LargeImageHeight) { TEST_P(CompressedTextureBCFormatTest, LargeImageHeight) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureWidthLevel0 = 8; config.textureWidthLevel0 = 8;
config.textureHeightLevel0 = 8; config.textureHeightLevel0 = 8;
@ -771,6 +820,8 @@ TEST_P(CompressedTextureBCFormatTest, LargeImageHeight) {
// Test the workaround in the B2T copies when (bufferSize - bufferOffset < bytesPerImage * // Test the workaround in the B2T copies when (bufferSize - bufferOffset < bytesPerImage *
// copyExtent.depth) and copyExtent needs to be clamped. // copyExtent.depth) and copyExtent needs to be clamped.
TEST_P(CompressedTextureBCFormatTest, LargeImageHeightAndClampedCopyExtent) { TEST_P(CompressedTextureBCFormatTest, LargeImageHeightAndClampedCopyExtent) {
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
CopyConfig config; CopyConfig config;
config.textureHeightLevel0 = 56; config.textureHeightLevel0 = 56;
config.textureWidthLevel0 = 56; config.textureWidthLevel0 = 56;
@ -803,4 +854,8 @@ TEST_P(CompressedTextureBCFormatTest, LargeImageHeightAndClampedCopyExtent) {
} }
// TODO(jiawei.shao@intel.com): support BC formats on OpenGL backend // TODO(jiawei.shao@intel.com): support BC formats on OpenGL backend
DAWN_INSTANTIATE_TEST(CompressedTextureBCFormatTest, D3D12Backend, MetalBackend, VulkanBackend); DAWN_INSTANTIATE_TEST(CompressedTextureBCFormatTest,
D3D12Backend,
MetalBackend,
OpenGLBackend,
VulkanBackend);

View File

@ -0,0 +1,78 @@
// 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 <gtest/gtest.h>
#include "dawn_native/Extensions.h"
#include "dawn_native/Instance.h"
#include "dawn_native/null/DeviceNull.h"
class ExtensionTests : public testing::Test {
public:
ExtensionTests() : testing::Test(), mInstanceBase(), mAdapterBase(&mInstanceBase) {
}
std::vector<const char*> GetAllExtensionNames() {
std::vector<const char*> allExtensionNames(kTotalExtensionsCount);
for (size_t i = 0; i < kTotalExtensionsCount; ++i) {
allExtensionNames[i] = ExtensionEnumToName(static_cast<dawn_native::Extension>(i));
}
return allExtensionNames;
}
static constexpr size_t kTotalExtensionsCount =
static_cast<size_t>(dawn_native::Extension::EnumCount);
protected:
dawn_native::InstanceBase mInstanceBase;
dawn_native::null::Adapter mAdapterBase;
};
// Test the creation of a device will fail if the requested extension is not supported on the
// Adapter.
TEST_F(ExtensionTests, AdapterWithRequiredExtensionDisabled) {
const std::vector<const char*> kAllExtensionNames = GetAllExtensionNames();
for (size_t i = 0; i < kTotalExtensionsCount; ++i) {
dawn_native::Extension notSupportedExtension = static_cast<dawn_native::Extension>(i);
std::vector<const char*> extensionNamesWithoutOne = kAllExtensionNames;
extensionNamesWithoutOne.erase(extensionNamesWithoutOne.begin() + i);
mAdapterBase.SetSupportedExtensions(extensionNamesWithoutOne);
dawn_native::Adapter adapterWithoutExtension(&mAdapterBase);
dawn_native::DeviceDescriptor deviceDescriptor;
const char* extensionName = ExtensionEnumToName(notSupportedExtension);
deviceDescriptor.requiredExtensions = std::vector<const char*>(1, extensionName);
DawnDevice deviceWithExtension = adapterWithoutExtension.CreateDevice(&deviceDescriptor);
ASSERT_EQ(nullptr, deviceWithExtension);
}
}
// Test Device.GetEnabledExtensions() can return the names of the enabled extensions correctly.
TEST_F(ExtensionTests, GetEnabledExtensions) {
dawn_native::Adapter adapter(&mAdapterBase);
for (size_t i = 0; i < kTotalExtensionsCount; ++i) {
dawn_native::Extension extension = static_cast<dawn_native::Extension>(i);
const char* extensionName = ExtensionEnumToName(extension);
dawn_native::DeviceDescriptor deviceDescriptor;
deviceDescriptor.requiredExtensions = {extensionName};
dawn_native::DeviceBase* deviceBase =
reinterpret_cast<dawn_native::DeviceBase*>(adapter.CreateDevice(&deviceDescriptor));
std::vector<const char*> enabledExtensions = deviceBase->GetEnabledExtensions();
ASSERT_EQ(1u, enabledExtensions.size());
ASSERT_EQ(0, std::strcmp(extensionName, enabledExtensions[0]));
}
}

View File

@ -1155,6 +1155,11 @@ TEST_F(CopyCommandTest_T2T, CopyToMipmapOfNonSquareTexture) {
} }
class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest { class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {
public:
CopyCommandTest_CompressedTextureFormats() : CopyCommandTest() {
device = CreateDeviceFromAdapter(adapter, {"texture_compression_bc"});
}
protected: protected:
dawn::Texture Create2DTexture(dawn::TextureFormat format, dawn::Texture Create2DTexture(dawn::TextureFormat format,
uint32_t mipmapLevels = 1, uint32_t mipmapLevels = 1,

View File

@ -250,10 +250,14 @@ TEST_F(TextureValidationTest, NonRenderableAndOutputAttachment) {
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
} }
// TODO(jiawei.shao@intel.com): use compressed texture formats as extensions.
// TODO(jiawei.shao@intel.com): add tests to verify we cannot create 1D or 3D textures with // TODO(jiawei.shao@intel.com): add tests to verify we cannot create 1D or 3D textures with
// compressed texture formats. // compressed texture formats.
class CompressedTextureFormatsValidationTests : public TextureValidationTest { class CompressedTextureFormatsValidationTests : public TextureValidationTest {
public:
CompressedTextureFormatsValidationTests() : TextureValidationTest() {
device = CreateDeviceFromAdapter(adapter, {"texture_compression_bc"});
}
protected: protected:
dawn::TextureDescriptor CreateDefaultTextureDescriptor() { dawn::TextureDescriptor CreateDefaultTextureDescriptor() {
dawn::TextureDescriptor descriptor = dawn::TextureDescriptor descriptor =
@ -309,6 +313,18 @@ TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
} }
} }
// Test the creation of a texture with BC format will fail when the extension textureCompressionBC
// is not enabled.
TEST_F(CompressedTextureFormatsValidationTests, UseBCFormatWithoutEnablingExtension) {
const std::vector<const char*> kEmptyVector;
dawn::Device deviceWithoutExtension = CreateDeviceFromAdapter(adapter, kEmptyVector);
for (dawn::TextureFormat format : kBCFormats) {
dawn::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
ASSERT_DEVICE_ERROR(deviceWithoutExtension.CreateTexture(&descriptor));
}
}
// Test the validation of texture usages when creating textures in compressed texture formats. // Test the validation of texture usages when creating textures in compressed texture formats.
TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) { TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) {
// Test that only CopySrc, CopyDst and Sampled are accepted as the texture usage of the // Test that only CopySrc, CopyDst and Sampled are accepted as the texture usage of the

View File

@ -35,12 +35,29 @@ ValidationTest::ValidationTest() {
} }
ASSERT(foundNullAdapter); ASSERT(foundNullAdapter);
device = dawn::Device::Acquire(adapter.CreateDevice());
DawnProcTable procs = dawn_native::GetProcs(); DawnProcTable procs = dawn_native::GetProcs();
dawnSetProcs(&procs); dawnSetProcs(&procs);
device.SetErrorCallback(ValidationTest::OnDeviceError, this); device = CreateDeviceFromAdapter(adapter, std::vector<const char*>());
}
dawn::Device ValidationTest::CreateDeviceFromAdapter(
dawn_native::Adapter adapterToTest,
const std::vector<const char*>& requiredExtensions) {
dawn::Device deviceToTest;
// Always keep the code path to test creating a device without a device descriptor.
if (requiredExtensions.empty()) {
deviceToTest = dawn::Device::Acquire(adapterToTest.CreateDevice());
} else {
dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = requiredExtensions;
deviceToTest = dawn::Device::Acquire(adapterToTest.CreateDevice(&descriptor));
}
deviceToTest.SetErrorCallback(ValidationTest::OnDeviceError, this);
return deviceToTest;
} }
ValidationTest::~ValidationTest() { ValidationTest::~ValidationTest() {

View File

@ -29,6 +29,9 @@ class ValidationTest : public testing::Test {
ValidationTest(); ValidationTest();
~ValidationTest(); ~ValidationTest();
dawn::Device CreateDeviceFromAdapter(dawn_native::Adapter adapter,
const std::vector<const char*>& requiredExtensions);
void TearDown() override; void TearDown() override;
void StartExpectDeviceError(); void StartExpectDeviceError();