blob: af227aff1854041b9b4c8f707516b4d38c721415 [file] [log] [blame]
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn/native/vulkan/AdapterVk.h"
#include <algorithm>
#include <string>
#include "dawn/common/GPUInfo.h"
#include "dawn/native/Limits.h"
#include "dawn/native/vulkan/BackendVk.h"
#include "dawn/native/vulkan/DeviceVk.h"
namespace dawn::native::vulkan {
namespace {
gpu_info::DriverVersion DecodeVulkanDriverVersion(uint32_t vendorID, uint32_t versionRaw) {
gpu_info::DriverVersion driverVersion;
switch (vendorID) {
case gpu_info::kVendorID_Nvidia:
driverVersion = {static_cast<uint16_t>((versionRaw >> 22) & 0x3FF),
static_cast<uint16_t>((versionRaw >> 14) & 0x0FF),
static_cast<uint16_t>((versionRaw >> 6) & 0x0FF),
static_cast<uint16_t>(versionRaw & 0x003F)};
break;
case gpu_info::kVendorID_Intel:
#if DAWN_PLATFORM_IS(WINDOWS)
// Windows Vulkan driver releases together with D3D driver, so they share the same
// version. But only CCC.DDDD is encoded in 32-bit driverVersion.
driverVersion = {static_cast<uint16_t>(versionRaw >> 14),
static_cast<uint16_t>(versionRaw & 0x3FFF)};
break;
#endif
default:
// Use Vulkan driver conversions for other vendors
driverVersion = {static_cast<uint16_t>(versionRaw >> 22),
static_cast<uint16_t>((versionRaw >> 12) & 0x3FF),
static_cast<uint16_t>(versionRaw & 0xFFF)};
break;
}
return driverVersion;
}
} // anonymous namespace
Adapter::Adapter(InstanceBase* instance,
VulkanInstance* vulkanInstance,
VkPhysicalDevice physicalDevice,
const TogglesState& adapterToggles)
: AdapterBase(instance, wgpu::BackendType::Vulkan, adapterToggles),
mPhysicalDevice(physicalDevice),
mVulkanInstance(vulkanInstance) {}
Adapter::~Adapter() = default;
const VulkanDeviceInfo& Adapter::GetDeviceInfo() const {
return mDeviceInfo;
}
VkPhysicalDevice Adapter::GetPhysicalDevice() const {
return mPhysicalDevice;
}
VulkanInstance* Adapter::GetVulkanInstance() const {
return mVulkanInstance.Get();
}
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);
VkFormatProperties properties;
mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(mPhysicalDevice, format,
&properties);
return properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
}
MaybeError Adapter::InitializeImpl() {
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
mDriverVersion = DecodeVulkanDriverVersion(mDeviceInfo.properties.vendorID,
mDeviceInfo.properties.driverVersion);
const std::string driverVersionStr = mDriverVersion.ToString();
#if DAWN_PLATFORM_IS(WINDOWS)
// Disable Vulkan adapter on Windows Intel driver < 30.0.101.2111 due to flaky
// issues.
const gpu_info::DriverVersion kDriverVersion({30, 0, 101, 2111});
if (gpu_info::IsIntel(mDeviceInfo.properties.vendorID) &&
gpu_info::CompareWindowsDriverVersion(mDeviceInfo.properties.vendorID, mDriverVersion,
kDriverVersion) == -1) {
return DAWN_FORMAT_INTERNAL_ERROR(
"Disable Intel Vulkan adapter on Windows driver version %s. See "
"https://crbug.com/1338622.",
driverVersionStr);
}
#endif
if (mDeviceInfo.HasExt(DeviceExt::DriverProperties)) {
mDriverDescription = mDeviceInfo.driverProperties.driverName;
if (mDeviceInfo.driverProperties.driverInfo[0] != '\0') {
mDriverDescription += std::string(": ") + mDeviceInfo.driverProperties.driverInfo;
}
// There may be no driver version in driverInfo.
if (mDriverDescription.find(driverVersionStr) == std::string::npos) {
mDriverDescription += std::string(" ") + driverVersionStr;
}
} else {
mDriverDescription = std::string("Vulkan driver version ") + driverVersionStr;
}
mDeviceId = mDeviceInfo.properties.deviceID;
mVendorId = mDeviceInfo.properties.vendorID;
mName = mDeviceInfo.properties.deviceName;
switch (mDeviceInfo.properties.deviceType) {
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
mAdapterType = wgpu::AdapterType::IntegratedGPU;
break;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
mAdapterType = wgpu::AdapterType::DiscreteGPU;
break;
case VK_PHYSICAL_DEVICE_TYPE_CPU:
mAdapterType = wgpu::AdapterType::CPU;
break;
default:
mAdapterType = wgpu::AdapterType::Unknown;
break;
}
// Check for essential Vulkan extensions and features
// Needed for viewport Y-flip.
if (!mDeviceInfo.HasExt(DeviceExt::Maintenance1)) {
return DAWN_INTERNAL_ERROR("Vulkan 1.1 or Vulkan 1.0 with KHR_Maintenance1 required.");
}
// Needed for security
if (!mDeviceInfo.features.robustBufferAccess) {
return DAWN_INTERNAL_ERROR("Vulkan robustBufferAccess feature required.");
}
if (!mDeviceInfo.features.textureCompressionBC &&
!(mDeviceInfo.features.textureCompressionETC2 &&
mDeviceInfo.features.textureCompressionASTC_LDR)) {
return DAWN_INTERNAL_ERROR(
"Vulkan textureCompressionBC feature required or both textureCompressionETC2 and "
"textureCompressionASTC required.");
}
// Needed for the respective WebGPU features.
if (!mDeviceInfo.features.depthBiasClamp) {
return DAWN_INTERNAL_ERROR("Vulkan depthBiasClamp feature required.");
}
if (!mDeviceInfo.features.fragmentStoresAndAtomics) {
return DAWN_INTERNAL_ERROR("Vulkan fragmentStoresAndAtomics feature required.");
}
if (!mDeviceInfo.features.fullDrawIndexUint32) {
return DAWN_INTERNAL_ERROR("Vulkan fullDrawIndexUint32 feature required.");
}
if (!mDeviceInfo.features.imageCubeArray) {
return DAWN_INTERNAL_ERROR("Vulkan imageCubeArray feature required.");
}
if (!mDeviceInfo.features.independentBlend) {
return DAWN_INTERNAL_ERROR("Vulkan independentBlend feature required.");
}
if (!mDeviceInfo.features.sampleRateShading) {
return DAWN_INTERNAL_ERROR("Vulkan sampleRateShading feature required.");
}
return {};
}
void Adapter::InitializeSupportedFeaturesImpl() {
// Initialize supported extensions
if (mDeviceInfo.features.textureCompressionBC == VK_TRUE) {
EnableFeature(Feature::TextureCompressionBC);
}
if (mDeviceInfo.features.textureCompressionETC2 == VK_TRUE) {
EnableFeature(Feature::TextureCompressionETC2);
}
if (mDeviceInfo.features.textureCompressionASTC_LDR == VK_TRUE) {
EnableFeature(Feature::TextureCompressionASTC);
}
if (mDeviceInfo.features.pipelineStatisticsQuery == VK_TRUE) {
EnableFeature(Feature::PipelineStatisticsQuery);
}
// TODO(dawn:1559) Resolving timestamp queries after a render pass is failing on Qualcomm-based
// Android devices.
if (mDeviceInfo.properties.limits.timestampComputeAndGraphics == VK_TRUE &&
!IsAndroidQualcomm()) {
EnableFeature(Feature::TimestampQuery);
EnableFeature(Feature::TimestampQueryInsidePasses);
}
if (IsDepthStencilFormatSupported(VK_FORMAT_D32_SFLOAT_S8_UINT)) {
EnableFeature(Feature::Depth32FloatStencil8);
}
if (mDeviceInfo.features.drawIndirectFirstInstance == VK_TRUE) {
EnableFeature(Feature::IndirectFirstInstance);
}
if (mDeviceInfo.HasExt(DeviceExt::ShaderFloat16Int8) &&
mDeviceInfo.HasExt(DeviceExt::_16BitStorage) &&
mDeviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE &&
mDeviceInfo._16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE &&
mDeviceInfo._16BitStorageFeatures.storageInputOutput16 == VK_TRUE &&
mDeviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE) {
EnableFeature(Feature::ShaderF16);
}
if (mDeviceInfo.HasExt(DeviceExt::ShaderIntegerDotProduct) &&
mDeviceInfo.shaderIntegerDotProductProperties
.integerDotProduct4x8BitPackedSignedAccelerated == VK_TRUE &&
mDeviceInfo.shaderIntegerDotProductProperties
.integerDotProduct4x8BitPackedUnsignedAccelerated == VK_TRUE) {
EnableFeature(Feature::ChromiumExperimentalDp4a);
}
// unclippedDepth=true translates to depthClipEnable=false, depthClamp=true
if (mDeviceInfo.features.depthClamp == VK_TRUE &&
mDeviceInfo.HasExt(DeviceExt::DepthClipEnable) &&
mDeviceInfo.depthClipEnableFeatures.depthClipEnable == VK_TRUE) {
EnableFeature(Feature::DepthClipControl);
}
VkFormatProperties rg11b10Properties;
mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
mPhysicalDevice, VK_FORMAT_B10G11R11_UFLOAT_PACK32, &rg11b10Properties);
if (IsSubset(static_cast<VkFormatFeatureFlags>(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
rg11b10Properties.optimalTilingFeatures)) {
EnableFeature(Feature::RG11B10UfloatRenderable);
}
VkFormatProperties bgra8unormProperties;
mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
mPhysicalDevice, VK_FORMAT_B8G8R8A8_UNORM, &bgra8unormProperties);
if (bgra8unormProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) {
EnableFeature(Feature::BGRA8UnormStorage);
}
#if DAWN_PLATFORM_IS(ANDROID) || DAWN_PLATFORM_IS(CHROMEOS)
// TODO(chromium:1258986): Precisely enable the feature by querying the device's format
// features.
EnableFeature(Feature::MultiPlanarFormats);
#endif // DAWN_PLATFORM_IS(ANDROID) || DAWN_PLATFORM_IS(CHROMEOS)
}
MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
GetDefaultLimits(&limits->v1);
CombinedLimits baseLimits = *limits;
const VkPhysicalDeviceLimits& vkLimits = mDeviceInfo.properties.limits;
#define CHECK_AND_SET_V1_LIMIT_IMPL(vulkanName, webgpuName, compareOp, msgSegment) \
do { \
if (vkLimits.vulkanName compareOp baseLimits.v1.webgpuName) { \
return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for " #webgpuName \
"." \
" VkPhysicalDeviceLimits::" #vulkanName \
" must be at " msgSegment " " + \
std::to_string(baseLimits.v1.webgpuName)); \
} \
limits->v1.webgpuName = vkLimits.vulkanName; \
} while (false)
#define CHECK_AND_SET_V1_MAX_LIMIT(vulkanName, webgpuName) \
CHECK_AND_SET_V1_LIMIT_IMPL(vulkanName, webgpuName, <, "least")
#define CHECK_AND_SET_V1_MIN_LIMIT(vulkanName, webgpuName) \
CHECK_AND_SET_V1_LIMIT_IMPL(vulkanName, webgpuName, >, "most")
CHECK_AND_SET_V1_MAX_LIMIT(maxImageDimension1D, maxTextureDimension1D);
CHECK_AND_SET_V1_MAX_LIMIT(maxImageDimension2D, maxTextureDimension2D);
CHECK_AND_SET_V1_MAX_LIMIT(maxImageDimensionCube, maxTextureDimension2D);
CHECK_AND_SET_V1_MAX_LIMIT(maxFramebufferWidth, maxTextureDimension2D);
CHECK_AND_SET_V1_MAX_LIMIT(maxFramebufferHeight, maxTextureDimension2D);
CHECK_AND_SET_V1_MAX_LIMIT(maxViewportDimensions[0], maxTextureDimension2D);
CHECK_AND_SET_V1_MAX_LIMIT(maxViewportDimensions[1], maxTextureDimension2D);
CHECK_AND_SET_V1_MAX_LIMIT(viewportBoundsRange[1], maxTextureDimension2D);
limits->v1.maxTextureDimension2D = std::min({
static_cast<uint32_t>(vkLimits.maxImageDimension2D),
static_cast<uint32_t>(vkLimits.maxImageDimensionCube),
static_cast<uint32_t>(vkLimits.maxFramebufferWidth),
static_cast<uint32_t>(vkLimits.maxFramebufferHeight),
static_cast<uint32_t>(vkLimits.maxViewportDimensions[0]),
static_cast<uint32_t>(vkLimits.maxViewportDimensions[1]),
static_cast<uint32_t>(vkLimits.viewportBoundsRange[1]),
});
CHECK_AND_SET_V1_MAX_LIMIT(maxImageDimension3D, maxTextureDimension3D);
CHECK_AND_SET_V1_MAX_LIMIT(maxImageArrayLayers, maxTextureArrayLayers);
CHECK_AND_SET_V1_MAX_LIMIT(maxBoundDescriptorSets, maxBindGroups);
CHECK_AND_SET_V1_MAX_LIMIT(maxDescriptorSetUniformBuffersDynamic,
maxDynamicUniformBuffersPerPipelineLayout);
CHECK_AND_SET_V1_MAX_LIMIT(maxDescriptorSetStorageBuffersDynamic,
maxDynamicStorageBuffersPerPipelineLayout);
CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorSampledImages,
maxSampledTexturesPerShaderStage);
CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorSamplers, maxSamplersPerShaderStage);
CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorStorageBuffers,
maxStorageBuffersPerShaderStage);
CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorStorageImages,
maxStorageTexturesPerShaderStage);
CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorUniformBuffers,
maxUniformBuffersPerShaderStage);
CHECK_AND_SET_V1_MAX_LIMIT(maxUniformBufferRange, maxUniformBufferBindingSize);
CHECK_AND_SET_V1_MAX_LIMIT(maxStorageBufferRange, maxStorageBufferBindingSize);
CHECK_AND_SET_V1_MAX_LIMIT(maxFragmentCombinedOutputResources,
maxFragmentCombinedOutputResources);
CHECK_AND_SET_V1_MIN_LIMIT(minUniformBufferOffsetAlignment, minUniformBufferOffsetAlignment);
CHECK_AND_SET_V1_MIN_LIMIT(minStorageBufferOffsetAlignment, minStorageBufferOffsetAlignment);
CHECK_AND_SET_V1_MAX_LIMIT(maxVertexInputBindings, maxVertexBuffers);
CHECK_AND_SET_V1_MAX_LIMIT(maxVertexInputAttributes, maxVertexAttributes);
if (vkLimits.maxVertexInputBindingStride < baseLimits.v1.maxVertexBufferArrayStride ||
vkLimits.maxVertexInputAttributeOffset < baseLimits.v1.maxVertexBufferArrayStride - 1) {
return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for maxVertexBufferArrayStride");
}
limits->v1.maxVertexBufferArrayStride =
std::min(vkLimits.maxVertexInputBindingStride, vkLimits.maxVertexInputAttributeOffset + 1);
if (vkLimits.maxVertexOutputComponents < baseLimits.v1.maxInterStageShaderComponents ||
vkLimits.maxFragmentInputComponents < baseLimits.v1.maxInterStageShaderComponents) {
return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for maxInterStageShaderComponents");
}
limits->v1.maxInterStageShaderComponents =
std::min(vkLimits.maxVertexOutputComponents, vkLimits.maxFragmentInputComponents);
CHECK_AND_SET_V1_MAX_LIMIT(maxComputeSharedMemorySize, maxComputeWorkgroupStorageSize);
CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupInvocations, maxComputeInvocationsPerWorkgroup);
CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupSize[0], maxComputeWorkgroupSizeX);
CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupSize[1], maxComputeWorkgroupSizeY);
CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupSize[2], maxComputeWorkgroupSizeZ);
CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupCount[0], maxComputeWorkgroupsPerDimension);
CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupCount[1], maxComputeWorkgroupsPerDimension);
CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupCount[2], maxComputeWorkgroupsPerDimension);
limits->v1.maxComputeWorkgroupsPerDimension = std::min({
vkLimits.maxComputeWorkGroupCount[0],
vkLimits.maxComputeWorkGroupCount[1],
vkLimits.maxComputeWorkGroupCount[2],
});
CHECK_AND_SET_V1_MAX_LIMIT(maxColorAttachments, maxColorAttachments);
if (!IsSubset(VkSampleCountFlags(VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT),
vkLimits.framebufferColorSampleCounts)) {
return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for framebufferColorSampleCounts");
}
if (!IsSubset(VkSampleCountFlags(VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT),
vkLimits.framebufferDepthSampleCounts)) {
return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for framebufferDepthSampleCounts");
}
if (mDeviceInfo.HasExt(DeviceExt::Maintenance3)) {
limits->v1.maxBufferSize = mDeviceInfo.propertiesMaintenance3.maxMemoryAllocationSize;
if (mDeviceInfo.propertiesMaintenance3.maxMemoryAllocationSize <
baseLimits.v1.maxBufferSize) {
return DAWN_INTERNAL_ERROR("Insufficient Vulkan maxBufferSize limit");
}
} else {
limits->v1.maxBufferSize = kAssumedMaxBufferSize;
}
// Using base limits for:
// TODO(crbug.com/dawn/1448):
// - maxInterStageShaderVariables
return {};
}
bool Adapter::SupportsExternalImages() const {
// Via dawn::native::vulkan::WrapVulkanImage
return external_memory::Service::CheckSupport(mDeviceInfo) &&
external_semaphore::Service::CheckSupport(mDeviceInfo, mPhysicalDevice,
mVulkanInstance->GetFunctions());
}
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);
}
if (IsIntelMesa() && gpu_info::IsIntelGen12LP(GetVendorId(), GetDeviceId())) {
// dawn:1688: Intel Mesa driver has a bug about reusing the VkDeviceMemory that was
// previously bound to a 2D VkImage. To work around that bug we have to disable the resource
// sub-allocation for 2D textures with CopyDst or RenderAttachment usage.
const gpu_info::DriverVersion kBuggyDriverVersion = {21, 3, 6, 0};
if (gpu_info::CompareIntelMesaDriverVersion(GetDriverVersion(), kBuggyDriverVersion) >= 0) {
deviceToggles->Default(
Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment, true);
}
// chromium:1361662: Mesa driver has a bug clearing R8 mip-leveled textures on Intel Gen12
// GPUs. Work around it by clearing the whole texture as soon as they are created.
const gpu_info::DriverVersion kFixedDriverVersion = {23, 1, 0, 0};
if (gpu_info::CompareIntelMesaDriverVersion(GetDriverVersion(), kFixedDriverVersion) < 0) {
deviceToggles->Default(Toggle::VulkanClearGen12TextureWithCCSAmbiguateOnCreation, 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);
// Inject fragment shaders in all vertex-only pipelines.
// TODO(crbug.com/dawn/1698): relax this requirement where the Vulkan spec allows.
// In particular, enable rasterizer discard if the depth-stencil stage is a no-op, and skip
// insertion of the placeholder fragment shader.
deviceToggles->Default(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline, true);
}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor,
const TogglesState& deviceToggles) {
return Device::Create(this, descriptor, deviceToggles);
}
MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(wgpu::FeatureName feature,
const TogglesState& toggles) const {
return {};
}
// Android devices with Qualcomm GPUs have a myriad of known issues. (dawn:1549)
bool Adapter::IsAndroidQualcomm() const {
#if DAWN_PLATFORM_IS(ANDROID)
return gpu_info::IsQualcomm(GetVendorId());
#else
return false;
#endif
}
bool Adapter::IsIntelMesa() const {
if (mDeviceInfo.HasExt(DeviceExt::DriverProperties)) {
return mDeviceInfo.driverProperties.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR;
}
return false;
}
} // namespace dawn::native::vulkan