diff --git a/src/dawn/common/GPUInfo.cpp b/src/dawn/common/GPUInfo.cpp index 4b80876274..b46f2429ee 100644 --- a/src/dawn/common/GPUInfo.cpp +++ b/src/dawn/common/GPUInfo.cpp @@ -90,6 +90,16 @@ int CompareWindowsDriverVersion(PCIVendorID vendorId, return 0; } +int CompareIntelMesaDriverVersion(const DriverVersion& version1, const DriverVersion& version2) { + for (uint32_t i = 0; i < 3; ++i) { + int diff = static_cast(version1[i]) - static_cast(version2[i]); + if (diff != 0) { + return diff; + } + } + return 0; +} + // Intel GPUs bool IsSkylake(PCIDeviceID deviceId) { return std::find(Skylake.cbegin(), Skylake.cend(), deviceId) != Skylake.cend(); diff --git a/src/dawn/common/GPUInfo.h b/src/dawn/common/GPUInfo.h index 855d05cb93..dab977f08e 100644 --- a/src/dawn/common/GPUInfo.h +++ b/src/dawn/common/GPUInfo.h @@ -52,6 +52,12 @@ int CompareWindowsDriverVersion(PCIVendorID vendorId, const DriverVersion& version1, const DriverVersion& version2); +// Do comparison between two Intel Mesa driver versions. +// - Return a negative number if build number of version1 is smaller +// - Return a positive number if build number of version1 is bigger +// - Return 0 if version1 and version2 represent same driver version +int CompareIntelMesaDriverVersion(const DriverVersion& version1, const DriverVersion& version2); + // Intel architectures bool IsSkylake(PCIDeviceID deviceId); diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp index c2c105ad4b..cd802ffbda 100644 --- a/src/dawn/native/Toggles.cpp +++ b/src/dawn/native/Toggles.cpp @@ -329,11 +329,11 @@ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {{ "default on Qualcomm GPUs, which have been observed experiencing a driver crash in this " "situation.", "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.", + {Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment, + {"disable_sub_allocation_for_2d_texture_with_copy_dst_or_render_attachment", + "Disable resource sub-allocation for the 2D texture with CopyDst or RenderAttachment usage. " + "This toggle is enabled by default on D3D12 backends using Intel Gen9.5 and Gen11 GPUs and " + "on Vulkan backends using Intel Gen12 GPUs due to Intel Mesa Vulkan and D3D12 driver issues.", "https://crbug.com/1237175", ToggleStage::Device}}, {Toggle::MetalUseCombinedDepthStencilFormatForStencil8, {"metal_use_combined_depth_stencil_format_for_stencil8", diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h index 4962e3c2ac..0eab4852be 100644 --- a/src/dawn/native/Toggles.h +++ b/src/dawn/native/Toggles.h @@ -83,7 +83,7 @@ enum class Toggle { ApplyClearBigIntegerColorValueWithDraw, MetalUseMockBlitEncoderForWriteTimestamp, VulkanSplitCommandBufferOnDepthStencilComputeSampleAfterRenderPass, - D3D12Allocate2DTextureWithCopyDstOrRenderAttachmentAsCommittedResource, + DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment, MetalUseCombinedDepthStencilFormatForStencil8, MetalUseBothDepthAndStencilAttachmentsForCombinedDepthStencilFormats, MetalKeepMultisubresourceDepthStencilTexturesInitialized, diff --git a/src/dawn/native/d3d12/AdapterD3D12.cpp b/src/dawn/native/d3d12/AdapterD3D12.cpp index d56ef2f27b..ccd42bffea 100644 --- a/src/dawn/native/d3d12/AdapterD3D12.cpp +++ b/src/dawn/native/d3d12/AdapterD3D12.cpp @@ -558,7 +558,7 @@ void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const { if ((gpu_info::IsIntelGen9(vendorId, deviceId) && !gpu_info::IsSkylake(deviceId)) || gpu_info::IsIntelGen11(vendorId, deviceId)) { deviceToggles->Default( - Toggle::D3D12Allocate2DTextureWithCopyDstOrRenderAttachmentAsCommittedResource, true); + Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment, 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(). diff --git a/src/dawn/native/d3d12/TextureD3D12.cpp b/src/dawn/native/d3d12/TextureD3D12.cpp index 3c99d880c9..f87078ac72 100644 --- a/src/dawn/native/d3d12/TextureD3D12.cpp +++ b/src/dawn/native/d3d12/TextureD3D12.cpp @@ -612,7 +612,7 @@ MaybeError Texture::InitializeAsInternalTexture() { } bool forceAllocateAsCommittedResource = (device->IsToggleEnabled( - Toggle::D3D12Allocate2DTextureWithCopyDstOrRenderAttachmentAsCommittedResource)) && + Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment)) && GetDimension() == wgpu::TextureDimension::e2D && (GetInternalUsage() & (wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment)); DAWN_TRY_ASSIGN(mResourceAllocation, diff --git a/src/dawn/native/vulkan/AdapterVk.cpp b/src/dawn/native/vulkan/AdapterVk.cpp index d6a61dcd0b..cec496aa25 100644 --- a/src/dawn/native/vulkan/AdapterVk.cpp +++ b/src/dawn/native/vulkan/AdapterVk.cpp @@ -416,6 +416,17 @@ void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const { 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 kDriverVersion = {21, 3, 6, 0}; + if (gpu_info::CompareIntelMesaDriverVersion(GetDriverVersion(), kDriverVersion) >= 0) { + deviceToggles->Default( + Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment, 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); @@ -474,4 +485,11 @@ bool Adapter::IsAndroidQualcomm() const { #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 diff --git a/src/dawn/native/vulkan/AdapterVk.h b/src/dawn/native/vulkan/AdapterVk.h index 0b8226a26a..0eb9317285 100644 --- a/src/dawn/native/vulkan/AdapterVk.h +++ b/src/dawn/native/vulkan/AdapterVk.h @@ -43,6 +43,7 @@ class Adapter : public AdapterBase { bool IsDepthStencilFormatSupported(VkFormat format) const; bool IsAndroidQualcomm() const; + bool IsIntelMesa() const; private: MaybeError InitializeImpl() override; diff --git a/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.cpp b/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.cpp index 390b3262cf..ba1816eb26 100644 --- a/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.cpp +++ b/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.cpp @@ -124,7 +124,8 @@ ResourceMemoryAllocator::~ResourceMemoryAllocator() = default; ResultOrError ResourceMemoryAllocator::Allocate( const VkMemoryRequirements& requirements, - MemoryKind kind) { + MemoryKind kind, + bool forceDisableSubAllocation) { // The Vulkan spec guarantees at least on memory type is valid. int memoryType = FindBestTypeIndex(requirements, kind); ASSERT(memoryType >= 0); @@ -134,7 +135,8 @@ ResultOrError ResourceMemoryAllocator::Allocate( // Sub-allocate non-mappable resources because at the moment the mapped pointer // is part of the resource and not the heap, which doesn't match the Vulkan model. // TODO(crbug.com/dawn/849): allow sub-allocating mappable resources, maybe. - if (requirements.size < kMaxSizeForSubAllocation && kind != MemoryKind::LinearMappable && + if (!forceDisableSubAllocation && requirements.size < kMaxSizeForSubAllocation && + kind != MemoryKind::LinearMappable && !mDevice->IsToggleEnabled(Toggle::DisableResourceSuballocation)) { // When sub-allocating, Vulkan requires that we respect bufferImageGranularity. Some // hardware puts information on the memory's page table entry and allocating a linear diff --git a/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h b/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h index 1ece6d7592..2be1895980 100644 --- a/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h +++ b/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h @@ -43,7 +43,8 @@ class ResourceMemoryAllocator { ~ResourceMemoryAllocator(); ResultOrError Allocate(const VkMemoryRequirements& requirements, - MemoryKind kind); + MemoryKind kind, + bool forceDisableSubAllocation = false); void Deallocate(ResourceMemoryAllocation* allocation); void DestroyPool(); diff --git a/src/dawn/native/vulkan/TextureVk.cpp b/src/dawn/native/vulkan/TextureVk.cpp index b15b9bef2d..2e767a74fd 100644 --- a/src/dawn/native/vulkan/TextureVk.cpp +++ b/src/dawn/native/vulkan/TextureVk.cpp @@ -730,8 +730,14 @@ MaybeError Texture::InitializeAsInternalTexture(VkImageUsageFlags extraUsages) { VkMemoryRequirements requirements; device->fn.GetImageMemoryRequirements(device->GetVkDevice(), mHandle, &requirements); - DAWN_TRY_ASSIGN(mMemoryAllocation, device->GetResourceMemoryAllocator()->Allocate( - requirements, MemoryKind::Opaque)); + bool forceDisableSubAllocation = + (device->IsToggleEnabled( + Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment)) && + GetDimension() == wgpu::TextureDimension::e2D && + (GetInternalUsage() & (wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment)); + DAWN_TRY_ASSIGN(mMemoryAllocation, + device->GetResourceMemoryAllocator()->Allocate(requirements, MemoryKind::Opaque, + forceDisableSubAllocation)); DAWN_TRY(CheckVkSuccess( device->fn.BindImageMemory(device->GetVkDevice(), mHandle,