Emulate store and multisample resolve on Metal
This patch implements "store and MSAA resolve" store operation on Metal drivers that don't support MTLStoreActionStoreAndMultisampleResolve with a workaround that does MSAA resolve in another render pass. Driver workaround is one type of Dawn Toggles. Dawn Toggles will include other optional optimizations and features that can be configured to use or not when we create Dawn Devices. As all Metal try bots don't need this toggle, to better test this patch on the try bots: 1. We add the support of forcing enabling a workaround when starting an Dawn end2end test so that we can test the workaround on the platforms where the workaround is disabled. 2. We add an optional parameter DeviceDescriptor to CreateDevice() so that we can custom the toggles the Dawn device should use. This patch also adds the support of querying toggle details from Instance and the names of the toggles in use from Device. These APIs are tested in the Dawn unittests added in this patch. BUG=dawn:56 TEST=dawn_end2end_tests TEST=dawn_unittests Change-Id: Iae31d2ded6057eee638b6099d3061e9d78b04d55 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/6620 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
parent
8e97b4c8a5
commit
15d4c2e63b
2
BUILD.gn
2
BUILD.gn
|
@ -153,6 +153,7 @@ source_set("libdawn_native_sources") {
|
||||||
"src/dawn_native/Texture.cpp",
|
"src/dawn_native/Texture.cpp",
|
||||||
"src/dawn_native/Texture.h",
|
"src/dawn_native/Texture.h",
|
||||||
"src/dawn_native/ToBackend.h",
|
"src/dawn_native/ToBackend.h",
|
||||||
|
"src/dawn_native/Toggles.h",
|
||||||
"src/dawn_native/dawn_platform.h",
|
"src/dawn_native/dawn_platform.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -581,6 +582,7 @@ test("dawn_unittests") {
|
||||||
"src/tests/unittests/validation/ShaderModuleValidationTests.cpp",
|
"src/tests/unittests/validation/ShaderModuleValidationTests.cpp",
|
||||||
"src/tests/unittests/validation/TextureValidationTests.cpp",
|
"src/tests/unittests/validation/TextureValidationTests.cpp",
|
||||||
"src/tests/unittests/validation/TextureViewValidationTests.cpp",
|
"src/tests/unittests/validation/TextureViewValidationTests.cpp",
|
||||||
|
"src/tests/unittests/validation/ToggleValidationTests.cpp",
|
||||||
"src/tests/unittests/validation/ValidationTest.cpp",
|
"src/tests/unittests/validation/ValidationTest.cpp",
|
||||||
"src/tests/unittests/validation/ValidationTest.h",
|
"src/tests/unittests/validation/ValidationTest.h",
|
||||||
"src/tests/unittests/validation/VertexBufferValidationTests.cpp",
|
"src/tests/unittests/validation/VertexBufferValidationTests.cpp",
|
||||||
|
|
|
@ -38,20 +38,21 @@ namespace dawn_native {
|
||||||
return mInstance;
|
return mInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* AdapterBase::CreateDevice() {
|
DeviceBase* AdapterBase::CreateDevice(const DeviceDescriptor* descriptor) {
|
||||||
DeviceBase* result = nullptr;
|
DeviceBase* result = nullptr;
|
||||||
|
|
||||||
if (mInstance->ConsumedError(CreateDeviceInternal(&result))) {
|
if (mInstance->ConsumedError(CreateDeviceInternal(&result, descriptor))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result) {
|
MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result,
|
||||||
|
const DeviceDescriptor* descriptor) {
|
||||||
// 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());
|
DAWN_TRY_ASSIGN(*result, CreateDeviceImpl(descriptor));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,16 +33,16 @@ namespace dawn_native {
|
||||||
const PCIInfo& GetPCIInfo() const;
|
const PCIInfo& GetPCIInfo() const;
|
||||||
InstanceBase* GetInstance() const;
|
InstanceBase* GetInstance() const;
|
||||||
|
|
||||||
DeviceBase* CreateDevice();
|
DeviceBase* CreateDevice(const DeviceDescriptor* descriptor = nullptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PCIInfo mPCIInfo = {};
|
PCIInfo mPCIInfo = {};
|
||||||
DeviceType mDeviceType = DeviceType::Unknown;
|
DeviceType mDeviceType = DeviceType::Unknown;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ResultOrError<DeviceBase*> CreateDeviceImpl() = 0;
|
virtual ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) = 0;
|
||||||
|
|
||||||
MaybeError CreateDeviceInternal(DeviceBase** result);
|
MaybeError CreateDeviceInternal(DeviceBase** result, const DeviceDescriptor* descriptor);
|
||||||
|
|
||||||
InstanceBase* mInstance = nullptr;
|
InstanceBase* mInstance = nullptr;
|
||||||
BackendType mBackend;
|
BackendType mBackend;
|
||||||
|
|
|
@ -26,6 +26,12 @@ namespace dawn_native {
|
||||||
return GetProcsAutogen();
|
return GetProcsAutogen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<const char*> GetTogglesUsed(DawnDevice device) {
|
||||||
|
const dawn_native::DeviceBase* deviceBase =
|
||||||
|
reinterpret_cast<const dawn_native::DeviceBase*>(device);
|
||||||
|
return deviceBase->GetTogglesUsed();
|
||||||
|
}
|
||||||
|
|
||||||
// Adapter
|
// Adapter
|
||||||
|
|
||||||
Adapter::Adapter() = default;
|
Adapter::Adapter() = default;
|
||||||
|
@ -53,8 +59,8 @@ namespace dawn_native {
|
||||||
return mImpl != nullptr;
|
return mImpl != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DawnDevice Adapter::CreateDevice() {
|
DawnDevice Adapter::CreateDevice(const DeviceDescriptor* deviceDescriptor) {
|
||||||
return reinterpret_cast<DawnDevice>(mImpl->CreateDevice());
|
return reinterpret_cast<DawnDevice>(mImpl->CreateDevice(deviceDescriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdapterDiscoverOptionsBase
|
// AdapterDiscoverOptionsBase
|
||||||
|
@ -89,4 +95,8 @@ namespace dawn_native {
|
||||||
return adapters;
|
return adapters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ToggleInfo* Instance::GetToggleInfo(const char* toggleName) {
|
||||||
|
return mImpl->GetToggleInfo(toggleName);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "dawn_native/ErrorData.h"
|
#include "dawn_native/ErrorData.h"
|
||||||
#include "dawn_native/Fence.h"
|
#include "dawn_native/Fence.h"
|
||||||
#include "dawn_native/FenceSignalTracker.h"
|
#include "dawn_native/FenceSignalTracker.h"
|
||||||
|
#include "dawn_native/Instance.h"
|
||||||
#include "dawn_native/PipelineLayout.h"
|
#include "dawn_native/PipelineLayout.h"
|
||||||
#include "dawn_native/Queue.h"
|
#include "dawn_native/Queue.h"
|
||||||
#include "dawn_native/RenderPipeline.h"
|
#include "dawn_native/RenderPipeline.h"
|
||||||
|
@ -50,7 +51,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
// DeviceBase
|
// DeviceBase
|
||||||
|
|
||||||
DeviceBase::DeviceBase(AdapterBase* adapter) : mAdapter(adapter) {
|
DeviceBase::DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor)
|
||||||
|
: mAdapter(adapter) {
|
||||||
mCaches = std::make_unique<DeviceBase::Caches>();
|
mCaches = std::make_unique<DeviceBase::Caches>();
|
||||||
mFenceSignalTracker = std::make_unique<FenceSignalTracker>(this);
|
mFenceSignalTracker = std::make_unique<FenceSignalTracker>(this);
|
||||||
mDynamicUploader = std::make_unique<DynamicUploader>(this);
|
mDynamicUploader = std::make_unique<DynamicUploader>(this);
|
||||||
|
@ -257,6 +259,42 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceBase::ApplyToggleOverrides(const DeviceDescriptor* deviceDescriptor) {
|
||||||
|
ASSERT(deviceDescriptor);
|
||||||
|
|
||||||
|
for (const char* toggleName : deviceDescriptor->forceEnabledToggles) {
|
||||||
|
Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName);
|
||||||
|
if (toggle != Toggle::InvalidEnum) {
|
||||||
|
mTogglesSet.SetToggle(toggle, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const char* toggleName : deviceDescriptor->forceDisabledToggles) {
|
||||||
|
Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName);
|
||||||
|
if (toggle != Toggle::InvalidEnum) {
|
||||||
|
mTogglesSet.SetToggle(toggle, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const char*> DeviceBase::GetTogglesUsed() const {
|
||||||
|
std::vector<const char*> togglesNameInUse(mTogglesSet.toggleBitset.count());
|
||||||
|
|
||||||
|
uint32_t index = 0;
|
||||||
|
for (uint32_t i : IterateBitSet(mTogglesSet.toggleBitset)) {
|
||||||
|
const char* toggleName =
|
||||||
|
GetAdapter()->GetInstance()->ToggleEnumToName(static_cast<Toggle>(i));
|
||||||
|
togglesNameInUse[index] = toggleName;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return togglesNameInUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeviceBase::IsToggleEnabled(Toggle toggle) const {
|
||||||
|
return mTogglesSet.IsEnabled(toggle);
|
||||||
|
}
|
||||||
|
|
||||||
// Implementation details of object creation
|
// Implementation details of object creation
|
||||||
|
|
||||||
MaybeError DeviceBase::CreateBindGroupInternal(BindGroupBase** result,
|
MaybeError DeviceBase::CreateBindGroupInternal(BindGroupBase** result,
|
||||||
|
@ -361,4 +399,8 @@ namespace dawn_native {
|
||||||
return mDynamicUploader.get();
|
return mDynamicUploader.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceBase::SetToggle(Toggle toggle, bool isEnabled) {
|
||||||
|
mTogglesSet.SetToggle(toggle, isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "dawn_native/Error.h"
|
#include "dawn_native/Error.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/DawnNative.h"
|
#include "dawn_native/DawnNative.h"
|
||||||
#include "dawn_native/dawn_platform.h"
|
#include "dawn_native/dawn_platform.h"
|
||||||
|
@ -36,7 +37,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
class DeviceBase {
|
class DeviceBase {
|
||||||
public:
|
public:
|
||||||
DeviceBase(AdapterBase* adapter);
|
DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor);
|
||||||
virtual ~DeviceBase();
|
virtual ~DeviceBase();
|
||||||
|
|
||||||
void HandleError(const char* message);
|
void HandleError(const char* message);
|
||||||
|
@ -115,7 +116,13 @@ namespace dawn_native {
|
||||||
|
|
||||||
ResultOrError<DynamicUploader*> GetDynamicUploader() const;
|
ResultOrError<DynamicUploader*> GetDynamicUploader() const;
|
||||||
|
|
||||||
|
std::vector<const char*> GetTogglesUsed() const;
|
||||||
|
bool IsToggleEnabled(Toggle toggle) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void SetToggle(Toggle toggle, bool isEnabled);
|
||||||
|
void ApplyToggleOverrides(const DeviceDescriptor* deviceDescriptor);
|
||||||
|
|
||||||
std::unique_ptr<DynamicUploader> mDynamicUploader;
|
std::unique_ptr<DynamicUploader> mDynamicUploader;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -179,6 +186,8 @@ namespace dawn_native {
|
||||||
dawn::DeviceErrorCallback mErrorCallback = nullptr;
|
dawn::DeviceErrorCallback mErrorCallback = nullptr;
|
||||||
dawn::CallbackUserdata mErrorUserdata = 0;
|
dawn::CallbackUserdata mErrorUserdata = 0;
|
||||||
uint32_t mRefCount = 1;
|
uint32_t mRefCount = 1;
|
||||||
|
|
||||||
|
TogglesSet mTogglesSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -49,6 +49,28 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
|
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct ToggleEnumAndInfo {
|
||||||
|
Toggle toggle;
|
||||||
|
ToggleInfo info;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ToggleEnumAndInfoList =
|
||||||
|
std::array<ToggleEnumAndInfo, static_cast<size_t>(Toggle::EnumCount)>;
|
||||||
|
|
||||||
|
static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {
|
||||||
|
{{Toggle::EmulateStoreAndMSAAResolve,
|
||||||
|
{"emulate_store_and_msaa_resolve",
|
||||||
|
"Emulate storing into multisampled color attachments and doing MSAA resolve "
|
||||||
|
"simultaneously. This workaround is enabled by default on the Metal drivers that do "
|
||||||
|
"not support MTLStoreActionStoreAndMultisampleResolve. To support StoreOp::Store on "
|
||||||
|
"those platforms, we should do MSAA resolve in another render pass after ending the "
|
||||||
|
"previous one.",
|
||||||
|
"https://bugs.chromium.org/p/dawn/issues/detail?id=56"}}}};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
// InstanceBase
|
// InstanceBase
|
||||||
|
|
||||||
void InstanceBase::DiscoverDefaultAdapters() {
|
void InstanceBase::DiscoverDefaultAdapters() {
|
||||||
|
@ -78,6 +100,53 @@ namespace dawn_native {
|
||||||
return !ConsumedError(DiscoverAdaptersInternal(options));
|
return !ConsumedError(DiscoverAdaptersInternal(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* InstanceBase::ToggleEnumToName(Toggle toggle) {
|
||||||
|
ASSERT(toggle != Toggle::InvalidEnum);
|
||||||
|
|
||||||
|
const ToggleEnumAndInfo& toggleNameAndInfo =
|
||||||
|
kToggleNameAndInfoList[static_cast<size_t>(toggle)];
|
||||||
|
ASSERT(toggleNameAndInfo.toggle == toggle);
|
||||||
|
return toggleNameAndInfo.info.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ToggleInfo* InstanceBase::GetToggleInfo(const char* toggleName) {
|
||||||
|
ASSERT(toggleName);
|
||||||
|
|
||||||
|
EnsureToggleNameToEnumMapInitialized();
|
||||||
|
|
||||||
|
const auto& iter = mToggleNameToEnumMap.find(toggleName);
|
||||||
|
if (iter != mToggleNameToEnumMap.cend()) {
|
||||||
|
return &kToggleNameAndInfoList[static_cast<size_t>(iter->second)].info;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toggle InstanceBase::ToggleNameToEnum(const char* toggleName) {
|
||||||
|
ASSERT(toggleName);
|
||||||
|
|
||||||
|
EnsureToggleNameToEnumMapInitialized();
|
||||||
|
|
||||||
|
const auto& iter = mToggleNameToEnumMap.find(toggleName);
|
||||||
|
if (iter != mToggleNameToEnumMap.cend()) {
|
||||||
|
return kToggleNameAndInfoList[static_cast<size_t>(iter->second)].toggle;
|
||||||
|
}
|
||||||
|
return Toggle::InvalidEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceBase::EnsureToggleNameToEnumMapInitialized() {
|
||||||
|
if (mToggleNameToEnumMapInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t index = 0; index < kToggleNameAndInfoList.size(); ++index) {
|
||||||
|
const ToggleEnumAndInfo& toggleNameAndInfo = kToggleNameAndInfoList[index];
|
||||||
|
ASSERT(index == static_cast<size_t>(toggleNameAndInfo.toggle));
|
||||||
|
mToggleNameToEnumMap[toggleNameAndInfo.info.name] = toggleNameAndInfo.toggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
mToggleNameToEnumMapInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const {
|
const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const {
|
||||||
return mAdapters;
|
return mAdapters;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,11 @@
|
||||||
|
|
||||||
#include "dawn_native/Adapter.h"
|
#include "dawn_native/Adapter.h"
|
||||||
#include "dawn_native/BackendConnection.h"
|
#include "dawn_native/BackendConnection.h"
|
||||||
|
#include "dawn_native/Toggles.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
@ -41,19 +44,33 @@ namespace dawn_native {
|
||||||
// Used to handle error that happen up to device creation.
|
// Used to handle error that happen up to device creation.
|
||||||
bool ConsumedError(MaybeError maybeError);
|
bool ConsumedError(MaybeError maybeError);
|
||||||
|
|
||||||
|
// Used to query the details of a toggle. Return nullptr if toggleName is not a valid name
|
||||||
|
// of a toggle supported in Dawn.
|
||||||
|
const ToggleInfo* GetToggleInfo(const char* toggleName);
|
||||||
|
|
||||||
|
Toggle ToggleNameToEnum(const char* toggleName);
|
||||||
|
const char* ToggleEnumToName(Toggle toggle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Lazily creates connections to all backends that have been compiled.
|
// Lazily creates connections to all backends that have been compiled.
|
||||||
void EnsureBackendConnections();
|
void EnsureBackendConnections();
|
||||||
|
|
||||||
// Finds the BackendConnection for `type` or returns an error.
|
// Finds the BackendConnection for `type` or returns an error.
|
||||||
ResultOrError<BackendConnection*> FindBackend(BackendType type);
|
ResultOrError<BackendConnection*> FindBackend(BackendType type);
|
||||||
|
|
||||||
MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options);
|
MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options);
|
||||||
|
|
||||||
|
void EnsureToggleNameToEnumMapInitialized();
|
||||||
|
|
||||||
bool mBackendsConnected = false;
|
bool mBackendsConnected = false;
|
||||||
bool mDiscoveredDefaultAdapters = false;
|
bool mDiscoveredDefaultAdapters = false;
|
||||||
|
|
||||||
|
bool mToggleNameToEnumMapInitialized = false;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, Toggle> mToggleNameToEnumMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
// 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_TOGGLES_H_
|
||||||
|
#define DAWNNATIVE_TOGGLES_H_
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
#include "dawn_native/DawnNative.h"
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
enum class Toggle {
|
||||||
|
EmulateStoreAndMSAAResolve = 0,
|
||||||
|
|
||||||
|
EnumCount = 1,
|
||||||
|
InvalidEnum = EnumCount,
|
||||||
|
};
|
||||||
|
|
||||||
|
// A wrapper of the bitset to store if a toggle is enabled or not. This wrapper provides the
|
||||||
|
// convenience to convert the enums of enum class Toggle to the indices of a bitset.
|
||||||
|
struct TogglesSet {
|
||||||
|
std::bitset<static_cast<size_t>(Toggle::EnumCount)> toggleBitset;
|
||||||
|
|
||||||
|
void SetToggle(Toggle toggle, bool enabled) {
|
||||||
|
ASSERT(toggle != Toggle::InvalidEnum);
|
||||||
|
const size_t toggleIndex = static_cast<size_t>(toggle);
|
||||||
|
toggleBitset.set(toggleIndex, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEnabled(Toggle toggle) const {
|
||||||
|
ASSERT(toggle != Toggle::InvalidEnum);
|
||||||
|
const size_t toggleIndex = static_cast<size_t>(toggle);
|
||||||
|
return toggleBitset.test(toggleIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // DAWNNATIVE_TOGGLES_H_
|
|
@ -59,7 +59,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
return mBackend;
|
return mBackend;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl() {
|
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
|
||||||
ComPtr<ID3D12Device> d3d12Device;
|
ComPtr<ID3D12Device> d3d12Device;
|
||||||
if (FAILED(mBackend->GetFunctions()->d3d12CreateDevice(
|
if (FAILED(mBackend->GetFunctions()->d3d12CreateDevice(
|
||||||
mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3d12Device)))) {
|
mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3d12Device)))) {
|
||||||
|
@ -67,7 +67,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(d3d12Device != nullptr);
|
ASSERT(d3d12Device != nullptr);
|
||||||
return new Device(this, d3d12Device);
|
return new Device(this, d3d12Device, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace dawn_native::d3d12
|
}} // namespace dawn_native::d3d12
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
Backend* GetBackend() const;
|
Backend* GetBackend() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResultOrError<DeviceBase*> CreateDeviceImpl() override;
|
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
|
||||||
|
|
||||||
ComPtr<IDXGIAdapter1> mHardwareAdapter;
|
ComPtr<IDXGIAdapter1> mHardwareAdapter;
|
||||||
Backend* mBackend;
|
Backend* mBackend;
|
||||||
|
|
|
@ -43,8 +43,10 @@ namespace dawn_native { namespace d3d12 {
|
||||||
ASSERT(SUCCEEDED(hr));
|
ASSERT(SUCCEEDED(hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(Adapter* adapter, ComPtr<ID3D12Device> d3d12Device)
|
Device::Device(Adapter* adapter,
|
||||||
: DeviceBase(adapter), mD3d12Device(d3d12Device) {
|
ComPtr<ID3D12Device> d3d12Device,
|
||||||
|
const DeviceDescriptor* descriptor)
|
||||||
|
: DeviceBase(adapter, descriptor), mD3d12Device(d3d12Device) {
|
||||||
// Create device-global objects
|
// Create device-global objects
|
||||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||||
|
|
|
@ -37,7 +37,9 @@ namespace dawn_native { namespace d3d12 {
|
||||||
// Definition of backend types
|
// Definition of backend types
|
||||||
class Device : public DeviceBase {
|
class Device : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
Device(Adapter* adapter, ComPtr<ID3D12Device> d3d12Device);
|
Device(Adapter* adapter,
|
||||||
|
ComPtr<ID3D12Device> d3d12Device,
|
||||||
|
const DeviceDescriptor* descriptor);
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override;
|
CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override;
|
||||||
|
|
|
@ -142,8 +142,8 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResultOrError<DeviceBase*> CreateDeviceImpl() override {
|
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
|
||||||
return {new Device(this, mDevice)};
|
return {new Device(this, mDevice, descriptor)};
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLDevice> mDevice = nil;
|
id<MTLDevice> mDevice = nil;
|
||||||
|
|
|
@ -47,7 +47,9 @@ namespace dawn_native { namespace metal {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates an autoreleased MTLRenderPassDescriptor matching desc
|
// Creates an autoreleased MTLRenderPassDescriptor matching desc
|
||||||
MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(BeginRenderPassCmd* renderPass) {
|
MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(
|
||||||
|
BeginRenderPassCmd* renderPass,
|
||||||
|
bool shouldEmulateStoreAndMSAAResolve) {
|
||||||
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
|
||||||
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
|
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
|
||||||
|
@ -67,10 +69,9 @@ namespace dawn_native { namespace metal {
|
||||||
descriptor.colorAttachments[i].level = attachmentInfo.view->GetBaseMipLevel();
|
descriptor.colorAttachments[i].level = attachmentInfo.view->GetBaseMipLevel();
|
||||||
descriptor.colorAttachments[i].slice = attachmentInfo.view->GetBaseArrayLayer();
|
descriptor.colorAttachments[i].slice = attachmentInfo.view->GetBaseArrayLayer();
|
||||||
|
|
||||||
ASSERT(attachmentInfo.storeOp == dawn::StoreOp::Store);
|
if (attachmentInfo.storeOp == dawn::StoreOp::Store) {
|
||||||
// TODO(jiawei.shao@intel.com): emulate MTLStoreActionStoreAndMultisampleResolve on
|
if (attachmentInfo.resolveTarget.Get() != nullptr &&
|
||||||
// the platforms that do not support this store action.
|
!shouldEmulateStoreAndMSAAResolve) {
|
||||||
if (attachmentInfo.resolveTarget.Get() != nullptr) {
|
|
||||||
descriptor.colorAttachments[i].resolveTexture =
|
descriptor.colorAttachments[i].resolveTexture =
|
||||||
ToBackend(attachmentInfo.resolveTarget->GetTexture())->GetMTLTexture();
|
ToBackend(attachmentInfo.resolveTarget->GetTexture())->GetMTLTexture();
|
||||||
descriptor.colorAttachments[i].resolveLevel =
|
descriptor.colorAttachments[i].resolveLevel =
|
||||||
|
@ -83,6 +84,7 @@ namespace dawn_native { namespace metal {
|
||||||
descriptor.colorAttachments[i].storeAction = MTLStoreActionStore;
|
descriptor.colorAttachments[i].storeAction = MTLStoreActionStore;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (renderPass->hasDepthStencilAttachment) {
|
if (renderPass->hasDepthStencilAttachment) {
|
||||||
auto& attachmentInfo = renderPass->depthStencilAttachment;
|
auto& attachmentInfo = renderPass->depthStencilAttachment;
|
||||||
|
@ -120,6 +122,43 @@ namespace dawn_native { namespace metal {
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do MSAA resolve in another render pass.
|
||||||
|
void ResolveInAnotherRenderPass(id<MTLCommandBuffer> commandBuffer,
|
||||||
|
BeginRenderPassCmd* renderPass) {
|
||||||
|
ASSERT(renderPass->sampleCount > 1);
|
||||||
|
MTLRenderPassDescriptor* renderPassForResolve = nil;
|
||||||
|
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
|
||||||
|
auto& attachmentInfo = renderPass->colorAttachments[i];
|
||||||
|
if (attachmentInfo.resolveTarget.Get() == nil ||
|
||||||
|
attachmentInfo.storeOp != dawn::StoreOp::Store) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderPassForResolve == nil) {
|
||||||
|
renderPassForResolve = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
}
|
||||||
|
renderPassForResolve.colorAttachments[i].texture =
|
||||||
|
ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture();
|
||||||
|
renderPassForResolve.colorAttachments[i].level = 0;
|
||||||
|
renderPassForResolve.colorAttachments[i].slice = 0;
|
||||||
|
|
||||||
|
renderPassForResolve.colorAttachments[i].storeAction =
|
||||||
|
MTLStoreActionMultisampleResolve;
|
||||||
|
renderPassForResolve.colorAttachments[i].resolveTexture =
|
||||||
|
ToBackend(attachmentInfo.resolveTarget->GetTexture())->GetMTLTexture();
|
||||||
|
renderPassForResolve.colorAttachments[i].resolveLevel =
|
||||||
|
attachmentInfo.resolveTarget->GetBaseMipLevel();
|
||||||
|
renderPassForResolve.colorAttachments[i].resolveSlice =
|
||||||
|
attachmentInfo.resolveTarget->GetBaseArrayLayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderPassForResolve != nil) {
|
||||||
|
id<MTLRenderCommandEncoder> encoder =
|
||||||
|
[commandBuffer renderCommandEncoderWithDescriptor:renderPassForResolve];
|
||||||
|
[encoder endEncoding];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handles a call to SetBindGroup, directing the commands to the correct encoder.
|
// Handles a call to SetBindGroup, directing the commands to the correct encoder.
|
||||||
// There is a single function that takes both encoders to factor code. Other approaches like
|
// There is a single function that takes both encoders to factor code. Other approaches like
|
||||||
// templates wouldn't work because the name of methods are different between the two encoder
|
// templates wouldn't work because the name of methods are different between the two encoder
|
||||||
|
@ -599,9 +638,13 @@ namespace dawn_native { namespace metal {
|
||||||
std::array<uint32_t, kMaxPushConstants> vertexPushConstants;
|
std::array<uint32_t, kMaxPushConstants> vertexPushConstants;
|
||||||
std::array<uint32_t, kMaxPushConstants> fragmentPushConstants;
|
std::array<uint32_t, kMaxPushConstants> fragmentPushConstants;
|
||||||
|
|
||||||
|
bool shouldEmulateStoreAndMSAAResolve =
|
||||||
|
GetDevice()->IsToggleEnabled(Toggle::EmulateStoreAndMSAAResolve);
|
||||||
// This will be autoreleased
|
// This will be autoreleased
|
||||||
id<MTLRenderCommandEncoder> encoder = [commandBuffer
|
id<MTLRenderCommandEncoder> encoder = [commandBuffer
|
||||||
renderCommandEncoderWithDescriptor:CreateMTLRenderPassDescriptor(renderPassCmd)];
|
renderCommandEncoderWithDescriptor:CreateMTLRenderPassDescriptor(
|
||||||
|
renderPassCmd,
|
||||||
|
shouldEmulateStoreAndMSAAResolve)];
|
||||||
|
|
||||||
// Set default values for push constants
|
// Set default values for push constants
|
||||||
vertexPushConstants.fill(0);
|
vertexPushConstants.fill(0);
|
||||||
|
@ -620,6 +663,9 @@ namespace dawn_native { namespace metal {
|
||||||
case Command::EndRenderPass: {
|
case Command::EndRenderPass: {
|
||||||
mCommands.NextCommand<EndRenderPassCmd>();
|
mCommands.NextCommand<EndRenderPassCmd>();
|
||||||
[encoder endEncoding];
|
[encoder endEncoding];
|
||||||
|
if (renderPassCmd->sampleCount > 1 && shouldEmulateStoreAndMSAAResolve) {
|
||||||
|
ResolveInAnotherRenderPass(commandBuffer, renderPassCmd);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
class Device : public DeviceBase {
|
class Device : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
Device(AdapterBase* adapter, id<MTLDevice> mtlDevice);
|
Device(AdapterBase* adapter, id<MTLDevice> mtlDevice, const DeviceDescriptor* descriptor);
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override;
|
CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override;
|
||||||
|
@ -86,6 +86,8 @@ namespace dawn_native { namespace metal {
|
||||||
TextureBase* texture,
|
TextureBase* texture,
|
||||||
const TextureViewDescriptor* descriptor) override;
|
const TextureViewDescriptor* descriptor) override;
|
||||||
|
|
||||||
|
void InitTogglesFromDriver();
|
||||||
|
|
||||||
id<MTLDevice> mMtlDevice = nil;
|
id<MTLDevice> mMtlDevice = nil;
|
||||||
id<MTLCommandQueue> mCommandQueue = nil;
|
id<MTLCommandQueue> mCommandQueue = nil;
|
||||||
std::unique_ptr<MapRequestTracker> mMapTracker;
|
std::unique_ptr<MapRequestTracker> mMapTracker;
|
||||||
|
|
|
@ -34,13 +34,20 @@
|
||||||
|
|
||||||
namespace dawn_native { namespace metal {
|
namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
Device::Device(AdapterBase* adapter, id<MTLDevice> mtlDevice)
|
Device::Device(AdapterBase* adapter,
|
||||||
: DeviceBase(adapter),
|
id<MTLDevice> mtlDevice,
|
||||||
|
const DeviceDescriptor* descriptor)
|
||||||
|
: DeviceBase(adapter, descriptor),
|
||||||
mMtlDevice([mtlDevice retain]),
|
mMtlDevice([mtlDevice retain]),
|
||||||
mMapTracker(new MapRequestTracker(this)),
|
mMapTracker(new MapRequestTracker(this)),
|
||||||
mCompletedSerial(0) {
|
mCompletedSerial(0) {
|
||||||
[mMtlDevice retain];
|
[mMtlDevice retain];
|
||||||
mCommandQueue = [mMtlDevice newCommandQueue];
|
mCommandQueue = [mMtlDevice newCommandQueue];
|
||||||
|
|
||||||
|
InitTogglesFromDriver();
|
||||||
|
if (descriptor != nil) {
|
||||||
|
ApplyToggleOverrides(descriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
|
@ -67,6 +74,13 @@ namespace dawn_native { namespace metal {
|
||||||
mMtlDevice = nil;
|
mMtlDevice = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device::InitTogglesFromDriver() {
|
||||||
|
// TODO(jiawei.shao@intel.com): check iOS feature sets
|
||||||
|
bool emulateStoreAndMSAAResolve =
|
||||||
|
![mMtlDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2];
|
||||||
|
SetToggle(Toggle::EmulateStoreAndMSAAResolve, emulateStoreAndMSAAResolve);
|
||||||
|
}
|
||||||
|
|
||||||
ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl(
|
ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl(
|
||||||
const BindGroupDescriptor* descriptor) {
|
const BindGroupDescriptor* descriptor) {
|
||||||
return new BindGroup(this, descriptor);
|
return new BindGroup(this, descriptor);
|
||||||
|
|
|
@ -33,8 +33,8 @@ namespace dawn_native { namespace null {
|
||||||
virtual ~Adapter() = default;
|
virtual ~Adapter() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResultOrError<DeviceBase*> CreateDeviceImpl() override {
|
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
|
||||||
return {new Device(this)};
|
return {new Device(this, descriptor)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,7 +58,12 @@ namespace dawn_native { namespace null {
|
||||||
|
|
||||||
// Device
|
// Device
|
||||||
|
|
||||||
Device::Device(Adapter* adapter) : DeviceBase(adapter) {
|
Device::Device(Adapter* adapter, const DeviceDescriptor* descriptor)
|
||||||
|
: DeviceBase(adapter, descriptor) {
|
||||||
|
// Apply toggle overrides if necessary for test
|
||||||
|
if (descriptor != nullptr) {
|
||||||
|
ApplyToggleOverrides(descriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace dawn_native { namespace null {
|
||||||
|
|
||||||
class Device : public DeviceBase {
|
class Device : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
Device(Adapter* adapter);
|
Device(Adapter* adapter, const DeviceDescriptor* descriptor);
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override;
|
CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override;
|
||||||
|
|
|
@ -39,10 +39,10 @@ namespace dawn_native { namespace opengl {
|
||||||
virtual ~Adapter() = default;
|
virtual ~Adapter() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResultOrError<DeviceBase*> CreateDeviceImpl() override {
|
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
|
||||||
// There is no limit on the number of devices created from this adapter because they can
|
// There is no limit on the number of devices created from this adapter because they can
|
||||||
// all share the same backing OpenGL context.
|
// all share the same backing OpenGL context.
|
||||||
return {new Device(this)};
|
return {new Device(this, descriptor)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
|
|
||||||
namespace dawn_native { namespace opengl {
|
namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
Device::Device(AdapterBase* adapter) : DeviceBase(adapter) {
|
Device::Device(AdapterBase* adapter, const DeviceDescriptor* descriptor)
|
||||||
|
: DeviceBase(adapter, descriptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
class Device : public DeviceBase {
|
class Device : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
Device(AdapterBase* adapter);
|
Device(AdapterBase* adapter, const DeviceDescriptor* descriptor);
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
void SubmitFenceSync();
|
void SubmitFenceSync();
|
||||||
|
|
|
@ -62,8 +62,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl() {
|
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
|
||||||
std::unique_ptr<Device> device = std::make_unique<Device>(this);
|
std::unique_ptr<Device> device = std::make_unique<Device>(this, descriptor);
|
||||||
DAWN_TRY(device->Initialize());
|
DAWN_TRY(device->Initialize());
|
||||||
return device.release();
|
return device.release();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
MaybeError Initialize();
|
MaybeError Initialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResultOrError<DeviceBase*> CreateDeviceImpl() override;
|
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
|
||||||
|
|
||||||
VkPhysicalDevice mPhysicalDevice;
|
VkPhysicalDevice mPhysicalDevice;
|
||||||
Backend* mBackend;
|
Backend* mBackend;
|
||||||
|
|
|
@ -40,7 +40,8 @@
|
||||||
|
|
||||||
namespace dawn_native { namespace vulkan {
|
namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
Device::Device(Adapter* adapter) : DeviceBase(adapter) {
|
Device::Device(Adapter* adapter, const DeviceDescriptor* descriptor)
|
||||||
|
: DeviceBase(adapter, descriptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::Initialize() {
|
MaybeError Device::Initialize() {
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
class Device : public DeviceBase {
|
class Device : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
Device(Adapter* adapter);
|
Device(Adapter* adapter, const DeviceDescriptor* descriptor);
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
MaybeError Initialize();
|
MaybeError Initialize();
|
||||||
|
|
|
@ -47,6 +47,22 @@ namespace dawn_native {
|
||||||
class InstanceBase;
|
class InstanceBase;
|
||||||
class AdapterBase;
|
class AdapterBase;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
struct DAWN_NATIVE_EXPORT DeviceDescriptor {
|
||||||
|
std::vector<const char*> forceEnabledToggles;
|
||||||
|
std::vector<const char*> forceDisabledToggles;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A struct to record the information of a toggle. A toggle is a code path in Dawn device that
|
||||||
|
// can be manually configured to run or not outside Dawn, including workarounds, special
|
||||||
|
// features and optimizations.
|
||||||
|
struct ToggleInfo {
|
||||||
|
const char* name;
|
||||||
|
const char* description;
|
||||||
|
const char* url;
|
||||||
|
};
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -68,7 +84,7 @@ namespace dawn_native {
|
||||||
// Create a device on this adapter, note that the interface will change to include at least
|
// Create a device on this adapter, note that the interface will change to include at least
|
||||||
// a device descriptor and a pointer to backend specific options.
|
// a device descriptor and a pointer to backend specific options.
|
||||||
// On an error, nullptr is returned.
|
// On an error, nullptr is returned.
|
||||||
DawnDevice CreateDevice();
|
DawnDevice CreateDevice(const DeviceDescriptor* deviceDescriptor = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AdapterBase* mImpl = nullptr;
|
AdapterBase* mImpl = nullptr;
|
||||||
|
@ -107,6 +123,8 @@ namespace dawn_native {
|
||||||
// Returns all the adapters that the instance knows about.
|
// Returns all the adapters that the instance knows about.
|
||||||
std::vector<Adapter> GetAdapters() const;
|
std::vector<Adapter> GetAdapters() const;
|
||||||
|
|
||||||
|
const ToggleInfo* GetToggleInfo(const char* toggleName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InstanceBase* mImpl = nullptr;
|
InstanceBase* mImpl = nullptr;
|
||||||
};
|
};
|
||||||
|
@ -114,6 +132,9 @@ namespace dawn_native {
|
||||||
// Backend-agnostic API for dawn_native
|
// Backend-agnostic API for dawn_native
|
||||||
DAWN_NATIVE_EXPORT DawnProcTable GetProcs();
|
DAWN_NATIVE_EXPORT DawnProcTable GetProcs();
|
||||||
|
|
||||||
|
// Query the names of all the toggles that are enabled in device
|
||||||
|
DAWN_NATIVE_EXPORT std::vector<const char*> GetTogglesUsed(DawnDevice device);
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
||||||
#endif // DAWNNATIVE_DAWNNATIVE_H_
|
#endif // DAWNNATIVE_DAWNNATIVE_H_
|
||||||
|
|
|
@ -67,6 +67,12 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dawn_native::DeviceDescriptor InitWorkaround(const char* forceEnabledWorkaround) {
|
||||||
|
dawn_native::DeviceDescriptor deviceDescriptor;
|
||||||
|
deviceDescriptor.forceEnabledToggles.push_back(forceEnabledWorkaround);
|
||||||
|
return deviceDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
struct MapReadUserdata {
|
struct MapReadUserdata {
|
||||||
DawnTest* test;
|
DawnTest* test;
|
||||||
size_t slot;
|
size_t slot;
|
||||||
|
@ -83,6 +89,12 @@ namespace {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
DawnTestParam ForceWorkaround(const DawnTestParam& originParam, const char* workaround) {
|
||||||
|
DawnTestParam newTestParam = originParam;
|
||||||
|
newTestParam.forceEnabledWorkaround = workaround;
|
||||||
|
return newTestParam;
|
||||||
|
}
|
||||||
|
|
||||||
// Implementation of DawnTestEnvironment
|
// Implementation of DawnTestEnvironment
|
||||||
|
|
||||||
void InitDawnEnd2EndTestEnvironment(int argc, char** argv) {
|
void InitDawnEnd2EndTestEnvironment(int argc, char** argv) {
|
||||||
|
@ -112,10 +124,10 @@ void DawnTestEnvironment::SetUp() {
|
||||||
mInstance = std::make_unique<dawn_native::Instance>();
|
mInstance = std::make_unique<dawn_native::Instance>();
|
||||||
|
|
||||||
static constexpr dawn_native::BackendType kAllBackends[] = {
|
static constexpr dawn_native::BackendType kAllBackends[] = {
|
||||||
D3D12Backend,
|
dawn_native::BackendType::D3D12,
|
||||||
MetalBackend,
|
dawn_native::BackendType::Metal,
|
||||||
OpenGLBackend,
|
dawn_native::BackendType::OpenGL,
|
||||||
VulkanBackend,
|
dawn_native::BackendType::Vulkan,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a test window for each backend and discover an adapter using it.
|
// Create a test window for each backend and discover an adapter using it.
|
||||||
|
@ -191,19 +203,19 @@ DawnTest::~DawnTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DawnTest::IsD3D12() const {
|
bool DawnTest::IsD3D12() const {
|
||||||
return GetParam() == D3D12Backend;
|
return GetParam().backendType == dawn_native::BackendType::D3D12;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DawnTest::IsMetal() const {
|
bool DawnTest::IsMetal() const {
|
||||||
return GetParam() == MetalBackend;
|
return GetParam().backendType == dawn_native::BackendType::Metal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DawnTest::IsOpenGL() const {
|
bool DawnTest::IsOpenGL() const {
|
||||||
return GetParam() == OpenGLBackend;
|
return GetParam().backendType == dawn_native::BackendType::OpenGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DawnTest::IsVulkan() const {
|
bool DawnTest::IsVulkan() const {
|
||||||
return GetParam() == VulkanBackend;
|
return GetParam().backendType == dawn_native::BackendType::Vulkan;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DawnTest::IsAMD() const {
|
bool DawnTest::IsAMD() const {
|
||||||
|
@ -257,19 +269,20 @@ bool DawnTest::IsMacOS() const {
|
||||||
void DawnTest::SetUp() {
|
void DawnTest::SetUp() {
|
||||||
// Get an adapter for the backend to use, and create the device.
|
// Get an adapter for the backend to use, and create the device.
|
||||||
dawn_native::Adapter backendAdapter;
|
dawn_native::Adapter backendAdapter;
|
||||||
|
const dawn_native::BackendType backendType = GetParam().backendType;
|
||||||
{
|
{
|
||||||
dawn_native::Instance* instance = gTestEnv->GetInstance();
|
dawn_native::Instance* instance = gTestEnv->GetInstance();
|
||||||
std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
|
std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
|
||||||
|
|
||||||
for (const dawn_native::Adapter& adapter : adapters) {
|
for (const dawn_native::Adapter& adapter : adapters) {
|
||||||
if (adapter.GetBackendType() == GetParam()) {
|
if (adapter.GetBackendType() == backendType) {
|
||||||
backendAdapter = adapter;
|
backendAdapter = 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.
|
||||||
// TODO(cwallez@chromium.org): Replace this with command line arguments requesting
|
// TODO(cwallez@chromium.org): Replace this with command line arguments requesting
|
||||||
// a specific device / vendor ID once the macOS 10.13 SDK is rolled and correct
|
// a specific device / vendor ID once the macOS 10.13 SDK is rolled and correct
|
||||||
// PCI info collection is implemented on Metal.
|
// PCI info collection is implemented on Metal.
|
||||||
if (GetParam() != MetalBackend) {
|
if (backendType != dawn_native::BackendType::Metal) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,13 +292,22 @@ void DawnTest::SetUp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
mPCIInfo = backendAdapter.GetPCIInfo();
|
mPCIInfo = backendAdapter.GetPCIInfo();
|
||||||
DawnDevice backendDevice = backendAdapter.CreateDevice();
|
|
||||||
|
DawnDevice backendDevice;
|
||||||
|
const char* forceEnabledWorkaround = GetParam().forceEnabledWorkaround;
|
||||||
|
if (forceEnabledWorkaround != nullptr) {
|
||||||
|
dawn_native::DeviceDescriptor deviceDescriptor = InitWorkaround(forceEnabledWorkaround);
|
||||||
|
backendDevice = backendAdapter.CreateDevice(&deviceDescriptor);
|
||||||
|
} else {
|
||||||
|
backendDevice = backendAdapter.CreateDevice(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
DawnProcTable backendProcs = dawn_native::GetProcs();
|
DawnProcTable backendProcs = dawn_native::GetProcs();
|
||||||
|
|
||||||
// Get the test window and create the device using it (esp. for OpenGL)
|
// Get the test window and create the device using it (esp. for OpenGL)
|
||||||
GLFWwindow* testWindow = gTestEnv->GetWindowForBackend(GetParam());
|
GLFWwindow* testWindow = gTestEnv->GetWindowForBackend(backendType);
|
||||||
DAWN_ASSERT(testWindow != nullptr);
|
DAWN_ASSERT(testWindow != nullptr);
|
||||||
mBinding.reset(utils::CreateBinding(GetParam(), testWindow, backendDevice));
|
mBinding.reset(utils::CreateBinding(backendType, testWindow, backendDevice));
|
||||||
DAWN_ASSERT(mBinding != nullptr);
|
DAWN_ASSERT(mBinding != nullptr);
|
||||||
|
|
||||||
// Choose whether to use the backend procs and devices directly, or set up the wire.
|
// Choose whether to use the backend procs and devices directly, or set up the wire.
|
||||||
|
@ -586,20 +608,26 @@ namespace detail {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<dawn_native::BackendType> FilterBackends(const dawn_native::BackendType* types,
|
std::vector<DawnTestParam> FilterBackends(const DawnTestParam* params, size_t numParams) {
|
||||||
size_t numParams) {
|
std::vector<DawnTestParam> backends;
|
||||||
std::vector<dawn_native::BackendType> backends;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numParams; ++i) {
|
for (size_t i = 0; i < numParams; ++i) {
|
||||||
if (IsBackendAvailable(types[i])) {
|
if (IsBackendAvailable(params[i].backendType)) {
|
||||||
backends.push_back(types[i]);
|
backends.push_back(params[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return backends;
|
return backends;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetParamName(const testing::TestParamInfo<dawn_native::BackendType>& info) {
|
std::string GetParamName(const testing::TestParamInfo<DawnTestParam>& info) {
|
||||||
return ParamName(info.param);
|
std::ostringstream ostream;
|
||||||
|
ostream << ParamName(info.param.backendType);
|
||||||
|
|
||||||
|
if (info.param.forceEnabledWorkaround != nullptr) {
|
||||||
|
ostream << "_" << info.param.forceEnabledWorkaround;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ostream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper classes to set expectations
|
// Helper classes to set expectations
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "dawn_native/DawnNative.h"
|
#include "dawn_native/DawnNative.h"
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
@ -60,11 +61,24 @@ struct RGBA8 {
|
||||||
};
|
};
|
||||||
std::ostream& operator<<(std::ostream& stream, const RGBA8& color);
|
std::ostream& operator<<(std::ostream& stream, const RGBA8& color);
|
||||||
|
|
||||||
|
struct DawnTestParam {
|
||||||
|
constexpr explicit DawnTestParam(dawn_native::BackendType backendType)
|
||||||
|
: backendType(backendType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn_native::BackendType backendType;
|
||||||
|
|
||||||
|
// TODO(jiawei.shao@intel.com): support enabling and disabling multiple workarounds.
|
||||||
|
const char* forceEnabledWorkaround = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
// Shorthands for backend types used in the DAWN_INSTANTIATE_TEST
|
// Shorthands for backend types used in the DAWN_INSTANTIATE_TEST
|
||||||
static constexpr dawn_native::BackendType D3D12Backend = dawn_native::BackendType::D3D12;
|
static constexpr DawnTestParam D3D12Backend(dawn_native::BackendType::D3D12);
|
||||||
static constexpr dawn_native::BackendType MetalBackend = dawn_native::BackendType::Metal;
|
static constexpr DawnTestParam MetalBackend(dawn_native::BackendType::Metal);
|
||||||
static constexpr dawn_native::BackendType OpenGLBackend = dawn_native::BackendType::OpenGL;
|
static constexpr DawnTestParam OpenGLBackend(dawn_native::BackendType::OpenGL);
|
||||||
static constexpr dawn_native::BackendType VulkanBackend = dawn_native::BackendType::Vulkan;
|
static constexpr DawnTestParam VulkanBackend(dawn_native::BackendType::Vulkan);
|
||||||
|
|
||||||
|
DawnTestParam ForceWorkaround(const DawnTestParam& originParam, const char* workaround);
|
||||||
|
|
||||||
struct GLFWwindow;
|
struct GLFWwindow;
|
||||||
|
|
||||||
|
@ -107,7 +121,7 @@ class DawnTestEnvironment : public testing::Environment {
|
||||||
std::unordered_map<dawn_native::BackendType, GLFWwindow*> mWindows;
|
std::unordered_map<dawn_native::BackendType, GLFWwindow*> mWindows;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DawnTest : public ::testing::TestWithParam<dawn_native::BackendType> {
|
class DawnTest : public ::testing::TestWithParam<DawnTestParam> {
|
||||||
public:
|
public:
|
||||||
DawnTest();
|
DawnTest();
|
||||||
~DawnTest();
|
~DawnTest();
|
||||||
|
@ -242,9 +256,8 @@ class DawnTest : public ::testing::TestWithParam<dawn_native::BackendType> {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
// Helper functions used for DAWN_INSTANTIATE_TEST
|
// Helper functions used for DAWN_INSTANTIATE_TEST
|
||||||
bool IsBackendAvailable(dawn_native::BackendType type);
|
bool IsBackendAvailable(dawn_native::BackendType type);
|
||||||
std::vector<dawn_native::BackendType> FilterBackends(const dawn_native::BackendType* types,
|
std::vector<DawnTestParam> FilterBackends(const DawnTestParam* params, size_t numParams);
|
||||||
size_t numParams);
|
std::string GetParamName(const testing::TestParamInfo<DawnTestParam>& info);
|
||||||
std::string GetParamName(const testing::TestParamInfo<dawn_native::BackendType>& info);
|
|
||||||
|
|
||||||
// All classes used to implement the deferred expectations should inherit from this.
|
// All classes used to implement the deferred expectations should inherit from this.
|
||||||
class Expectation {
|
class Expectation {
|
||||||
|
|
|
@ -510,4 +510,9 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DArrayTexture) {
|
||||||
VerifyResolveTarget(kGreen, resolveTexture2, kBaseMipLevel2, kBaseArrayLayer2);
|
VerifyResolveTarget(kGreen, resolveTexture2, kBaseMipLevel2, kBaseArrayLayer2);
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(MultisampledRenderingTest, D3D12Backend, OpenGLBackend, MetalBackend, VulkanBackend);
|
DAWN_INSTANTIATE_TEST(MultisampledRenderingTest,
|
||||||
|
D3D12Backend,
|
||||||
|
MetalBackend,
|
||||||
|
OpenGLBackend,
|
||||||
|
VulkanBackend,
|
||||||
|
ForceWorkaround(MetalBackend, "emulate_store_and_msaa_resolve"));
|
||||||
|
|
|
@ -34,7 +34,7 @@ class RingBufferTests : public testing::Test {
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
// TODO(bryan.bernhart@intel.com): Create this device through the adapter.
|
// TODO(bryan.bernhart@intel.com): Create this device through the adapter.
|
||||||
mDevice = std::make_unique<null::Device>(/*adapter*/ nullptr);
|
mDevice = std::make_unique<null::Device>(/*adapter*/ nullptr, /*deviceDescriptor*/ nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
null::Device* GetDevice() const {
|
null::Device* GetDevice() const {
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
// 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 "tests/unittests/validation/ValidationTest.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class ToggleValidationTest : public ValidationTest {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tests querying the detail of a toggle from dawn_native::InstanceBase works correctly.
|
||||||
|
TEST_F(ToggleValidationTest, QueryToggleInfo) {
|
||||||
|
// Query with a valid toggle name
|
||||||
|
{
|
||||||
|
const char* kValidToggleName = "emulate_store_and_msaa_resolve";
|
||||||
|
const dawn_native::ToggleInfo* toggleInfo = instance->GetToggleInfo(kValidToggleName);
|
||||||
|
ASSERT_NE(nullptr, toggleInfo);
|
||||||
|
ASSERT_NE(nullptr, toggleInfo->name);
|
||||||
|
ASSERT_NE(nullptr, toggleInfo->description);
|
||||||
|
ASSERT_NE(nullptr, toggleInfo->url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query with an invalid toggle name
|
||||||
|
{
|
||||||
|
const char* kInvalidToggleName = "!@#$%^&*";
|
||||||
|
const dawn_native::ToggleInfo* toggleInfo = instance->GetToggleInfo(kInvalidToggleName);
|
||||||
|
ASSERT_EQ(nullptr, toggleInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests overriding toggles when creating a device works correctly.
|
||||||
|
TEST_F(ToggleValidationTest, OverrideToggleUsage) {
|
||||||
|
// Dawn unittests use null Adapters, so there should be no toggles that are enabled by default
|
||||||
|
{
|
||||||
|
std::vector<const char*> toggleNames = dawn_native::GetTogglesUsed(device.Get());
|
||||||
|
ASSERT_EQ(0u, toggleNames.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create device with a valid name of a toggle
|
||||||
|
{
|
||||||
|
const char* kValidToggleName = "emulate_store_and_msaa_resolve";
|
||||||
|
dawn_native::DeviceDescriptor descriptor;
|
||||||
|
descriptor.forceEnabledToggles.push_back(kValidToggleName);
|
||||||
|
|
||||||
|
DawnDevice deviceWithToggle = adapter.CreateDevice(&descriptor);
|
||||||
|
std::vector<const char*> toggleNames = dawn_native::GetTogglesUsed(deviceWithToggle);
|
||||||
|
ASSERT_EQ(1u, toggleNames.size());
|
||||||
|
ASSERT_EQ(0, strcmp(kValidToggleName, toggleNames[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create device with an invalid toggle name
|
||||||
|
{
|
||||||
|
dawn_native::DeviceDescriptor descriptor;
|
||||||
|
descriptor.forceEnabledToggles.push_back("!@#$%^&*");
|
||||||
|
|
||||||
|
DawnDevice deviceWithToggle = adapter.CreateDevice(&descriptor);
|
||||||
|
std::vector<const char*> toggleNames = dawn_native::GetTogglesUsed(deviceWithToggle);
|
||||||
|
ASSERT_EQ(0u, toggleNames.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // anonymous namespace
|
|
@ -16,28 +16,26 @@
|
||||||
|
|
||||||
#include "common/Assert.h"
|
#include "common/Assert.h"
|
||||||
#include "dawn/dawn.h"
|
#include "dawn/dawn.h"
|
||||||
#include "dawn_native/DawnNative.h"
|
|
||||||
#include "dawn_native/NullBackend.h"
|
#include "dawn_native/NullBackend.h"
|
||||||
|
|
||||||
ValidationTest::ValidationTest() {
|
ValidationTest::ValidationTest() {
|
||||||
mInstance = std::make_unique<dawn_native::Instance>();
|
instance = std::make_unique<dawn_native::Instance>();
|
||||||
mInstance->DiscoverDefaultAdapters();
|
instance->DiscoverDefaultAdapters();
|
||||||
|
|
||||||
std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
|
std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
|
||||||
|
|
||||||
// Validation tests run against the null backend, find the corresponding adapter
|
// Validation tests run against the null backend, find the corresponding adapter
|
||||||
bool foundNullAdapter = false;
|
bool foundNullAdapter = false;
|
||||||
dawn_native::Adapter nullAdapter;
|
for (auto ¤tAdapter : adapters) {
|
||||||
for (auto adapter : adapters) {
|
if (currentAdapter.GetBackendType() == dawn_native::BackendType::Null) {
|
||||||
if (adapter.GetBackendType() == dawn_native::BackendType::Null) {
|
adapter = currentAdapter;
|
||||||
nullAdapter = adapter;
|
|
||||||
foundNullAdapter = true;
|
foundNullAdapter = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(foundNullAdapter);
|
ASSERT(foundNullAdapter);
|
||||||
device = dawn::Device::Acquire(nullAdapter.CreateDevice());
|
device = dawn::Device::Acquire(adapter.CreateDevice());
|
||||||
|
|
||||||
DawnProcTable procs = dawn_native::GetProcs();
|
DawnProcTable procs = dawn_native::GetProcs();
|
||||||
dawnSetProcs(&procs);
|
dawnSetProcs(&procs);
|
||||||
|
|
|
@ -17,10 +17,7 @@
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "dawn/dawncpp.h"
|
#include "dawn/dawncpp.h"
|
||||||
|
#include "dawn_native/DawnNative.h"
|
||||||
namespace dawn_native {
|
|
||||||
class Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ASSERT_DEVICE_ERROR(statement) \
|
#define ASSERT_DEVICE_ERROR(statement) \
|
||||||
StartExpectDeviceError(); \
|
StartExpectDeviceError(); \
|
||||||
|
@ -55,10 +52,10 @@ class ValidationTest : public testing::Test {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
dawn::Device device;
|
dawn::Device device;
|
||||||
|
dawn_native::Adapter adapter;
|
||||||
|
std::unique_ptr<dawn_native::Instance> instance;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<dawn_native::Instance> mInstance;
|
|
||||||
|
|
||||||
static void OnDeviceError(const char* message, DawnCallbackUserdata userdata);
|
static void OnDeviceError(const char* message, DawnCallbackUserdata userdata);
|
||||||
std::string mDeviceErrorMessage;
|
std::string mDeviceErrorMessage;
|
||||||
bool mExpectError = false;
|
bool mExpectError = false;
|
||||||
|
|
Loading…
Reference in New Issue