Dawn: Refactor device toggles

This CL refactor the logic adapter creating device toggles set when
creating device and the way device holding its toggles. This CL also
introduce the concept "toggle stage", currently "device stage" only but
in future will add "instance stage" and "adapter stage" for instance and
adapter toggles. No changes on Dawn API.
More details:
1. Introduce `TogglesState` objects that represent the complete toggles
   state of a device (and will used for instance and adapter in future).
2. When creating a device, adapter set up a TogglesState object for it
   in `AdapterBase::CreateDeviceInternal` and
   `Adapter::SetupBackendDeviceToggles`, no other place would change
   the device's toggles state. This change simplify the logic.
3. Introduce the `ToggleStage` enum for every toggle and `TogglesState`
   object. Currently we only have `Device` toggle stage, but in future
   will have `Instance` and `Adapter` for instance and adapter toggles.

Bug: dawn:1495
Change-Id: Ifafac6a6a075b5b9a733159574ae5b6d4f3ebde9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118030
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Zhaoming Jiang <zhaoming.jiang@intel.com>
This commit is contained in:
Zhaoming Jiang 2023-02-10 01:43:55 +00:00 committed by Dawn LUCI CQ
parent 4906b03963
commit 63b777b552
27 changed files with 695 additions and 642 deletions

View File

@ -63,23 +63,23 @@ bool useRenderPass = device->IsToggleEnabled(Toggle::UseD3D12RenderPass);
```
Toggles are defined in a table in [Toggles.cpp](../src/dawn/native/Toggles.cpp) that also includes their name and description.
The name can be used to force enabling of a toggle or, at the contrary, force the disabling of a toogle.
The name can be used to require enabling of a toggle or, at the contrary, require the disabling of a toogle.
This is particularly useful in tests so that the two sides of a code path can be tested (for example using D3D12 render passes and not).
Here's an example of a test that is run in the D3D12 backend both with the D3D12 render passes forcibly disabled, and in the default configuration.
Here's an example of a test that is run in the D3D12 backend both with the D3D12 render passes required to be disabled, and in the default configuration.
```
DAWN_INSTANTIATE_TEST(RenderPassTest,
D3D12Backend(),
D3D12Backend({}, {"use_d3d12_render_pass"}));
// The {} is the list of force enabled toggles, {"..."} the force disabled ones.
// The {} is the list of required enabled toggles, {"..."} the required disabled ones.
```
The initialization order of toggles looks as follows:
The toggles state of a device is decided by the adapter when creating it. The steps of device toggles state decision looks as follows:
- The toggles overrides from the device descriptor are applied.
- The frontend device default toggles are applied (unless already overriden).
- The backend device default toggles are applied (unless already overriden) using `DeviceBase::SetToggle`
- The backend device can ignore overriden toggles if it can't support them by using `DeviceBase::ForceSetToggle`
- The device toggles state initialized to required device toggles from the DawnTogglesDescriptor chained in device descriptor.
- The frontend (i.e. not backend-specific) default toggles are set (unless already required) using `TogglesState::Default`.
- Any backend device toggle that not supported is forced set to a proper state in `Adapter::SetupBackendDeviceToggles` using `TogglesState::ForceSet`.
- The backend device default toggles are applied (unless already set) in `Adapter::SetupBackendDeviceToggles` using `TogglesState::Default`.
Forcing toggles should only be done when there is no "safe" option for the toggle.
This is to avoid crashes during testing when the tests try to use both sides of a toggle.

View File

@ -49,6 +49,12 @@ struct DAWN_NATIVE_EXPORT DawnDeviceDescriptor {
const WGPURequiredLimits* requiredLimits = nullptr;
};
// Each toggle is assigned with a TogglesStage, indicating the validation and earliest usage
// time of the toggle.
// TODO(dawn:1495): Currently all toggles are device toggles, i.e. of Device toggle stage. Add
// instance and adapter stages after instance and adapter toggles implemented.
enum class ToggleStage { Device };
// 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.
@ -56,6 +62,7 @@ struct ToggleInfo {
const char* name;
const char* description;
const char* url;
ToggleStage stage;
};
// A struct to record the information of a feature. A feature is a GPU feature that is not

View File

@ -206,9 +206,9 @@ bool AdapterBase::GetLimits(SupportedLimits* limits) const {
return true;
}
MaybeError AdapterBase::ValidateFeatureSupportedWithToggles(
MaybeError AdapterBase::ValidateFeatureSupportedWithDeviceToggles(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) {
const TogglesState& deviceTogglesState) {
DAWN_TRY(ValidateFeatureName(feature));
DAWN_INVALID_IF(!mSupportedFeatures.IsEnabled(feature),
"Requested feature %s is not supported.", feature);
@ -216,21 +216,21 @@ MaybeError AdapterBase::ValidateFeatureSupportedWithToggles(
const FeatureInfo* featureInfo = GetInstance()->GetFeatureInfo(feature);
// Experimental features are guarded by toggle DisallowUnsafeAPIs.
if (featureInfo->featureState == FeatureInfo::FeatureState::Experimental) {
DAWN_INVALID_IF(!userProvidedToggles.IsDisabled(Toggle::DisallowUnsafeAPIs),
// DisallowUnsafeAPIs toggle is by default enabled if not explicitly disabled.
DAWN_INVALID_IF(deviceTogglesState.IsEnabled(Toggle::DisallowUnsafeAPIs),
"Feature %s is guarded by toggle disallow_unsafe_apis.", featureInfo->name);
}
// Do backend-specific validation.
return ValidateFeatureSupportedWithTogglesImpl(feature, userProvidedToggles);
return ValidateFeatureSupportedWithDeviceTogglesImpl(feature, deviceTogglesState);
}
ResultOrError<Ref<DeviceBase>> AdapterBase::CreateDeviceInternal(
const DeviceDescriptor* descriptor) {
ASSERT(descriptor != nullptr);
// Check overriden toggles before creating device, as some device features may be guarded by
// toggles, and requiring such features without using corresponding toggles should fails the
// device creating.
// Create device toggles state from required toggles descriptor.
// TODO(dawn:1495): After implementing adapter toggles, also inherite adapter toggles state.
const DawnTogglesDescriptor* deviceTogglesDesc = nullptr;
FindInChain(descriptor->nextInChain, &deviceTogglesDesc);
@ -261,13 +261,24 @@ ResultOrError<Ref<DeviceBase>> AdapterBase::CreateDeviceInternal(
deviceTogglesDesc = &convertedDeviceTogglesDesc;
}
TripleStateTogglesSet userProvidedToggles =
TripleStateTogglesSet::CreateFromTogglesDescriptor(deviceTogglesDesc);
// Create device toggles state from user-given toggles descriptor, and set up forced and default
// toggles.
// TODO(dawn:1495): After implementing adapter toggles, device toggles state should also inherit
// from adapter toggles state.
TogglesState deviceToggles =
TogglesState::CreateFromTogglesDescriptor(deviceTogglesDesc, ToggleStage::Device);
// Default toggles for all backend
deviceToggles.Default(Toggle::LazyClearResourceOnFirstUse, true);
deviceToggles.Default(Toggle::DisallowUnsafeAPIs, true);
// Backend-specific forced and default device toggles
SetupBackendDeviceToggles(&deviceToggles);
// Validate all required features are supported by the adapter and suitable under given toggles.
// TODO(dawn:1495): After implementing adapter toggles, validate supported features using
// adapter toggles instead of device toggles.
for (uint32_t i = 0; i < descriptor->requiredFeaturesCount; ++i) {
wgpu::FeatureName feature = descriptor->requiredFeatures[i];
DAWN_TRY(ValidateFeatureSupportedWithToggles(feature, userProvidedToggles));
DAWN_TRY(ValidateFeatureSupportedWithDeviceToggles(feature, deviceToggles));
}
if (descriptor->requiredLimits != nullptr) {
@ -278,7 +289,7 @@ ResultOrError<Ref<DeviceBase>> AdapterBase::CreateDeviceInternal(
DAWN_INVALID_IF(descriptor->requiredLimits->nextInChain != nullptr,
"nextInChain is not nullptr.");
}
return CreateDeviceImpl(descriptor, userProvidedToggles);
return CreateDeviceImpl(descriptor, deviceToggles);
}
void AdapterBase::SetUseTieredLimits(bool useTieredLimits) {

View File

@ -82,14 +82,17 @@ class AdapterBase : public RefCounted {
// validation error if proper toggles are not enabled/disabled.
FeaturesSet mSupportedFeatures;
// Check if a feature os supported by this adapter AND suitable with given toggles.
MaybeError ValidateFeatureSupportedWithToggles(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles);
// TODO(dawn:1495): After implementing adapter toggles, remove this and use adapter toggles
// instead of device toggles to validate supported features.
MaybeError ValidateFeatureSupportedWithDeviceToggles(wgpu::FeatureName feature,
const TogglesState& deviceTogglesState);
private:
virtual ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) = 0;
// Backend-specific force-setting and defaulting device toggles
virtual void SetupBackendDeviceToggles(TogglesState* deviceToggles) const = 0;
virtual ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) = 0;
virtual MaybeError InitializeImpl() = 0;
@ -101,9 +104,9 @@ class AdapterBase : public RefCounted {
virtual void InitializeVendorArchitectureImpl();
virtual MaybeError ValidateFeatureSupportedWithTogglesImpl(
virtual MaybeError ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) = 0;
const TogglesState& deviceTogglesState) = 0;
ResultOrError<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* descriptor);

View File

@ -173,18 +173,14 @@ ResultOrError<Ref<PipelineLayoutBase>> ValidateLayoutAndGetRenderPipelineDescrip
DeviceBase::DeviceBase(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles)
: mAdapter(adapter),
mEnabledToggles(userProvidedToggles.providedTogglesEnabled),
mOverridenToggles(userProvidedToggles.togglesIsProvided),
mNextPipelineCompatibilityToken(1) {
const TogglesState& deviceToggles)
: mAdapter(adapter), mToggles(deviceToggles), mNextPipelineCompatibilityToken(1) {
mAdapter->GetInstance()->IncrementDeviceCountForTesting();
ASSERT(descriptor != nullptr);
AdapterProperties adapterProperties;
adapter->APIGetProperties(&adapterProperties);
SetDefaultToggles();
ApplyFeatures(descriptor);
DawnCacheDeviceDescriptor defaultCacheDesc = {};
@ -210,10 +206,10 @@ DeviceBase::DeviceBase(AdapterBase* adapter,
// descriptor is added (and probably handled here), the cache key recording needs to be
// updated.
StreamIn(&mDeviceCacheKey, kDawnVersion, adapterProperties, mEnabledFeatures.featuresBitSet,
mEnabledToggles.toggleBitset, cacheDesc);
mToggles, cacheDesc);
}
DeviceBase::DeviceBase() : mState(State::Alive) {
DeviceBase::DeviceBase() : mState(State::Alive), mToggles(ToggleStage::Device) {
mCaches = std::make_unique<DeviceBase::Caches>();
}
@ -1754,30 +1750,15 @@ DynamicUploader* DeviceBase::GetDynamicUploader() const {
// The Toggle device facility
std::vector<const char*> DeviceBase::GetTogglesUsed() const {
return mEnabledToggles.GetContainedToggleNames();
return mToggles.GetEnabledToggleNames();
}
bool DeviceBase::IsToggleEnabled(Toggle toggle) const {
return mEnabledToggles.Has(toggle);
return mToggles.IsEnabled(toggle);
}
void DeviceBase::SetToggle(Toggle toggle, bool isEnabled) {
if (!mOverridenToggles.Has(toggle)) {
mEnabledToggles.Set(toggle, isEnabled);
}
}
void DeviceBase::ForceSetToggle(Toggle toggle, bool isEnabled) {
if (mOverridenToggles.Has(toggle) && mEnabledToggles.Has(toggle) != isEnabled) {
dawn::WarningLog() << "Forcing toggle \"" << ToggleEnumToName(toggle) << "\" to "
<< isEnabled << " when it was overriden to be " << !isEnabled;
}
mEnabledToggles.Set(toggle, isEnabled);
}
void DeviceBase::SetDefaultToggles() {
SetToggle(Toggle::LazyClearResourceOnFirstUse, true);
SetToggle(Toggle::DisallowUnsafeAPIs, true);
void DeviceBase::ForceSetToggleForTesting(Toggle toggle, bool isEnabled) {
mToggles.ForceSet(toggle, isEnabled);
}
void DeviceBase::FlushCallbackTaskQueue() {

View File

@ -63,7 +63,7 @@ class DeviceBase : public RefCountedWithExternalCount {
public:
DeviceBase(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles);
const TogglesState& deviceToggles);
~DeviceBase() override;
// Handles the error, causing a device loss if applicable. Almost always when a device loss
@ -419,8 +419,7 @@ class DeviceBase : public RefCountedWithExternalCount {
// Constructor used only for mocking and testing.
DeviceBase();
void SetToggle(Toggle toggle, bool isEnabled);
void ForceSetToggle(Toggle toggle, bool isEnabled);
void ForceSetToggleForTesting(Toggle toggle, bool isEnabled);
MaybeError Initialize(Ref<QueueBase> defaultQueue);
void DestroyObjects();
@ -490,8 +489,6 @@ class DeviceBase : public RefCountedWithExternalCount {
void ApplyFeatures(const DeviceDescriptor* deviceDescriptor);
void SetDefaultToggles();
void SetWGSLExtensionAllowList();
void ConsumeError(std::unique_ptr<ErrorData> error);
@ -570,8 +567,8 @@ class DeviceBase : public RefCountedWithExternalCount {
FormatTable mFormatTable;
TogglesSet mEnabledToggles;
TogglesSet mOverridenToggles;
TogglesState mToggles;
size_t mLazyClearCountForTesting = 0;
std::atomic_uint64_t mNextPipelineCompatibilityToken;

View File

@ -15,9 +15,10 @@
#include <array>
#include "dawn/common/Assert.h"
#include "dawn/common/BitSetIterator.h"
#include "dawn/common/Log.h"
#include "dawn/native/Toggles.h"
#include "dawn/native/dawn_platform.h"
#include "dawn/native/stream/Stream.h"
namespace dawn::native {
namespace {
@ -36,13 +37,13 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
"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://crbug.com/dawn/56"}},
"https://crbug.com/dawn/56", ToggleStage::Device}},
{Toggle::NonzeroClearResourcesOnCreationForTesting,
{"nonzero_clear_resources_on_creation_for_testing",
"Clears texture to full 1 bits as soon as they are created, but doesn't update the tracking "
"state of the texture. This way we can test the logic of clearing textures that use recycled "
"memory.",
"https://crbug.com/dawn/145"}},
"https://crbug.com/dawn/145", ToggleStage::Device}},
{Toggle::AlwaysResolveIntoZeroLevelAndLayer,
{"always_resolve_into_zero_level_and_layer",
"When the resolve target is a texture view that is created on the non-zero level or layer of "
@ -51,17 +52,17 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
"workaround is enabled by default on the Metal drivers that have bugs when setting non-zero "
"resolveLevel or resolveSlice. It is also enabled by default on Qualcomm Vulkan drivers, "
"which have similar bugs.",
"https://crbug.com/dawn/56"}},
"https://crbug.com/dawn/56", ToggleStage::Device}},
{Toggle::LazyClearResourceOnFirstUse,
{"lazy_clear_resource_on_first_use",
"Clears resource to zero on first usage. This initializes the resource so that no dirty bits "
"from recycled memory is present in the new resource.",
"https://crbug.com/dawn/145"}},
"https://crbug.com/dawn/145", ToggleStage::Device}},
{Toggle::TurnOffVsync,
{"turn_off_vsync",
"Turn off vsync when rendering. In order to do performance test or run perf tests, turn off "
"vsync so that the fps can exeed 60.",
"https://crbug.com/dawn/237"}},
"https://crbug.com/dawn/237", ToggleStage::Device}},
{Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy,
{"use_temporary_buffer_in_texture_to_texture_copy",
"Split texture-to-texture copy into two copies: copy from source texture into a temporary "
@ -70,115 +71,116 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
"by default on all Vulkan drivers to solve an issue in the Vulkan SPEC about the "
"texture-to-texture copies with compressed formats. See #1005 "
"(https://github.com/KhronosGroup/Vulkan-Docs/issues/1005) for more details.",
"https://crbug.com/dawn/42"}},
"https://crbug.com/dawn/42", ToggleStage::Device}},
{Toggle::UseD3D12ResourceHeapTier2,
{"use_d3d12_resource_heap_tier2",
"Enable support for resource heap tier 2. Resource heap tier 2 allows mixing of texture and "
"buffers in the same heap. This allows better heap re-use and reduces fragmentation.",
"https://crbug.com/dawn/27"}},
"https://crbug.com/dawn/27", ToggleStage::Device}},
{Toggle::UseD3D12RenderPass,
{"use_d3d12_render_pass",
"Use the D3D12 render pass API introduced in Windows build 1809 by default. On versions of "
"Windows prior to build 1809, or when this toggle is turned off, Dawn will emulate a render "
"pass.",
"https://crbug.com/dawn/36"}},
"https://crbug.com/dawn/36", ToggleStage::Device}},
{Toggle::UseD3D12ResidencyManagement,
{"use_d3d12_residency_management",
"Enable residency management. This allows page-in and page-out of resource heaps in GPU "
"memory. This component improves overcommitted performance by keeping the most recently used "
"resources local to the GPU. Turning this component off can cause allocation failures when "
"application memory exceeds physical device memory.",
"https://crbug.com/dawn/193"}},
"https://crbug.com/dawn/193", ToggleStage::Device}},
{Toggle::DisableResourceSuballocation,
{"disable_resource_suballocation",
"Force the backends to not perform resource suballocation. This may expose allocation "
"patterns which would otherwise only occur with large or specific types of resources.",
"https://crbug.com/1313172"}},
"https://crbug.com/1313172", ToggleStage::Device}},
{Toggle::SkipValidation,
{"skip_validation", "Skip expensive validation of Dawn commands.",
"https://crbug.com/dawn/271"}},
"https://crbug.com/dawn/271", ToggleStage::Device}},
{Toggle::VulkanUseD32S8,
{"vulkan_use_d32s8",
"Vulkan mandates support of either D32_FLOAT_S8 or D24_UNORM_S8. When available the backend "
"will use D32S8 (toggle to on) but setting the toggle to off will make it use the D24S8 "
"format when possible.",
"https://crbug.com/dawn/286"}},
"https://crbug.com/dawn/286", ToggleStage::Device}},
{Toggle::VulkanUseS8,
{"vulkan_use_s8",
"Vulkan has a pure stencil8 format but it is not universally available. When this toggle is "
"on, the backend will use S8 for the stencil8 format, otherwise it will fallback to D32S8 or "
"D24S8.",
"https://crbug.com/dawn/666"}},
"https://crbug.com/dawn/666", ToggleStage::Device}},
{Toggle::MetalDisableSamplerCompare,
{"metal_disable_sampler_compare",
"Disables the use of sampler compare on Metal. This is unsupported before A9 processors.",
"https://crbug.com/dawn/342"}},
"https://crbug.com/dawn/342", ToggleStage::Device}},
{Toggle::MetalUseSharedModeForCounterSampleBuffer,
{"metal_use_shared_mode_for_counter_sample_buffer",
"The query set on Metal need to create MTLCounterSampleBuffer which storage mode must be "
"either MTLStorageModeShared or MTLStorageModePrivate. But the private mode does not work "
"properly on Intel platforms. The workaround is use shared mode instead.",
"https://crbug.com/dawn/434"}},
"https://crbug.com/dawn/434", ToggleStage::Device}},
{Toggle::DisableBaseVertex,
{"disable_base_vertex",
"Disables the use of non-zero base vertex which is unsupported on some platforms.",
"https://crbug.com/dawn/343"}},
"https://crbug.com/dawn/343", ToggleStage::Device}},
{Toggle::DisableBaseInstance,
{"disable_base_instance",
"Disables the use of non-zero base instance which is unsupported on some platforms.",
"https://crbug.com/dawn/343"}},
"https://crbug.com/dawn/343", ToggleStage::Device}},
{Toggle::DisableIndexedDrawBuffers,
{"disable_indexed_draw_buffers",
"Disables the use of indexed draw buffer state which is unsupported on some platforms.",
"https://crbug.com/dawn/582"}},
"https://crbug.com/dawn/582", ToggleStage::Device}},
{Toggle::DisableSnormRead,
{"disable_snorm_read",
"Disables reading from Snorm textures which is unsupported on some platforms.",
"https://crbug.com/dawn/667"}},
"https://crbug.com/dawn/667", ToggleStage::Device}},
{Toggle::DisableDepthRead,
{"disable_depth_read",
"Disables reading from depth textures which is unsupported on some platforms.",
"https://crbug.com/dawn/667"}},
"https://crbug.com/dawn/667", ToggleStage::Device}},
{Toggle::DisableStencilRead,
{"disable_stencil_read",
"Disables reading from stencil textures which is unsupported on some platforms.",
"https://crbug.com/dawn/667"}},
"https://crbug.com/dawn/667", ToggleStage::Device}},
{Toggle::DisableDepthStencilRead,
{"disable_depth_stencil_read",
"Disables reading from depth/stencil textures which is unsupported on some platforms.",
"https://crbug.com/dawn/667"}},
"https://crbug.com/dawn/667", ToggleStage::Device}},
{Toggle::DisableBGRARead,
{"disable_bgra_read",
"Disables reading from BGRA textures which is unsupported on some platforms.",
"https://crbug.com/dawn/1393"}},
"https://crbug.com/dawn/1393", ToggleStage::Device}},
{Toggle::DisableSampleVariables,
{"disable_sample_variables",
"Disables gl_SampleMask and related functionality which is unsupported on some platforms.",
"https://crbug.com/dawn/673"}},
"https://crbug.com/dawn/673", ToggleStage::Device}},
{Toggle::UseD3D12SmallShaderVisibleHeapForTesting,
{"use_d3d12_small_shader_visible_heap",
"Enable use of a small D3D12 shader visible heap, instead of using a large one by default. "
"This setting is used to test bindgroup encoding.",
"https://crbug.com/dawn/155"}},
"https://crbug.com/dawn/155", ToggleStage::Device}},
{Toggle::UseDXC,
{"use_dxc",
"Use DXC instead of FXC for compiling HLSL when both dxcompiler.dll and dxil.dll is "
"available.",
"https://crbug.com/dawn/402"}},
"https://crbug.com/dawn/402", ToggleStage::Device}},
{Toggle::DisableRobustness,
{"disable_robustness", "Disable robust buffer access", "https://crbug.com/dawn/480"}},
{"disable_robustness", "Disable robust buffer access", "https://crbug.com/dawn/480",
ToggleStage::Device}},
{Toggle::MetalEnableVertexPulling,
{"metal_enable_vertex_pulling", "Uses vertex pulling to protect out-of-bounds reads on Metal",
"https://crbug.com/dawn/480"}},
"https://crbug.com/dawn/480", ToggleStage::Device}},
{Toggle::DisallowUnsafeAPIs,
{"disallow_unsafe_apis",
"Produces validation errors on API entry points or parameter combinations that aren't "
"considered secure yet.",
"http://crbug.com/1138528"}},
"http://crbug.com/1138528", ToggleStage::Device}},
{Toggle::FlushBeforeClientWaitSync,
{"flush_before_client_wait_sync",
"Call glFlush before glClientWaitSync to work around bugs in the latter",
"https://crbug.com/dawn/633"}},
"https://crbug.com/dawn/633", ToggleStage::Device}},
{Toggle::UseTempBufferInSmallFormatTextureToTextureCopyFromGreaterToLessMipLevel,
{"use_temp_buffer_in_small_format_texture_to_texture_copy_from_greater_to_less_mip_level",
"Split texture-to-texture copy into two copies: copy from source texture into a temporary "
@ -187,67 +189,67 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
"bug in the execution of CopyTextureRegion() when we copy with the formats whose texel "
"block sizes are less than 4 bytes from a greater mip level to a smaller mip level on D3D12 "
"backends.",
"https://crbug.com/1161355"}},
"https://crbug.com/1161355", ToggleStage::Device}},
{Toggle::EmitHLSLDebugSymbols,
{"emit_hlsl_debug_symbols",
"Sets the D3DCOMPILE_SKIP_OPTIMIZATION and D3DCOMPILE_DEBUG compilation flags when compiling "
"HLSL code. Enables better shader debugging with external graphics debugging tools.",
"https://crbug.com/dawn/776"}},
"https://crbug.com/dawn/776", ToggleStage::Device}},
{Toggle::DisallowSpirv,
{"disallow_spirv",
"Disallow usage of SPIR-V completely so that only WGSL is used for shader modules. This is "
"useful to prevent a Chromium renderer process from successfully sending SPIR-V code to be "
"compiled in the GPU process.",
"https://crbug.com/1214923"}},
"https://crbug.com/1214923", ToggleStage::Device}},
{Toggle::DumpShaders,
{"dump_shaders",
"Dump shaders for debugging purposes. Dumped shaders will be log via EmitLog, thus printed "
"in Chrome console or consumed by user-defined callback function.",
"https://crbug.com/dawn/792"}},
"https://crbug.com/dawn/792", ToggleStage::Device}},
{Toggle::ForceWGSLStep,
{"force_wgsl_step",
"When ingesting SPIR-V shaders, force a first conversion to WGSL. This allows testing Tint's "
"SPIRV->WGSL translation on real content to be sure that it will work when the same "
"translation runs in a WASM module in the page.",
"https://crbug.com/dawn/960"}},
"https://crbug.com/dawn/960", ToggleStage::Device}},
{Toggle::DisableWorkgroupInit,
{"disable_workgroup_init",
"Disables the workgroup memory zero-initialization for compute shaders.",
"https://crbug.com/tint/1003"}},
"https://crbug.com/tint/1003", ToggleStage::Device}},
{Toggle::DisableSymbolRenaming,
{"disable_symbol_renaming", "Disables the WGSL symbol renaming so that names are preserved.",
"https://crbug.com/dawn/1016"}},
"https://crbug.com/dawn/1016", ToggleStage::Device}},
{Toggle::UseUserDefinedLabelsInBackend,
{"use_user_defined_labels_in_backend",
"Enables calls to SetLabel to be forwarded to backend-specific APIs that label objects.",
"https://crbug.com/dawn/840"}},
"https://crbug.com/dawn/840", ToggleStage::Device}},
{Toggle::UsePlaceholderFragmentInVertexOnlyPipeline,
{"use_placeholder_fragment_in_vertex_only_pipeline",
"Use a placeholder empty fragment shader in vertex only render pipeline. This toggle must be "
"enabled for OpenGL ES backend, and serves as a workaround by default enabled on some Metal "
"devices with Intel GPU to ensure the depth result is correct.",
"https://crbug.com/dawn/136"}},
"https://crbug.com/dawn/136", ToggleStage::Device}},
{Toggle::FxcOptimizations,
{"fxc_optimizations",
"Enable optimizations when compiling with FXC. Disabled by default because FXC miscompiles "
"in many cases when optimizations are enabled.",
"https://crbug.com/dawn/1203"}},
"https://crbug.com/dawn/1203", ToggleStage::Device}},
{Toggle::RecordDetailedTimingInTraceEvents,
{"record_detailed_timing_in_trace_events",
"Record detailed timing information in trace events at certain point. Currently the timing "
"information is recorded right before calling ExecuteCommandLists on a D3D12 command queue, "
"and the information includes system time, CPU timestamp, GPU timestamp, and their "
"frequency.",
"https://crbug.com/dawn/1264"}},
"https://crbug.com/dawn/1264", ToggleStage::Device}},
{Toggle::DisableTimestampQueryConversion,
{"disable_timestamp_query_conversion",
"Resolve timestamp queries into ticks instead of nanoseconds.",
"https://crbug.com/dawn/1305"}},
"Resolve timestamp queries into ticks instead of nanoseconds.", "https://crbug.com/dawn/1305",
ToggleStage::Device}},
{Toggle::VulkanUseZeroInitializeWorkgroupMemoryExtension,
{"use_vulkan_zero_initialize_workgroup_memory_extension",
"Initialize workgroup memory with OpConstantNull on Vulkan when the Vulkan extension "
"VK_KHR_zero_initialize_workgroup_memory is supported.",
"https://crbug.com/dawn/1302"}},
"https://crbug.com/dawn/1302", ToggleStage::Device}},
{Toggle::D3D12SplitBufferTextureCopyForRowsPerImagePaddings,
{"d3d12_split_buffer_texture_copy_for_rows_per_image_paddings",
"D3D12 requires more buffer storage than it should when rowsPerImage is greater than "
@ -255,48 +257,48 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
"the buffer used for B2T/T2B copy might be big enough according to WebGPU's spec but it "
"doesn't meet D3D12's requirement, then we need to workaround it via split the copy "
"operation into two copies, in order to make B2T/T2B copy being done correctly on D3D12.",
"https://crbug.com/dawn/1289"}},
"https://crbug.com/dawn/1289", ToggleStage::Device}},
{Toggle::MetalRenderR8RG8UnormSmallMipToTempTexture,
{"metal_render_r8_rg8_unorm_small_mip_to_temp_texture",
"Metal Intel devices have issues with r8unorm and rg8unorm textures where rendering to small "
"mips (level >= 2) doesn't work correctly. Workaround this issue by detecting this case and "
"rendering to a temporary texture instead (with copies before and after if needed).",
"https://crbug.com/dawn/1071"}},
"https://crbug.com/dawn/1071", ToggleStage::Device}},
{Toggle::DisableBlobCache,
{"disable_blob_cache",
"Disables usage of the blob cache (backed by the platform cache if set/passed). Prevents any "
"persistent caching capabilities, i.e. pipeline caching.",
"https://crbug.com/dawn/549"}},
"https://crbug.com/dawn/549", ToggleStage::Device}},
{Toggle::D3D12ForceClearCopyableDepthStencilTextureOnCreation,
{"d3d12_force_clear_copyable_depth_stencil_texture_on_creation",
"Always clearing copyable depth stencil textures when creating them instead of skipping the "
"initialization when the entire subresource is the copy destination as a workaround on Intel "
"D3D12 drivers.",
"https://crbug.com/dawn/1487"}},
"https://crbug.com/dawn/1487", ToggleStage::Device}},
{Toggle::D3D12DontSetClearValueOnDepthTextureCreation,
{"d3d12_dont_set_clear_value_on_depth_texture_creation",
"Don't set D3D12_CLEAR_VALUE when creating depth textures with CreatePlacedResource() or "
"CreateCommittedResource() as a workaround on Intel Gen12 D3D12 drivers.",
"https://crbug.com/dawn/1487"}},
"https://crbug.com/dawn/1487", ToggleStage::Device}},
{Toggle::D3D12AlwaysUseTypelessFormatsForCastableTexture,
{"d3d12_always_use_typeless_formats_for_castable_texture",
"Always use the typeless DXGI format when we create a texture with valid viewFormat. This "
"Toggle is enabled by default on the D3D12 platforms where CastingFullyTypedFormatSupported "
"is false.",
"https://crbug.com/dawn/1276"}},
"https://crbug.com/dawn/1276", ToggleStage::Device}},
{Toggle::D3D12AllocateExtraMemoryFor2DArrayColorTexture,
{"d3d12_allocate_extra_memory_for_2d_array_color_texture",
"Memory allocation for 2D array color texture may be smaller than it should be on D3D12 on "
"some Intel devices. So texture access can be out-of-bound, which may cause critical "
"security issue. We can workaround this security issue via allocating extra memory and "
"limiting its access in itself.",
"https://crbug.com/dawn/949"}},
"https://crbug.com/dawn/949", ToggleStage::Device}},
{Toggle::D3D12UseTempBufferInDepthStencilTextureAndBufferCopyWithNonZeroBufferOffset,
{"d3d12_use_temp_buffer_in_depth_stencil_texture_and_buffer_copy_with_non_zero_buffer_offset",
"Split buffer-texture copy into two copies: do first copy with a temporary buffer at offset "
"0, then copy from the temporary buffer to the destination. Now this toggle must be enabled "
"on the D3D12 platforms where programmable MSAA is not supported.",
"https://crbug.com/dawn/727"}},
"https://crbug.com/dawn/727", ToggleStage::Device}},
{Toggle::ApplyClearBigIntegerColorValueWithDraw,
{"apply_clear_big_integer_color_value_with_draw",
"Apply the clear value of the color attachment with a draw call when load op is 'clear'. "
@ -306,26 +308,26 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
"float numbers as clear values, while a float number cannot always precisely represent an "
"integer that is greater than 2^24 or smaller than -2^24). This toggle is also enabled on "
"Intel GPUs on Metal backend due to a driver issue on Intel Metal driver.",
"https://crbug.com/dawn/537"}},
"https://crbug.com/dawn/537", ToggleStage::Device}},
{Toggle::MetalUseMockBlitEncoderForWriteTimestamp,
{"metal_use_mock_blit_encoder_for_write_timestamp",
"Add mock blit command to blit encoder when encoding writeTimestamp as workaround on Metal."
"This toggle is enabled by default on Metal backend where GPU counters cannot be stored to"
"sampleBufferAttachments on empty blit encoder.",
"https://crbug.com/dawn/1473"}},
"https://crbug.com/dawn/1473", ToggleStage::Device}},
{Toggle::VulkanSplitCommandBufferOnDepthStencilComputeSampleAfterRenderPass,
{"vulkan_split_command_buffer_on_depth_stencil_compute_sample_after_render_pass",
"Splits any command buffer that samples a depth/stencil texture in a compute pass after that "
"texture was used as an attachment for a prior render pass. This toggle is enabled by "
"default on Qualcomm GPUs, which have been observed experiencing a driver crash in this "
"situation.",
"https://crbug.com/dawn/1564"}},
"https://crbug.com/dawn/1564", ToggleStage::Device}},
{Toggle::D3D12Allocate2DTextureWithCopyDstOrRenderAttachmentAsCommittedResource,
{"d3d12_allocate_2d_texture_with_copy_dst_or_render_attachment_as_committed_resource",
"Allocate each 2D texture with CopyDst or RenderAttachment usage as committed resources "
"instead of placed resources. This toggle is enabled by default on D3D12 backends using "
"Intel Gen9.5 and Gen11 GPUs due to a driver issue on Intel D3D12 driver.",
"https://crbug.com/1237175"}},
"https://crbug.com/1237175", ToggleStage::Device}},
{Toggle::MetalUseCombinedDepthStencilFormatForStencil8,
{"metal_use_combined_depth_stencil_format_for_stencil8",
"Use a combined depth stencil format instead of stencil8. Works around an issue where the "
@ -333,7 +335,7 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
"attachments using a stencil8 format to also set the depth attachment in the Metal render "
"pass. This works around another issue where Metal fails to set the stencil attachment "
"correctly for a combined depth stencil format if the depth attachment is not also set.",
"https://crbug.com/dawn/1389"}},
"https://crbug.com/dawn/1389", ToggleStage::Device}},
{Toggle::MetalUseBothDepthAndStencilAttachmentsForCombinedDepthStencilFormats,
{"metal_use_both_depth_and_stencil_attachments_for_combined_depth_stencil_formats",
"In Metal, depth and stencil attachments are set separately. Setting just one without the "
@ -341,47 +343,47 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
"This workarounds ensures that both are set. This situation arises during lazy clears, or "
"for stencil8 formats if metal_use_combined_depth_stencil_format_for_stencil8 is also "
"enabled.",
"https://crbug.com/dawn/1389"}},
"https://crbug.com/dawn/1389", ToggleStage::Device}},
{Toggle::UseBlitForBufferToDepthTextureCopy,
{"use_blit_for_buffer_to_depth_texture_copy",
"Use a blit instead of a copy command to copy buffer data to the depth aspect of a "
"texture. Works around an issue where depth writes by copy commands are not visible "
"to a render or compute pass.",
"https://crbug.com/dawn/1389"}},
"https://crbug.com/dawn/1389", ToggleStage::Device}},
{Toggle::UseBlitForBufferToStencilTextureCopy,
{"use_blit_for_buffer_to_stencil_texture_copy",
"Use a blit instead of a copy command to copy buffer data to the stencil aspect of a "
"texture. Works around an issue where stencil writes by copy commands are not visible "
"to a render or compute pass.",
"https://crbug.com/dawn/1389"}},
"https://crbug.com/dawn/1389", ToggleStage::Device}},
{Toggle::UseBlitForDepthTextureToTextureCopyToNonzeroSubresource,
{"use_blit_for_depth_texture_to_texture_copy_to_nonzero_subresource",
"Use a blit to copy from a depth texture to the nonzero subresource of a depth texture. "
"Works around an issue where nonzero layers are not written.",
"https://crbug.com/dawn/1083"}},
"https://crbug.com/dawn/1083", ToggleStage::Device}},
{Toggle::DisallowDeprecatedAPIs,
{"disallow_deprecated_apis",
"Disallow all deprecated paths by changing the deprecation warnings to validation error for "
"these paths."
"This toggle is off by default. It is expected to turn on or get removed when WebGPU V1 "
"ships and stays stable.",
"https://crbug.com/dawn/1563"}},
"https://crbug.com/dawn/1563", ToggleStage::Device}},
{Toggle::NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget,
{"no_workaround_sample_mask_becomes_zero_for_all_but_last_color_target",
"MacOS 12.0+ Intel has a bug where the sample mask is only applied for the last color "
"target. If there are multiple color targets, all but the last one will use a sample mask "
"of zero.",
"https://crbug.com/dawn/1462"}},
"https://crbug.com/dawn/1462", ToggleStage::Device}},
{Toggle::NoWorkaroundIndirectBaseVertexNotApplied,
{"no_workaround_indirect_base_vertex_not_applied",
"MacOS Intel < Gen9 has a bug where indirect base vertex is not applied for "
"drawIndexedIndirect. Draws are done as if it is always zero.",
"https://crbug.com/dawn/966"}},
"https://crbug.com/dawn/966", ToggleStage::Device}},
{Toggle::NoWorkaroundDstAlphaBlendDoesNotWork,
{"no_workaround_dst_alpha_blend_does_not_work",
"Using D3D12_BLEND_DEST_ALPHA as blend factor doesn't work correctly on the D3D12 backend "
"using Intel Gen9 or Gen9.5 GPUs.",
"https://crbug.com/dawn/1579"}},
"https://crbug.com/dawn/1579", ToggleStage::Device}},
// Comment to separate the }} so it is clearer what to copy-paste to add a toggle.
}};
} // anonymous namespace
@ -389,77 +391,108 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{
void TogglesSet::Set(Toggle toggle, bool enabled) {
ASSERT(toggle != Toggle::InvalidEnum);
const size_t toggleIndex = static_cast<size_t>(toggle);
toggleBitset.set(toggleIndex, enabled);
bitset.set(toggleIndex, enabled);
}
bool TogglesSet::Has(Toggle toggle) const {
ASSERT(toggle != Toggle::InvalidEnum);
const size_t toggleIndex = static_cast<size_t>(toggle);
return toggleBitset.test(toggleIndex);
return bitset.test(toggleIndex);
}
std::vector<const char*> TogglesSet::GetContainedToggleNames() const {
std::vector<const char*> togglesNameInUse(toggleBitset.count());
size_t TogglesSet::Count() const {
return bitset.count();
}
uint32_t index = 0;
for (uint32_t i : IterateBitSet(toggleBitset)) {
const char* toggleName = ToggleEnumToName(static_cast<Toggle>(i));
togglesNameInUse[index] = toggleName;
++index;
TogglesSet::Iterator TogglesSet::Iterate() const {
return IterateBitSet(bitset);
}
TogglesState::TogglesState(ToggleStage stage) : mStage(stage) {}
TogglesState TogglesState::CreateFromTogglesDescriptor(const DawnTogglesDescriptor* togglesDesc,
ToggleStage requiredStage) {
TogglesState togglesState(requiredStage);
if (togglesDesc == nullptr) {
return togglesState;
}
return togglesNameInUse;
}
TripleStateTogglesSet TripleStateTogglesSet::CreateFromTogglesDescriptor(
const DawnTogglesDescriptor* togglesDesc) {
TripleStateTogglesSet userToggles;
if (togglesDesc != nullptr) {
TogglesInfo togglesInfo;
for (uint32_t i = 0; i < togglesDesc->enabledTogglesCount; ++i) {
Toggle toggle = togglesInfo.ToggleNameToEnum(togglesDesc->enabledToggles[i]);
if (toggle != Toggle::InvalidEnum) {
userToggles.togglesIsProvided.Set(toggle, true);
userToggles.providedTogglesEnabled.Set(toggle, true);
}
}
for (uint32_t i = 0; i < togglesDesc->disabledTogglesCount; ++i) {
Toggle toggle = togglesInfo.ToggleNameToEnum(togglesDesc->disabledToggles[i]);
if (toggle != Toggle::InvalidEnum) {
userToggles.togglesIsProvided.Set(toggle, true);
userToggles.providedTogglesEnabled.Set(toggle, false);
TogglesInfo togglesInfo;
for (uint32_t i = 0; i < togglesDesc->enabledTogglesCount; ++i) {
Toggle toggle = togglesInfo.ToggleNameToEnum(togglesDesc->enabledToggles[i]);
if (toggle != Toggle::InvalidEnum) {
const ToggleInfo* toggleInfo = togglesInfo.GetToggleInfo(toggle);
if (toggleInfo->stage == requiredStage) {
togglesState.mTogglesSet.Set(toggle, true);
togglesState.mEnabledToggles.Set(toggle, true);
}
}
}
return userToggles;
for (uint32_t i = 0; i < togglesDesc->disabledTogglesCount; ++i) {
Toggle toggle = togglesInfo.ToggleNameToEnum(togglesDesc->disabledToggles[i]);
if (toggle != Toggle::InvalidEnum) {
const ToggleInfo* toggleInfo = togglesInfo.GetToggleInfo(toggle);
if (toggleInfo->stage == requiredStage) {
togglesState.mTogglesSet.Set(toggle, true);
togglesState.mEnabledToggles.Set(toggle, false);
}
}
}
return togglesState;
}
void TripleStateTogglesSet::Set(Toggle toggle, bool enabled) {
// Set a toggle to given state, if the toggle has not been already set. Do nothing otherwise.
void TogglesState::Default(Toggle toggle, bool enabled) {
ASSERT(toggle != Toggle::InvalidEnum);
togglesIsProvided.Set(toggle, true);
providedTogglesEnabled.Set(toggle, enabled);
ASSERT(TogglesInfo::GetToggleInfo(toggle)->stage == mStage);
if (IsSet(toggle)) {
return;
}
mTogglesSet.Set(toggle, true);
mEnabledToggles.Set(toggle, enabled);
}
bool TripleStateTogglesSet::IsProvided(Toggle toggle) const {
return togglesIsProvided.Has(toggle);
void TogglesState::ForceSet(Toggle toggle, bool enabled) {
ASSERT(toggle != Toggle::InvalidEnum);
ASSERT(TogglesInfo::GetToggleInfo(toggle)->stage == mStage);
// Make sure that each toggle is force-set at most once.
ASSERT(!mForcedToggles.Has(toggle));
if (mTogglesSet.Has(toggle) && mEnabledToggles.Has(toggle) != enabled) {
dawn::WarningLog() << "Forcing toggle \"" << ToggleEnumToName(toggle) << "\" to " << enabled
<< " when it was " << !enabled;
}
mTogglesSet.Set(toggle, true);
mEnabledToggles.Set(toggle, enabled);
mForcedToggles.Set(toggle, true);
}
bool TogglesState::IsSet(Toggle toggle) const {
// Ensure that the toggle never used earlier than its stage.
ASSERT(TogglesInfo::GetToggleInfo(toggle)->stage <= mStage);
return mTogglesSet.Has(toggle);
}
// Return true if the toggle is provided in enable list, and false otherwise.
bool TripleStateTogglesSet::IsEnabled(Toggle toggle) const {
return togglesIsProvided.Has(toggle) && providedTogglesEnabled.Has(toggle);
}
// Return true if the toggle is provided in disable list, and false otherwise.
bool TripleStateTogglesSet::IsDisabled(Toggle toggle) const {
return togglesIsProvided.Has(toggle) && !providedTogglesEnabled.Has(toggle);
bool TogglesState::IsEnabled(Toggle toggle) const {
// Ensure that the toggle never used earlier than its stage.
ASSERT(TogglesInfo::GetToggleInfo(toggle)->stage <= mStage);
return mEnabledToggles.Has(toggle);
}
std::vector<const char*> TripleStateTogglesSet::GetEnabledToggleNames() const {
std::vector<const char*> enabledTogglesName(providedTogglesEnabled.toggleBitset.count());
ToggleStage TogglesState::GetStage() const {
return mStage;
}
std::vector<const char*> TogglesState::GetEnabledToggleNames() const {
std::vector<const char*> enabledTogglesName(mEnabledToggles.Count());
uint32_t index = 0;
for (uint32_t i : IterateBitSet(providedTogglesEnabled.toggleBitset)) {
for (uint32_t i : mEnabledToggles.Iterate()) {
const Toggle& toggle = static_cast<Toggle>(i);
// All enabled toggles must be provided.
ASSERT(togglesIsProvided.Has(toggle));
ASSERT(mTogglesSet.Has(toggle));
const char* toggleName = ToggleEnumToName(toggle);
enabledTogglesName[index] = toggleName;
++index;
@ -468,15 +501,14 @@ std::vector<const char*> TripleStateTogglesSet::GetEnabledToggleNames() const {
return enabledTogglesName;
}
std::vector<const char*> TripleStateTogglesSet::GetDisabledToggleNames() const {
std::vector<const char*> enabledTogglesName(togglesIsProvided.toggleBitset.count() -
providedTogglesEnabled.toggleBitset.count());
std::vector<const char*> TogglesState::GetDisabledToggleNames() const {
std::vector<const char*> enabledTogglesName(mTogglesSet.Count() - mEnabledToggles.Count());
uint32_t index = 0;
for (uint32_t i : IterateBitSet(togglesIsProvided.toggleBitset)) {
for (uint32_t i : mTogglesSet.Iterate()) {
const Toggle& toggle = static_cast<Toggle>(i);
// Disabled toggles are those provided but not enabled.
if (!providedTogglesEnabled.Has(toggle)) {
if (!mEnabledToggles.Has(toggle)) {
const char* toggleName = ToggleEnumToName(toggle);
enabledTogglesName[index] = toggleName;
++index;
@ -486,6 +518,11 @@ std::vector<const char*> TripleStateTogglesSet::GetDisabledToggleNames() const {
return enabledTogglesName;
}
// Allowing TogglesState to be used in cache key.
void StreamIn(stream::Sink* s, const TogglesState& togglesState) {
StreamIn(s, togglesState.mEnabledToggles.bitset);
}
const char* ToggleEnumToName(Toggle toggle) {
ASSERT(toggle != Toggle::InvalidEnum);
@ -511,6 +548,12 @@ const ToggleInfo* TogglesInfo::GetToggleInfo(const char* toggleName) {
return nullptr;
}
const ToggleInfo* TogglesInfo::GetToggleInfo(Toggle toggle) {
ASSERT(toggle != Toggle::InvalidEnum);
return &kToggleNameAndInfoList[static_cast<size_t>(toggle)].info;
}
Toggle TogglesInfo::ToggleNameToEnum(const char* toggleName) {
ASSERT(toggleName);

View File

@ -20,6 +20,7 @@
#include <unordered_map>
#include <vector>
#include "dawn/common/BitSetIterator.h"
#include "dawn/native/DawnNative.h"
namespace dawn::native {
@ -101,32 +102,57 @@ enum class Toggle {
// A wrapper of the bitset to store if a toggle is present 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;
std::bitset<static_cast<size_t>(Toggle::EnumCount)> bitset;
using Iterator = BitSetIterator<static_cast<size_t>(Toggle::EnumCount), uint32_t>;
void Set(Toggle toggle, bool enabled);
bool Has(Toggle toggle) const;
std::vector<const char*> GetContainedToggleNames() const;
size_t Count() const;
Iterator Iterate() const;
};
// TripleStateTogglesSet track each toggle with three posible states, i.e. "Not provided" (default),
// "Provided as enabled", and "Provided as disabled". This struct can be used to record the
// user-provided toggles, where some toggles are explicitly enabled or disabled while the other
// toggles are left as default.
struct TripleStateTogglesSet {
TogglesSet togglesIsProvided;
TogglesSet providedTogglesEnabled;
namespace stream {
class Sink;
}
static TripleStateTogglesSet CreateFromTogglesDescriptor(
const DawnTogglesDescriptor* togglesDesc);
// Provide a single toggle with given state.
void Set(Toggle toggle, bool enabled);
bool IsProvided(Toggle toggle) const;
// Return true if the toggle is provided in enable list, and false otherwise.
// TogglesState hold the actual state of toggles for instances, adapters and devices. Each toggle
// is of one of these states: set/default to enabled/disabled, force set to enabled/disabled, or
// left unset without default value (and thus implicitly disabled).
class TogglesState {
public:
// Create an empty toggles state of given stage
explicit TogglesState(ToggleStage stage);
// Create a RequiredTogglesSet from a DawnTogglesDescriptor, only considering toggles of
// required toggle stage.
static TogglesState CreateFromTogglesDescriptor(const DawnTogglesDescriptor* togglesDesc,
ToggleStage requiredStage);
// Set a toggle of the same stage of toggles state stage if and only if it is not already set.
void Default(Toggle toggle, bool enabled);
// Force set a toggle of same stage of toggles state stage. A force-set toggle will get
// inherited to all later stage as forced.
void ForceSet(Toggle toggle, bool enabled);
// Return whether the toggle is set or not. Force-set is always treated as set.
bool IsSet(Toggle toggle) const;
// Return true if and only if the toggle is set to true.
bool IsEnabled(Toggle toggle) const;
// Return true if the toggle is provided in disable list, and false otherwise.
bool IsDisabled(Toggle toggle) const;
ToggleStage GetStage() const;
std::vector<const char*> GetEnabledToggleNames() const;
std::vector<const char*> GetDisabledToggleNames() const;
// Friend definition of StreamIn which can be found by ADL to override stream::StreamIn<T>. This
// allows writing TogglesState to stream for cache key.
friend void StreamIn(stream::Sink* sink, const TogglesState& togglesState);
private:
// Indicating which stage of toggles state is this object holding for, instance, adapter, or
// device.
const ToggleStage mStage;
TogglesSet mTogglesSet;
TogglesSet mEnabledToggles;
TogglesSet mForcedToggles;
};
const char* ToggleEnumToName(Toggle toggle);
@ -139,6 +165,9 @@ class TogglesInfo {
// 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);
// Used to query the details of a toggle enum. The enum value must not be Toggle::InvalidEnum,
// as Toggle::InvalidEnum doesn't has corresponding ToggleInfo.
static const ToggleInfo* GetToggleInfo(Toggle toggle);
Toggle ToggleNameToEnum(const char* toggleName);
private:

View File

@ -123,18 +123,19 @@ bool Adapter::AreTimestampQueriesSupported() const {
}
void Adapter::InitializeSupportedFeaturesImpl() {
if (AreTimestampQueriesSupported()) {
mSupportedFeatures.EnableFeature(Feature::TimestampQuery);
mSupportedFeatures.EnableFeature(Feature::TimestampQueryInsidePasses);
}
mSupportedFeatures.EnableFeature(Feature::TextureCompressionBC);
mSupportedFeatures.EnableFeature(Feature::PipelineStatisticsQuery);
mSupportedFeatures.EnableFeature(Feature::MultiPlanarFormats);
mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8);
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
mSupportedFeatures.EnableFeature(Feature::RG11B10UfloatRenderable);
mSupportedFeatures.EnableFeature(Feature::DepthClipControl);
if (AreTimestampQueriesSupported()) {
mSupportedFeatures.EnableFeature(Feature::TimestampQuery);
mSupportedFeatures.EnableFeature(Feature::TimestampQueryInsidePasses);
}
mSupportedFeatures.EnableFeature(Feature::PipelineStatisticsQuery);
// Both Dp4a and ShaderF16 features require DXC version being 1.4 or higher
if (GetBackend()->IsDXCAvailableAndVersionAtLeast(1, 4, 1, 4)) {
if (mDeviceInfo.supportsDP4a) {
@ -308,14 +309,14 @@ MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
return {};
}
MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
MaybeError Adapter::ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) {
const TogglesState& deviceTogglesState) {
// shader-f16 feature and chromium-experimental-dp4a feature require DXC 1.4 or higher for
// D3D12.
if (feature == wgpu::FeatureName::ShaderF16 ||
feature == wgpu::FeatureName::ChromiumExperimentalDp4a) {
DAWN_INVALID_IF(!(userProvidedToggles.IsEnabled(Toggle::UseDXC) &&
DAWN_INVALID_IF(!(deviceTogglesState.IsEnabled(Toggle::UseDXC) &&
mBackend->IsDXCAvailableAndVersionAtLeast(1, 4, 1, 4)),
"Feature %s requires DXC for D3D12.",
GetInstance()->GetFeatureInfo(feature)->name);
@ -434,10 +435,105 @@ void Adapter::CleanUpDebugLayerFilters() {
infoQueue->PopStorageFilter();
}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
return Device::Create(this, descriptor, userProvidedToggles);
void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
const bool useResourceHeapTier2 = (GetDeviceInfo().resourceHeapTier >= 2);
deviceToggles->Default(Toggle::UseD3D12ResourceHeapTier2, useResourceHeapTier2);
deviceToggles->Default(Toggle::UseD3D12RenderPass, GetDeviceInfo().supportsRenderPass);
deviceToggles->Default(Toggle::UseD3D12ResidencyManagement, true);
deviceToggles->Default(Toggle::D3D12AlwaysUseTypelessFormatsForCastableTexture,
!GetDeviceInfo().supportsCastingFullyTypedFormat);
deviceToggles->Default(Toggle::ApplyClearBigIntegerColorValueWithDraw, true);
// The restriction on the source box specifying a portion of the depth stencil texture in
// CopyTextureRegion() is only available on the D3D12 platforms which doesn't support
// programmable sample positions.
deviceToggles->Default(
Toggle::D3D12UseTempBufferInDepthStencilTextureAndBufferCopyWithNonZeroBufferOffset,
GetDeviceInfo().programmableSamplePositionsTier == 0);
// Check DXC for use_dxc toggle, and default to use FXC
// TODO(dawn:1495): When implementing adapter toggles, promote UseDXC as adapter toggle, and do
// the validation when creating adapters.
if (!GetBackend()->IsDXCAvailable()) {
deviceToggles->ForceSet(Toggle::UseDXC, false);
}
deviceToggles->Default(Toggle::UseDXC, false);
// Disable optimizations when using FXC
// See https://crbug.com/dawn/1203
deviceToggles->Default(Toggle::FxcOptimizations, false);
// By default use the maximum shader-visible heap size allowed.
deviceToggles->Default(Toggle::UseD3D12SmallShaderVisibleHeapForTesting, false);
uint32_t deviceId = GetDeviceId();
uint32_t vendorId = GetVendorId();
// Currently this workaround is only needed on Intel Gen9, Gen9.5 and Gen11 GPUs.
// See http://crbug.com/1161355 for more information.
if (gpu_info::IsIntelGen9(vendorId, deviceId) || gpu_info::IsIntelGen11(vendorId, deviceId)) {
const gpu_info::DriverVersion kFixedDriverVersion = {31, 0, 101, 2114};
if (gpu_info::CompareWindowsDriverVersion(vendorId, GetDriverVersion(),
kFixedDriverVersion) < 0) {
deviceToggles->Default(
Toggle::UseTempBufferInSmallFormatTextureToTextureCopyFromGreaterToLessMipLevel,
true);
}
}
// Currently this workaround is only needed on Intel Gen9, Gen9.5 and Gen12 GPUs.
// See http://crbug.com/dawn/1487 for more information.
if (gpu_info::IsIntelGen9(vendorId, deviceId) || gpu_info::IsIntelGen12LP(vendorId, deviceId) ||
gpu_info::IsIntelGen12HP(vendorId, deviceId)) {
deviceToggles->Default(Toggle::D3D12ForceClearCopyableDepthStencilTextureOnCreation, true);
}
// Currently this workaround is only needed on Intel Gen12 GPUs.
// See http://crbug.com/dawn/1487 for more information.
if (gpu_info::IsIntelGen12LP(vendorId, deviceId) ||
gpu_info::IsIntelGen12HP(vendorId, deviceId)) {
deviceToggles->Default(Toggle::D3D12DontSetClearValueOnDepthTextureCreation, true);
}
// Currently this workaround is needed on any D3D12 backend for some particular situations.
// But we may need to limit it if D3D12 runtime fixes the bug on its new release. See
// https://crbug.com/dawn/1289 for more information.
// TODO(dawn:1289): Unset this toggle when we skip the split on the buffer-texture copy
// on the platforms where UnrestrictedBufferTextureCopyPitchSupported is true.
deviceToggles->Default(Toggle::D3D12SplitBufferTextureCopyForRowsPerImagePaddings, true);
// This workaround is only needed on Intel Gen12LP with driver prior to 30.0.101.1692.
// See http://crbug.com/dawn/949 for more information.
if (gpu_info::IsIntelGen12LP(vendorId, deviceId)) {
const gpu_info::DriverVersion kFixedDriverVersion = {30, 0, 101, 1692};
if (gpu_info::CompareWindowsDriverVersion(vendorId, GetDriverVersion(),
kFixedDriverVersion) == -1) {
deviceToggles->Default(Toggle::D3D12AllocateExtraMemoryFor2DArrayColorTexture, true);
}
}
// Currently these workarounds are only needed on Intel Gen9.5 and Gen11 GPUs.
// See http://crbug.com/1237175 and http://crbug.com/dawn/1628 for more information.
if ((gpu_info::IsIntelGen9(vendorId, deviceId) && !gpu_info::IsSkylake(deviceId)) ||
gpu_info::IsIntelGen11(vendorId, deviceId)) {
deviceToggles->Default(
Toggle::D3D12Allocate2DTextureWithCopyDstOrRenderAttachmentAsCommittedResource, true);
// Now we don't need to force clearing depth stencil textures with CopyDst as all the depth
// stencil textures (can only be 2D textures) will be created with CreateCommittedResource()
// instead of CreatePlacedResource().
deviceToggles->Default(Toggle::D3D12ForceClearCopyableDepthStencilTextureOnCreation, false);
}
// Currently this toggle is only needed on Intel Gen9 and Gen9.5 GPUs.
// See http://crbug.com/dawn/1579 for more information.
if (gpu_info::IsIntelGen9(vendorId, deviceId)) {
deviceToggles->ForceSet(Toggle::NoWorkaroundDstAlphaBlendDoesNotWork, true);
}
}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) {
return Device::Create(this, descriptor, deviceToggles);
}
// Resets the backend device and creates a new one. If any D3D12 objects belonging to the

View File

@ -38,9 +38,11 @@ class Adapter : public AdapterBase {
ComPtr<ID3D12Device> GetDevice() const;
private:
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) override;
void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) override;
MaybeError ResetInternalDeviceForTestingImpl() override;
bool AreTimestampQueriesSupported() const;
@ -49,9 +51,9 @@ class Adapter : public AdapterBase {
void InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
MaybeError ValidateFeatureSupportedWithTogglesImpl(
MaybeError ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) override;
const TogglesState& deviceTogglesState) override;
MaybeError InitializeDebugLayerFilters();
void CleanUpDebugLayerFilters();

View File

@ -64,15 +64,13 @@ static constexpr uint64_t kMaxDebugMessagesToPrint = 5;
// static
ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
Ref<Device> device = AcquireRef(new Device(adapter, descriptor, userProvidedToggles));
const TogglesState& deviceToggles) {
Ref<Device> device = AcquireRef(new Device(adapter, descriptor, deviceToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
InitTogglesFromDriver();
mD3d12Device = ToBackend(GetAdapter())->GetDevice();
ASSERT(mD3d12Device != nullptr);
@ -179,9 +177,8 @@ MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
// device initialization to call NextSerial
DAWN_TRY(NextSerial());
// The environment can only use DXC when it's available. Override the decision if it is not
// applicable.
DAWN_TRY(ApplyUseDxcToggle());
// Ensure DXC if use_dxc toggle is set.
DAWN_TRY(EnsureDXCIfRequired());
DAWN_TRY(CreateZeroBuffer());
@ -233,12 +230,10 @@ ComPtr<IDXGIFactory4> Device::GetFactory() const {
return ToBackend(GetAdapter())->GetBackend()->GetFactory();
}
MaybeError Device::ApplyUseDxcToggle() {
if (!ToBackend(GetAdapter())->GetBackend()->IsDXCAvailable()) {
ForceSetToggle(Toggle::UseDXC, false);
}
// Ensure DXC if use_dxc toggles are set and validated.
MaybeError Device::EnsureDXCIfRequired() {
if (IsToggleEnabled(Toggle::UseDXC)) {
ASSERT(ToBackend(GetAdapter())->GetBackend()->IsDXCAvailable());
DAWN_TRY(ToBackend(GetAdapter())->GetBackend()->EnsureDxcCompiler());
DAWN_TRY(ToBackend(GetAdapter())->GetBackend()->EnsureDxcLibrary());
DAWN_TRY(ToBackend(GetAdapter())->GetBackend()->EnsureDxcValidator());
@ -652,94 +647,6 @@ const D3D12DeviceInfo& Device::GetDeviceInfo() const {
return ToBackend(GetAdapter())->GetDeviceInfo();
}
void Device::InitTogglesFromDriver() {
const bool useResourceHeapTier2 = (GetDeviceInfo().resourceHeapTier >= 2);
SetToggle(Toggle::UseD3D12ResourceHeapTier2, useResourceHeapTier2);
SetToggle(Toggle::UseD3D12RenderPass, GetDeviceInfo().supportsRenderPass);
SetToggle(Toggle::UseD3D12ResidencyManagement, true);
SetToggle(Toggle::UseDXC, false);
SetToggle(Toggle::D3D12AlwaysUseTypelessFormatsForCastableTexture,
!GetDeviceInfo().supportsCastingFullyTypedFormat);
SetToggle(Toggle::ApplyClearBigIntegerColorValueWithDraw, true);
// The restriction on the source box specifying a portion of the depth stencil texture in
// CopyTextureRegion() is only available on the D3D12 platforms which doesn't support
// programmable sample positions.
SetToggle(Toggle::D3D12UseTempBufferInDepthStencilTextureAndBufferCopyWithNonZeroBufferOffset,
GetDeviceInfo().programmableSamplePositionsTier == 0);
// Disable optimizations when using FXC
// See https://crbug.com/dawn/1203
SetToggle(Toggle::FxcOptimizations, false);
// By default use the maximum shader-visible heap size allowed.
SetToggle(Toggle::UseD3D12SmallShaderVisibleHeapForTesting, false);
uint32_t deviceId = GetAdapter()->GetDeviceId();
uint32_t vendorId = GetAdapter()->GetVendorId();
// Currently this workaround is only needed on Intel Gen9, Gen9.5 and Gen11 GPUs.
// See http://crbug.com/1161355 for more information.
if (gpu_info::IsIntelGen9(vendorId, deviceId) || gpu_info::IsIntelGen11(vendorId, deviceId)) {
const gpu_info::DriverVersion kFixedDriverVersion = {31, 0, 101, 2114};
if (gpu_info::CompareWindowsDriverVersion(vendorId, GetAdapter()->GetDriverVersion(),
kFixedDriverVersion) < 0) {
SetToggle(
Toggle::UseTempBufferInSmallFormatTextureToTextureCopyFromGreaterToLessMipLevel,
true);
}
}
// Currently this workaround is only needed on Intel Gen9, Gen9.5 and Gen12 GPUs.
// See http://crbug.com/dawn/1487 for more information.
if (gpu_info::IsIntelGen9(vendorId, deviceId) || gpu_info::IsIntelGen12LP(vendorId, deviceId) ||
gpu_info::IsIntelGen12HP(vendorId, deviceId)) {
SetToggle(Toggle::D3D12ForceClearCopyableDepthStencilTextureOnCreation, true);
}
// Currently this workaround is only needed on Intel Gen12 GPUs.
// See http://crbug.com/dawn/1487 for more information.
if (gpu_info::IsIntelGen12LP(vendorId, deviceId) ||
gpu_info::IsIntelGen12HP(vendorId, deviceId)) {
SetToggle(Toggle::D3D12DontSetClearValueOnDepthTextureCreation, true);
}
// Currently this workaround is needed on any D3D12 backend for some particular situations.
// But we may need to limit it if D3D12 runtime fixes the bug on its new release. See
// https://crbug.com/dawn/1289 for more information.
// TODO(dawn:1289): Unset this toggle when we skip the split on the buffer-texture copy
// on the platforms where UnrestrictedBufferTextureCopyPitchSupported is true.
SetToggle(Toggle::D3D12SplitBufferTextureCopyForRowsPerImagePaddings, true);
// This workaround is only needed on Intel Gen12LP with driver prior to 30.0.101.1692.
// See http://crbug.com/dawn/949 for more information.
if (gpu_info::IsIntelGen12LP(vendorId, deviceId)) {
const gpu_info::DriverVersion kFixedDriverVersion = {30, 0, 101, 1692};
if (gpu_info::CompareWindowsDriverVersion(vendorId, GetAdapter()->GetDriverVersion(),
kFixedDriverVersion) == -1) {
SetToggle(Toggle::D3D12AllocateExtraMemoryFor2DArrayColorTexture, true);
}
}
// Currently these workarounds are only needed on Intel Gen9.5 and Gen11 GPUs.
// See http://crbug.com/1237175 and http://crbug.com/dawn/1628 for more information.
if ((gpu_info::IsIntelGen9(vendorId, deviceId) && !gpu_info::IsSkylake(deviceId)) ||
gpu_info::IsIntelGen11(vendorId, deviceId)) {
SetToggle(Toggle::D3D12Allocate2DTextureWithCopyDstOrRenderAttachmentAsCommittedResource,
true);
// Now we don't need to force clearing depth stencil textures with CopyDst as all the depth
// stencil textures (can only be 2D textures) will be created with CreateCommittedResource()
// instead of CreatePlacedResource().
SetToggle(Toggle::D3D12ForceClearCopyableDepthStencilTextureOnCreation, false);
}
// Currently this toggle is only needed on Intel Gen9 and Gen9.5 GPUs.
// See http://crbug.com/dawn/1579 for more information.
if (gpu_info::IsIntelGen9(vendorId, deviceId)) {
SetToggle(Toggle::NoWorkaroundDstAlphaBlendDoesNotWork, true);
}
}
MaybeError Device::WaitForIdleForDestruction() {
// Immediately forget about all pending commands
mPendingCommands.Release();

View File

@ -48,7 +48,7 @@ class Device final : public DeviceBase {
public:
static ResultOrError<Ref<Device>> Create(Adapter* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles);
const TogglesState& deviceToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@ -150,8 +150,6 @@ class Device final : public DeviceBase {
ComPtr<ID3D11On12Device> GetOrCreateD3D11on12Device();
void InitTogglesFromDriver();
uint32_t GetOptimalBytesPerRowAlignment() const override;
uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
@ -216,7 +214,7 @@ class Device final : public DeviceBase {
MaybeError CheckDebugLayerAndGenerateErrors();
void AppendDebugLayerMessages(ErrorData* error) override;
MaybeError ApplyUseDxcToggle();
MaybeError EnsureDXCIfRequired();
MaybeError CreateZeroBuffer();

View File

@ -290,10 +290,137 @@ class Adapter : public AdapterBase {
}
private:
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) override {
return Device::Create(this, mDevice, descriptor, userProvidedToggles);
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) override {
return Device::Create(this, mDevice, descriptor, deviceToggles);
}
void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override {
{
bool haveStoreAndMSAAResolve = false;
#if DAWN_PLATFORM_IS(MACOS)
if (@available(macOS 10.12, *)) {
haveStoreAndMSAAResolve =
[*mDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2];
}
#elif DAWN_PLATFORM_IS(IOS)
haveStoreAndMSAAResolve = [*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2];
#endif
// On tvOS, we would need MTLFeatureSet_tvOS_GPUFamily2_v1.
deviceToggles->Default(Toggle::EmulateStoreAndMSAAResolve, !haveStoreAndMSAAResolve);
bool haveSamplerCompare = true;
#if DAWN_PLATFORM_IS(IOS)
haveSamplerCompare = [*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
#endif
// TODO(crbug.com/dawn/342): Investigate emulation -- possibly expensive.
deviceToggles->Default(Toggle::MetalDisableSamplerCompare, !haveSamplerCompare);
bool haveBaseVertexBaseInstance = true;
#if DAWN_PLATFORM_IS(IOS)
haveBaseVertexBaseInstance =
[*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
#endif
// TODO(crbug.com/dawn/343): Investigate emulation.
deviceToggles->Default(Toggle::DisableBaseVertex, !haveBaseVertexBaseInstance);
deviceToggles->Default(Toggle::DisableBaseInstance, !haveBaseVertexBaseInstance);
}
// Vertex buffer robustness is implemented by using programmable vertex pulling. Enable
// that code path if it isn't explicitly disabled.
if (!deviceToggles->IsEnabled(Toggle::DisableRobustness)) {
deviceToggles->Default(Toggle::MetalEnableVertexPulling, true);
}
// TODO(crbug.com/dawn/846): tighten this workaround when the driver bug is fixed.
deviceToggles->Default(Toggle::AlwaysResolveIntoZeroLevelAndLayer, true);
uint32_t deviceId = GetDeviceId();
uint32_t vendorId = GetVendorId();
// TODO(crbug.com/dawn/847): Use MTLStorageModeShared instead of MTLStorageModePrivate when
// creating MTLCounterSampleBuffer in QuerySet on Intel platforms, otherwise it fails to
// create the buffer. Change to use MTLStorageModePrivate when the bug is fixed.
if (@available(macOS 10.15, iOS 14.0, *)) {
bool useSharedMode = gpu_info::IsIntel(vendorId);
deviceToggles->Default(Toggle::MetalUseSharedModeForCounterSampleBuffer, useSharedMode);
}
// Rendering R8Unorm and RG8Unorm to small mip doesn't work properly on Intel.
// TODO(crbug.com/dawn/1071): Tighten the workaround when this issue is fixed.
if (gpu_info::IsIntel(vendorId)) {
deviceToggles->Default(Toggle::MetalRenderR8RG8UnormSmallMipToTempTexture, true);
}
// On some Intel GPUs vertex only render pipeline get wrong depth result if no fragment
// shader provided. Create a placeholder fragment shader module to work around this issue.
if (gpu_info::IsIntel(vendorId)) {
bool usePlaceholderFragmentShader = true;
if (gpu_info::IsSkylake(deviceId)) {
usePlaceholderFragmentShader = false;
}
deviceToggles->Default(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline,
usePlaceholderFragmentShader);
}
// On some Intel GPUs using big integer values as clear values in render pass doesn't work
// correctly. Currently we have to add workaround for this issue by enabling the toggle
// "apply_clear_big_integer_color_value_with_draw". See https://crbug.com/dawn/1109 and
// https://crbug.com/dawn/1463 for more details.
if (gpu_info::IsIntel(vendorId)) {
deviceToggles->Default(Toggle::ApplyClearBigIntegerColorValueWithDraw, true);
}
// TODO(dawn:1473): Metal fails to store GPU counters to sampleBufferAttachments on empty
// encoders on macOS 11.0+, we need to add mock blit command to blit encoder when encoding
// writeTimestamp as workaround by enabling the toggle
// "metal_use_mock_blit_encoder_for_write_timestamp".
if (@available(macos 11.0, iOS 14.0, *)) {
deviceToggles->Default(Toggle::MetalUseMockBlitEncoderForWriteTimestamp, true);
}
#if DAWN_PLATFORM_IS(MACOS)
if (gpu_info::IsIntel(vendorId)) {
deviceToggles->Default(
Toggle::MetalUseBothDepthAndStencilAttachmentsForCombinedDepthStencilFormats, true);
deviceToggles->Default(Toggle::UseBlitForBufferToStencilTextureCopy, true);
deviceToggles->Default(Toggle::UseBlitForBufferToDepthTextureCopy, true);
deviceToggles->Default(Toggle::UseBlitForDepthTextureToTextureCopyToNonzeroSubresource,
true);
if ([NSProcessInfo.processInfo
isOperatingSystemAtLeastVersion:NSOperatingSystemVersion{12, 0, 0}]) {
deviceToggles->ForceSet(
Toggle::NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget, true);
}
if (gpu_info::IsIntelGen7(vendorId, deviceId) ||
gpu_info::IsIntelGen8(vendorId, deviceId)) {
deviceToggles->ForceSet(Toggle::NoWorkaroundIndirectBaseVertexNotApplied, true);
}
}
if (gpu_info::IsAMD(vendorId) || gpu_info::IsIntel(vendorId)) {
deviceToggles->Default(Toggle::MetalUseCombinedDepthStencilFormatForStencil8, true);
}
// Local testing shows the workaround is needed on AMD Radeon HD 8870M (gcn-1) MacOS 12.1;
// not on AMD Radeon Pro 555 (gcn-4) MacOS 13.1.
// Conservatively enable the workaround on AMD unless the system is MacOS 13.1+
// with architecture at least AMD gcn-4.
bool isLessThanAMDGN4OrMac13Dot1 = false;
if (gpu_info::IsAMDGCN1(vendorId, deviceId) || gpu_info::IsAMDGCN2(vendorId, deviceId) ||
gpu_info::IsAMDGCN3(vendorId, deviceId)) {
isLessThanAMDGN4OrMac13Dot1 = true;
} else if (gpu_info::IsAMD(vendorId)) {
if (@available(macos 13.1, *)) {
} else {
isLessThanAMDGN4OrMac13Dot1 = true;
}
}
if (isLessThanAMDGN4OrMac13Dot1) {
deviceToggles->Default(
Toggle::MetalUseBothDepthAndStencilAttachmentsForCombinedDepthStencilFormats, true);
}
#endif
}
MaybeError InitializeImpl() override { return {}; }
@ -625,9 +752,9 @@ class Adapter : public AdapterBase {
return {};
}
MaybeError ValidateFeatureSupportedWithTogglesImpl(
MaybeError ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) override {
const TogglesState& deviceToggles) override {
return {};
}

View File

@ -41,7 +41,7 @@ class Device final : public DeviceBase {
static ResultOrError<Ref<Device>> Create(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles);
const TogglesState& deviceToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@ -91,7 +91,7 @@ class Device final : public DeviceBase {
Device(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles);
const TogglesState& deviceToggles);
ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;
@ -132,7 +132,6 @@ class Device final : public DeviceBase {
WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata) override;
void InitTogglesFromDriver();
void DestroyImpl() override;
MaybeError WaitForIdleForDestruction() override;
bool HasPendingCommands() const override;

View File

@ -107,9 +107,9 @@ void API_AVAILABLE(macos(10.15), ios(14)) UpdateTimestampPeriod(id<MTLDevice> de
ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
const TogglesState& deviceToggles) {
Ref<Device> device =
AcquireRef(new Device(adapter, std::move(mtlDevice), descriptor, userProvidedToggles));
AcquireRef(new Device(adapter, std::move(mtlDevice), descriptor, deviceToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
@ -117,8 +117,8 @@ ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
Device::Device(AdapterBase* adapter,
NSPRef<id<MTLDevice>> mtlDevice,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles)
: DeviceBase(adapter, descriptor, userProvidedToggles),
const TogglesState& deviceToggles)
: DeviceBase(adapter, descriptor, deviceToggles),
mMtlDevice(std::move(mtlDevice)),
mCompletedSerial(0) {
// On macOS < 11.0, we only can check whether counter sampling is supported, and the counter
@ -138,8 +138,6 @@ Device::~Device() {
}
MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
InitTogglesFromDriver();
mCommandQueue.Acquire([*mMtlDevice newCommandQueue]);
if (mCommandQueue == nil) {
return DAWN_INTERNAL_ERROR("Failed to allocate MTLCommandQueue.");
@ -174,131 +172,6 @@ MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
return DeviceBase::Initialize(AcquireRef(new Queue(this, &descriptor->defaultQueue)));
}
void Device::InitTogglesFromDriver() {
{
bool haveStoreAndMSAAResolve = false;
#if DAWN_PLATFORM_IS(MACOS)
if (@available(macOS 10.12, *)) {
haveStoreAndMSAAResolve =
[*mMtlDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2];
}
#elif DAWN_PLATFORM_IS(IOS)
haveStoreAndMSAAResolve = [*mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2];
#endif
// On tvOS, we would need MTLFeatureSet_tvOS_GPUFamily2_v1.
SetToggle(Toggle::EmulateStoreAndMSAAResolve, !haveStoreAndMSAAResolve);
bool haveSamplerCompare = true;
#if DAWN_PLATFORM_IS(IOS)
haveSamplerCompare = [*mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
#endif
// TODO(crbug.com/dawn/342): Investigate emulation -- possibly expensive.
SetToggle(Toggle::MetalDisableSamplerCompare, !haveSamplerCompare);
bool haveBaseVertexBaseInstance = true;
#if DAWN_PLATFORM_IS(IOS)
haveBaseVertexBaseInstance =
[*mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
#endif
// TODO(crbug.com/dawn/343): Investigate emulation.
SetToggle(Toggle::DisableBaseVertex, !haveBaseVertexBaseInstance);
SetToggle(Toggle::DisableBaseInstance, !haveBaseVertexBaseInstance);
}
// Vertex buffer robustness is implemented by using programmable vertex pulling. Enable
// that code path if it isn't explicitly disabled.
if (IsRobustnessEnabled()) {
SetToggle(Toggle::MetalEnableVertexPulling, true);
}
// TODO(crbug.com/dawn/846): tighten this workaround when the driver bug is fixed.
SetToggle(Toggle::AlwaysResolveIntoZeroLevelAndLayer, true);
uint32_t deviceId = GetAdapter()->GetDeviceId();
uint32_t vendorId = GetAdapter()->GetVendorId();
// TODO(crbug.com/dawn/847): Use MTLStorageModeShared instead of MTLStorageModePrivate when
// creating MTLCounterSampleBuffer in QuerySet on Intel platforms, otherwise it fails to
// create the buffer. Change to use MTLStorageModePrivate when the bug is fixed.
if (@available(macOS 10.15, iOS 14.0, *)) {
bool useSharedMode = gpu_info::IsIntel(vendorId);
SetToggle(Toggle::MetalUseSharedModeForCounterSampleBuffer, useSharedMode);
}
// Rendering R8Unorm and RG8Unorm to small mip doesn't work properly on Intel.
// TODO(crbug.com/dawn/1071): Tighten the workaround when this issue is fixed.
if (gpu_info::IsIntel(vendorId)) {
SetToggle(Toggle::MetalRenderR8RG8UnormSmallMipToTempTexture, true);
}
// On some Intel GPUs vertex only render pipeline get wrong depth result if no fragment
// shader provided. Create a placeholder fragment shader module to work around this issue.
if (gpu_info::IsIntel(vendorId)) {
bool usePlaceholderFragmentShader = true;
if (gpu_info::IsSkylake(deviceId)) {
usePlaceholderFragmentShader = false;
}
SetToggle(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline, usePlaceholderFragmentShader);
}
// On some Intel GPUs using big integer values as clear values in render pass doesn't work
// correctly. Currently we have to add workaround for this issue by enabling the toggle
// "apply_clear_big_integer_color_value_with_draw". See https://crbug.com/dawn/1109 and
// https://crbug.com/dawn/1463 for more details.
if (gpu_info::IsIntel(vendorId)) {
SetToggle(Toggle::ApplyClearBigIntegerColorValueWithDraw, true);
}
// TODO(dawn:1473): Metal fails to store GPU counters to sampleBufferAttachments on empty
// encoders on macOS 11.0+, we need to add mock blit command to blit encoder when encoding
// writeTimestamp as workaround by enabling the toggle
// "metal_use_mock_blit_encoder_for_write_timestamp".
if (@available(macos 11.0, iOS 14.0, *)) {
SetToggle(Toggle::MetalUseMockBlitEncoderForWriteTimestamp, true);
}
#if DAWN_PLATFORM_IS(MACOS)
if (gpu_info::IsIntel(vendorId)) {
SetToggle(Toggle::MetalUseBothDepthAndStencilAttachmentsForCombinedDepthStencilFormats,
true);
SetToggle(Toggle::UseBlitForBufferToStencilTextureCopy, true);
SetToggle(Toggle::UseBlitForBufferToDepthTextureCopy, true);
SetToggle(Toggle::UseBlitForDepthTextureToTextureCopyToNonzeroSubresource, true);
if ([NSProcessInfo.processInfo
isOperatingSystemAtLeastVersion:NSOperatingSystemVersion{12, 0, 0}]) {
ForceSetToggle(Toggle::NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget, true);
}
if (gpu_info::IsIntelGen7(vendorId, deviceId) ||
gpu_info::IsIntelGen8(vendorId, deviceId)) {
ForceSetToggle(Toggle::NoWorkaroundIndirectBaseVertexNotApplied, true);
}
}
if (gpu_info::IsAMD(vendorId) || gpu_info::IsIntel(vendorId)) {
SetToggle(Toggle::MetalUseCombinedDepthStencilFormatForStencil8, true);
}
// Local testing shows the workaround is needed on AMD Radeon HD 8870M (gcn-1) MacOS 12.1;
// not on AMD Radeon Pro 555 (gcn-4) MacOS 13.1.
// Conservatively enable the workaround on AMD unless the system is MacOS 13.1+
// with architecture at least AMD gcn-4.
bool isLessThanAMDGN4OrMac13Dot1 = false;
if (gpu_info::IsAMDGCN1(vendorId, deviceId) || gpu_info::IsAMDGCN2(vendorId, deviceId) ||
gpu_info::IsAMDGCN3(vendorId, deviceId)) {
isLessThanAMDGN4OrMac13Dot1 = true;
} else if (gpu_info::IsAMD(vendorId)) {
if (@available(macos 13.1, *)) {
} else {
isLessThanAMDGN4OrMac13Dot1 = true;
}
}
if (isLessThanAMDGN4OrMac13Dot1) {
SetToggle(Toggle::MetalUseBothDepthAndStencilAttachmentsForCombinedDepthStencilFormats,
true);
}
#endif
}
ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) {
return BindGroup::Create(this, descriptor);

View File

@ -67,15 +67,16 @@ MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
return {};
}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
return Device::Create(this, descriptor, userProvidedToggles);
void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) {
return Device::Create(this, descriptor, deviceToggles);
}
MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
MaybeError Adapter::ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) {
const TogglesState& deviceToggles) {
return {};
}
@ -115,8 +116,8 @@ struct CopyFromStagingToBufferOperation : PendingOperation {
// static
ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
Ref<Device> device = AcquireRef(new Device(adapter, descriptor, userProvidedToggles));
const TogglesState& deviceToggles) {
Ref<Device> device = AcquireRef(new Device(adapter, descriptor, deviceToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}

View File

@ -90,7 +90,7 @@ class Device final : public DeviceBase {
public:
static ResultOrError<Ref<Device>> Create(Adapter* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles);
const TogglesState& deviceToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@ -185,13 +185,13 @@ class Adapter : public AdapterBase {
void InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) override;
MaybeError ValidateFeatureSupportedWithTogglesImpl(
MaybeError ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) override;
const TogglesState& deviceToggles) override;
void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) override;
};
// Helper class so |BindGroup| can allocate memory for its binding data,

View File

@ -152,20 +152,76 @@ MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
return {};
}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
const OpenGLFunctions& gl = mFunctions;
bool supportsBaseVertex = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 2);
bool supportsBaseInstance = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(4, 2);
// TODO(crbug.com/dawn/582): Use OES_draw_buffers_indexed where available.
bool supportsIndexedDrawBuffers = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 0);
bool supportsSnormRead =
gl.IsAtLeastGL(4, 4) || gl.IsGLExtensionSupported("GL_EXT_render_snorm");
bool supportsDepthRead = gl.IsAtLeastGL(3, 0) || gl.IsGLExtensionSupported("GL_NV_read_depth");
bool supportsStencilRead =
gl.IsAtLeastGL(3, 0) || gl.IsGLExtensionSupported("GL_NV_read_stencil");
bool supportsDepthStencilRead =
gl.IsAtLeastGL(3, 0) || gl.IsGLExtensionSupported("GL_NV_read_depth_stencil");
// Desktop GL supports BGRA textures via swizzling in the driver; ES requires an extension.
bool supportsBGRARead =
gl.GetVersion().IsDesktop() || gl.IsGLExtensionSupported("GL_EXT_read_format_bgra");
bool supportsSampleVariables = gl.IsAtLeastGL(4, 0) || gl.IsAtLeastGLES(3, 2) ||
gl.IsGLExtensionSupported("GL_OES_sample_variables");
// TODO(crbug.com/dawn/343): We can support the extension variants, but need to load the EXT
// procs without the extension suffix.
// We'll also need emulation of shader builtins gl_BaseVertex and gl_BaseInstance.
// supportsBaseVertex |=
// (gl.IsAtLeastGLES(2, 0) &&
// (gl.IsGLExtensionSupported("OES_draw_elements_base_vertex") ||
// gl.IsGLExtensionSupported("EXT_draw_elements_base_vertex"))) ||
// (gl.IsAtLeastGL(3, 1) && gl.IsGLExtensionSupported("ARB_draw_elements_base_vertex"));
// supportsBaseInstance |=
// (gl.IsAtLeastGLES(3, 1) && gl.IsGLExtensionSupported("EXT_base_instance")) ||
// (gl.IsAtLeastGL(3, 1) && gl.IsGLExtensionSupported("ARB_base_instance"));
// TODO(crbug.com/dawn/343): Investigate emulation.
deviceToggles->Default(Toggle::DisableBaseVertex, !supportsBaseVertex);
deviceToggles->Default(Toggle::DisableBaseInstance, !supportsBaseInstance);
deviceToggles->Default(Toggle::DisableIndexedDrawBuffers, !supportsIndexedDrawBuffers);
deviceToggles->Default(Toggle::DisableSnormRead, !supportsSnormRead);
deviceToggles->Default(Toggle::DisableDepthRead, !supportsDepthRead);
deviceToggles->Default(Toggle::DisableStencilRead, !supportsStencilRead);
deviceToggles->Default(Toggle::DisableDepthStencilRead, !supportsDepthStencilRead);
deviceToggles->Default(Toggle::DisableBGRARead, !supportsBGRARead);
deviceToggles->Default(Toggle::DisableSampleVariables, !supportsSampleVariables);
deviceToggles->Default(Toggle::FlushBeforeClientWaitSync, gl.GetVersion().IsES());
// For OpenGL ES, we must use a placeholder fragment shader for vertex-only render pipeline.
deviceToggles->Default(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline,
gl.GetVersion().IsES());
}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) {
EGLenum api =
GetBackendType() == wgpu::BackendType::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API;
std::unique_ptr<Device::Context> context;
DAWN_TRY_ASSIGN(context, ContextEGL::Create(mEGLFunctions, api));
return Device::Create(this, descriptor, mFunctions, std::move(context), userProvidedToggles);
return Device::Create(this, descriptor, mFunctions, std::move(context), deviceToggles);
}
MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
MaybeError Adapter::ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) {
const TogglesState& deviceToggles) {
return {};
}
} // namespace dawn::native::opengl

View File

@ -36,13 +36,14 @@ class Adapter : public AdapterBase {
MaybeError InitializeImpl() override;
void InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) override;
MaybeError ValidateFeatureSupportedWithTogglesImpl(
MaybeError ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) override;
const TogglesState& deviceTogglesState) override;
void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) override;
OpenGLFunctions mFunctions;
EGLFunctions mEGLFunctions;

View File

@ -108,9 +108,9 @@ ResultOrError<Ref<Device>> Device::Create(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions,
std::unique_ptr<Context> context,
const TripleStateTogglesSet& userProvidedToggles) {
Ref<Device> device = AcquireRef(
new Device(adapter, descriptor, functions, std::move(context), userProvidedToggles));
const TogglesState& deviceToggles) {
Ref<Device> device =
AcquireRef(new Device(adapter, descriptor, functions, std::move(context), deviceToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
@ -119,8 +119,8 @@ Device::Device(AdapterBase* adapter,
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions,
std::unique_ptr<Context> context,
const TripleStateTogglesSet& userProvidedToggles)
: DeviceBase(adapter, descriptor, userProvidedToggles),
const TogglesState& deviceToggles)
: DeviceBase(adapter, descriptor, deviceToggles),
mGL(functions),
mContext(std::move(context)) {}
@ -130,7 +130,7 @@ Device::~Device() {
MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
const OpenGLFunctions& gl = GetGL();
InitTogglesFromDriver();
mFormatTable = BuildGLFormatTable(GetBGRAInternalFormat());
// Use the debug output functionality to get notified about GL errors
@ -177,62 +177,6 @@ MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
return DeviceBase::Initialize(AcquireRef(new Queue(this, &descriptor->defaultQueue)));
}
void Device::InitTogglesFromDriver() {
const OpenGLFunctions& gl = GetGL();
bool supportsBaseVertex = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 2);
bool supportsBaseInstance = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(4, 2);
// TODO(crbug.com/dawn/582): Use OES_draw_buffers_indexed where available.
bool supportsIndexedDrawBuffers = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 0);
bool supportsSnormRead =
gl.IsAtLeastGL(4, 4) || gl.IsGLExtensionSupported("GL_EXT_render_snorm");
bool supportsDepthRead = gl.IsAtLeastGL(3, 0) || gl.IsGLExtensionSupported("GL_NV_read_depth");
bool supportsStencilRead =
gl.IsAtLeastGL(3, 0) || gl.IsGLExtensionSupported("GL_NV_read_stencil");
bool supportsDepthStencilRead =
gl.IsAtLeastGL(3, 0) || gl.IsGLExtensionSupported("GL_NV_read_depth_stencil");
// Desktop GL supports BGRA textures via swizzling in the driver; ES requires an extension.
bool supportsBGRARead =
gl.GetVersion().IsDesktop() || gl.IsGLExtensionSupported("GL_EXT_read_format_bgra");
bool supportsSampleVariables = gl.IsAtLeastGL(4, 0) || gl.IsAtLeastGLES(3, 2) ||
gl.IsGLExtensionSupported("GL_OES_sample_variables");
// TODO(crbug.com/dawn/343): We can support the extension variants, but need to load the EXT
// procs without the extension suffix.
// We'll also need emulation of shader builtins gl_BaseVertex and gl_BaseInstance.
// supportsBaseVertex |=
// (gl.IsAtLeastGLES(2, 0) &&
// (gl.IsGLExtensionSupported("OES_draw_elements_base_vertex") ||
// gl.IsGLExtensionSupported("EXT_draw_elements_base_vertex"))) ||
// (gl.IsAtLeastGL(3, 1) && gl.IsGLExtensionSupported("ARB_draw_elements_base_vertex"));
// supportsBaseInstance |=
// (gl.IsAtLeastGLES(3, 1) && gl.IsGLExtensionSupported("EXT_base_instance")) ||
// (gl.IsAtLeastGL(3, 1) && gl.IsGLExtensionSupported("ARB_base_instance"));
// TODO(crbug.com/dawn/343): Investigate emulation.
SetToggle(Toggle::DisableBaseVertex, !supportsBaseVertex);
SetToggle(Toggle::DisableBaseInstance, !supportsBaseInstance);
SetToggle(Toggle::DisableIndexedDrawBuffers, !supportsIndexedDrawBuffers);
SetToggle(Toggle::DisableSnormRead, !supportsSnormRead);
SetToggle(Toggle::DisableDepthRead, !supportsDepthRead);
SetToggle(Toggle::DisableStencilRead, !supportsStencilRead);
SetToggle(Toggle::DisableDepthStencilRead, !supportsDepthStencilRead);
SetToggle(Toggle::DisableBGRARead, !supportsBGRARead);
SetToggle(Toggle::DisableSampleVariables, !supportsSampleVariables);
SetToggle(Toggle::FlushBeforeClientWaitSync, gl.GetVersion().IsES());
// For OpenGL ES, we must use a placeholder fragment shader for vertex-only render pipeline.
SetToggle(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline, gl.GetVersion().IsES());
}
const GLFormat& Device::GetGLFormat(const Format& format) {
ASSERT(format.isSupported);
ASSERT(format.GetIndex() < mFormatTable.size());

View File

@ -44,7 +44,7 @@ class Device final : public DeviceBase {
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions,
std::unique_ptr<Context> context,
const TripleStateTogglesSet& userProvidedToggles);
const TogglesState& deviceToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@ -95,7 +95,7 @@ class Device final : public DeviceBase {
const DeviceDescriptor* descriptor,
const OpenGLFunctions& functions,
std::unique_ptr<Context> context,
const TripleStateTogglesSet& userProvidedToggles);
const TogglesState& deviceToggless);
ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;
@ -127,7 +127,6 @@ class Device final : public DeviceBase {
Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
void InitTogglesFromDriver();
GLenum GetBGRAInternalFormat() const;
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
void DestroyImpl() override;

View File

@ -77,7 +77,7 @@ VulkanInstance* Adapter::GetVulkanInstance() const {
return mVulkanInstance.Get();
}
bool Adapter::IsDepthStencilFormatSupported(VkFormat format) {
bool Adapter::IsDepthStencilFormatSupported(VkFormat format) const {
ASSERT(format == VK_FORMAT_D16_UNORM_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT ||
format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_S8_UINT);
@ -440,20 +440,70 @@ bool Adapter::SupportsExternalImages() const {
mVulkanInstance->GetFunctions());
}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
return Device::Create(this, descriptor, userProvidedToggles);
void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
// TODO(crbug.com/dawn/857): tighten this workaround when this issue is fixed in both
// Vulkan SPEC and drivers.
deviceToggles->Default(Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy, true);
if (IsAndroidQualcomm()) {
// dawn:1564: Clearing a depth/stencil buffer in a render pass and then sampling it in a
// compute pass in the same command buffer causes a crash on Qualcomm GPUs. To work around
// that bug, split the command buffer any time we can detect that situation.
deviceToggles->Default(
Toggle::VulkanSplitCommandBufferOnDepthStencilComputeSampleAfterRenderPass, true);
// dawn:1569: Qualcomm devices have a bug resolving into a non-zero level of an array
// texture. Work around it by resolving into a single level texture and then copying into
// the intended layer.
deviceToggles->Default(Toggle::AlwaysResolveIntoZeroLevelAndLayer, true);
}
// The environment can request to various options for depth-stencil formats that could be
// unavailable. Override the decision if it is not applicable.
bool supportsD32s8 = IsDepthStencilFormatSupported(VK_FORMAT_D32_SFLOAT_S8_UINT);
bool supportsD24s8 = IsDepthStencilFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT);
bool supportsS8 = IsDepthStencilFormatSupported(VK_FORMAT_S8_UINT);
ASSERT(supportsD32s8 || supportsD24s8);
if (!supportsD24s8) {
deviceToggles->ForceSet(Toggle::VulkanUseD32S8, true);
}
if (!supportsD32s8) {
deviceToggles->ForceSet(Toggle::VulkanUseD32S8, false);
}
// By default try to use D32S8 for Depth24PlusStencil8
deviceToggles->Default(Toggle::VulkanUseD32S8, true);
if (!supportsS8) {
deviceToggles->ForceSet(Toggle::VulkanUseS8, false);
}
// By default try to use S8 if available.
deviceToggles->Default(Toggle::VulkanUseS8, true);
// The environment can only request to use VK_KHR_zero_initialize_workgroup_memory when the
// extension is available. Override the decision if it is no applicable.
if (!GetDeviceInfo().HasExt(DeviceExt::ZeroInitializeWorkgroupMemory)) {
deviceToggles->ForceSet(Toggle::VulkanUseZeroInitializeWorkgroupMemoryExtension, false);
}
// By default try to initialize workgroup memory with OpConstantNull according to the Vulkan
// extension VK_KHR_zero_initialize_workgroup_memory.
deviceToggles->Default(Toggle::VulkanUseZeroInitializeWorkgroupMemoryExtension, true);
}
MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) {
return Device::Create(this, descriptor, deviceToggles);
}
MaybeError Adapter::ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) {
const TogglesState& deviceToggles) {
return {};
}
// Android devices with Qualcomm GPUs have a myriad of known issues. (dawn:1549)
bool Adapter::IsAndroidQualcomm() {
bool Adapter::IsAndroidQualcomm() const {
#if DAWN_PLATFORM_IS(ANDROID)
return gpu_info::IsQualcomm(GetVendorId());
#else

View File

@ -39,22 +39,22 @@ class Adapter : public AdapterBase {
VkPhysicalDevice GetPhysicalDevice() const;
VulkanInstance* GetVulkanInstance() const;
bool IsDepthStencilFormatSupported(VkFormat format);
bool IsDepthStencilFormatSupported(VkFormat format) const;
bool IsAndroidQualcomm();
bool IsAndroidQualcomm() const;
private:
MaybeError InitializeImpl() override;
void InitializeSupportedFeaturesImpl() override;
MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) override;
MaybeError ValidateFeatureSupportedWithTogglesImpl(
MaybeError ValidateFeatureSupportedWithDeviceTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) override;
const TogglesState& deviceToggles) override;
void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) override;
VkPhysicalDevice mPhysicalDevice;
Ref<VulkanInstance> mVulkanInstance;

View File

@ -90,19 +90,16 @@ void DestroyCommandPoolAndBuffer(const VulkanFunctions& fn,
// static
ResultOrError<Ref<Device>> Device::Create(Adapter* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
Ref<Device> device = AcquireRef(new Device(adapter, descriptor, userProvidedToggles));
const TogglesState& deviceToggles) {
Ref<Device> device = AcquireRef(new Device(adapter, descriptor, deviceToggles));
DAWN_TRY(device->Initialize(descriptor));
return device;
}
Device::Device(Adapter* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles)
: DeviceBase(adapter, descriptor, userProvidedToggles),
mDebugPrefix(GetNextDeviceDebugPrefix()) {
InitTogglesFromDriver();
}
const TogglesState& deviceToggles)
: DeviceBase(adapter, descriptor, deviceToggles), mDebugPrefix(GetNextDeviceDebugPrefix()) {}
MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
// Copy the adapter's device info to the device so that we can change the "knobs"
@ -140,14 +137,6 @@ MaybeError Device::Initialize(const DeviceDescriptor* descriptor) {
DAWN_TRY(PrepareRecordingContext());
// The environment can request to various options for depth-stencil formats that could be
// unavailable. Override the decision if it is not applicable.
ApplyDepthStencilFormatToggles();
// The environment can only request to use VK_KHR_zero_initialize_workgroup_memory when the
// extension is available. Override the decision if it is no applicable.
ApplyUseZeroInitializeWorkgroupMemoryExtensionToggle();
SetLabelImpl();
ToBackend(GetAdapter())->GetVulkanInstance()->StartListeningForDeviceMessages(this);
@ -629,61 +618,6 @@ void Device::GatherQueueFromDevice() {
fn.GetDeviceQueue(mVkDevice, mQueueFamily, 0, &mQueue);
}
// Note that this function is called before mDeviceInfo is initialized.
void Device::InitTogglesFromDriver() {
// TODO(crbug.com/dawn/857): tighten this workaround when this issue is fixed in both
// Vulkan SPEC and drivers.
SetToggle(Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy, true);
// By default try to use D32S8 for Depth24PlusStencil8
SetToggle(Toggle::VulkanUseD32S8, true);
// By default try to initialize workgroup memory with OpConstantNull according to the Vulkan
// extension VK_KHR_zero_initialize_workgroup_memory.
SetToggle(Toggle::VulkanUseZeroInitializeWorkgroupMemoryExtension, true);
// By default try to use S8 if available.
SetToggle(Toggle::VulkanUseS8, true);
if (ToBackend(GetAdapter())->IsAndroidQualcomm()) {
// dawn:1564: Clearing a depth/stencil buffer in a render pass and then sampling it in a
// compute pass in the same command buffer causes a crash on Qualcomm GPUs. To work around
// that bug, split the command buffer any time we can detect that situation.
SetToggle(Toggle::VulkanSplitCommandBufferOnDepthStencilComputeSampleAfterRenderPass, true);
// dawn:1569: Qualcomm devices have a bug resolving into a non-zero level of an array
// texture. Work around it by resolving into a single level texture and then copying into
// the intended layer.
SetToggle(Toggle::AlwaysResolveIntoZeroLevelAndLayer, true);
}
}
void Device::ApplyDepthStencilFormatToggles() {
bool supportsD32s8 =
ToBackend(GetAdapter())->IsDepthStencilFormatSupported(VK_FORMAT_D32_SFLOAT_S8_UINT);
bool supportsD24s8 =
ToBackend(GetAdapter())->IsDepthStencilFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT);
bool supportsS8 = ToBackend(GetAdapter())->IsDepthStencilFormatSupported(VK_FORMAT_S8_UINT);
ASSERT(supportsD32s8 || supportsD24s8);
if (!supportsD24s8) {
ForceSetToggle(Toggle::VulkanUseD32S8, true);
}
if (!supportsD32s8) {
ForceSetToggle(Toggle::VulkanUseD32S8, false);
}
if (!supportsS8) {
ForceSetToggle(Toggle::VulkanUseS8, false);
}
}
void Device::ApplyUseZeroInitializeWorkgroupMemoryExtensionToggle() {
if (!mDeviceInfo.HasExt(DeviceExt::ZeroInitializeWorkgroupMemory)) {
ForceSetToggle(Toggle::VulkanUseZeroInitializeWorkgroupMemoryExtension, false);
}
}
VulkanFunctions* Device::GetMutableFunctions() {
return const_cast<VulkanFunctions*>(&fn);
}

View File

@ -45,7 +45,7 @@ class Device final : public DeviceBase {
public:
static ResultOrError<Ref<Device>> Create(Adapter* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles);
const TogglesState& deviceToggles);
~Device() override;
MaybeError Initialize(const DeviceDescriptor* descriptor);
@ -118,9 +118,7 @@ class Device final : public DeviceBase {
void ForceEventualFlushOfCommands() override;
private:
Device(Adapter* adapter,
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles);
Device(Adapter* adapter, const DeviceDescriptor* descriptor, const TogglesState& deviceToggles);
ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;
@ -163,9 +161,6 @@ class Device final : public DeviceBase {
void GatherQueueFromDevice();
uint32_t FindComputeSubgroupSize() const;
void InitTogglesFromDriver();
void ApplyDepthStencilFormatToggles();
void ApplyUseZeroInitializeWorkgroupMemoryExtensionToggle();
MaybeError CheckDebugLayerAndGenerateErrors();
void AppendDebugLayerMessages(ErrorData* error) override;

View File

@ -46,7 +46,7 @@ class DestroyObjectTests : public Test {
public:
DestroyObjectTests() : Test() {
// Skipping validation on descriptors as coverage for validation is already present.
mDevice.SetToggle(Toggle::SkipValidation, true);
mDevice.ForceSetToggleForTesting(Toggle::SkipValidation, true);
}
Ref<TextureMock> GetTexture() {

View File

@ -27,7 +27,7 @@ class DeviceMock : public DeviceBase {
public:
// Exposes some protected functions for testing purposes.
using DeviceBase::DestroyObjects;
using DeviceBase::SetToggle;
using DeviceBase::ForceSetToggleForTesting;
MOCK_METHOD(ResultOrError<Ref<CommandBufferBase>>,
CreateCommandBuffer,