diff --git a/DEPS b/DEPS index 3ad53c1c0a..8fd9da0e7e 100644 --- a/DEPS +++ b/DEPS @@ -155,7 +155,7 @@ deps = { # WebGPU CTS - not used directly by Dawn, only transitively by Chromium. 'third_party/webgpu-cts': { - 'url': '{chromium_git}/external/github.com/gpuweb/cts@fee6d96eb34b10e232bceb1e1fb7b13c28912ee1', + 'url': '{chromium_git}/external/github.com/gpuweb/cts@f19f0c38c943499913a9ab59b0fe0c26168a2368', 'condition': 'build_with_chromium', }, diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp index 843b6cfe9d..7b1526a04a 100644 --- a/src/dawn/native/Texture.cpp +++ b/src/dawn/native/Texture.cpp @@ -169,6 +169,10 @@ MaybeError ValidateSampleCount(const TextureDescriptor* descriptor, DAWN_INVALID_IF(usage & wgpu::TextureUsage::StorageBinding, "The sample count (%u) of a storage textures is not 1.", descriptor->sampleCount); + + DAWN_INVALID_IF((usage & wgpu::TextureUsage::RenderAttachment) == 0, + "The usage (%s) of a multisampled texture doesn't include (%s).", + descriptor->usage, wgpu::TextureUsage::RenderAttachment); } return {}; diff --git a/src/dawn/native/d3d12/TextureD3D12.cpp b/src/dawn/native/d3d12/TextureD3D12.cpp index 651f2d0e5f..f3aeee0e34 100644 --- a/src/dawn/native/d3d12/TextureD3D12.cpp +++ b/src/dawn/native/d3d12/TextureD3D12.cpp @@ -77,19 +77,14 @@ D3D12_RESOURCE_STATES D3D12TextureUsage(wgpu::TextureUsage usage, const Format& return resourceState; } -D3D12_RESOURCE_FLAGS D3D12ResourceFlags(wgpu::TextureUsage usage, - const Format& format, - bool isMultisampledTexture) { +D3D12_RESOURCE_FLAGS D3D12ResourceFlags(wgpu::TextureUsage usage, const Format& format) { D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE; if (usage & wgpu::TextureUsage::StorageBinding) { flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; } - // A multisampled resource must have either D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET or - // D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL set in D3D12_RESOURCE_DESC::Flags. - // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_resource_desc - if ((usage & wgpu::TextureUsage::RenderAttachment) != 0 || isMultisampledTexture) { + if (usage & wgpu::TextureUsage::RenderAttachment) { if (format.HasDepthOrStencil()) { flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; } else { @@ -591,8 +586,7 @@ MaybeError Texture::InitializeAsInternalTexture() { resourceDescriptor.SampleDesc.Count = GetSampleCount(); resourceDescriptor.SampleDesc.Quality = 0; resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - resourceDescriptor.Flags = - D3D12ResourceFlags(GetInternalUsage(), GetFormat(), IsMultisampledTexture()); + resourceDescriptor.Flags = D3D12ResourceFlags(GetInternalUsage(), GetFormat()); mD3D12ResourceFlags = resourceDescriptor.Flags; DAWN_TRY_ASSIGN(mResourceAllocation, @@ -1080,6 +1074,8 @@ MaybeError Texture::ClearTexture(CommandRecordingContext* commandContext, } } } else { + ASSERT(!IsMultisampledTexture()); + // create temp buffer with clear color to copy to the texture image TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST, range); diff --git a/src/dawn/native/metal/TextureMTL.mm b/src/dawn/native/metal/TextureMTL.mm index cf1b7a8b70..06e525b1f5 100644 --- a/src/dawn/native/metal/TextureMTL.mm +++ b/src/dawn/native/metal/TextureMTL.mm @@ -29,9 +29,7 @@ namespace dawn::native::metal { namespace { -MTLTextureUsage MetalTextureUsage(const Format& format, - wgpu::TextureUsage usage, - uint32_t sampleCount) { +MTLTextureUsage MetalTextureUsage(const Format& format, wgpu::TextureUsage usage) { MTLTextureUsage result = MTLTextureUsageUnknown; // This is 0 if (usage & (wgpu::TextureUsage::StorageBinding)) { @@ -52,8 +50,7 @@ MTLTextureUsage MetalTextureUsage(const Format& format, } } - // MTLTextureUsageRenderTarget is needed to clear multisample textures. - if (usage & (wgpu::TextureUsage::RenderAttachment) || sampleCount > 1) { + if (usage & wgpu::TextureUsage::RenderAttachment) { result |= MTLTextureUsageRenderTarget; } @@ -120,8 +117,7 @@ bool RequiresCreatingNewTextureView(const TextureBase* texture, // If the texture is created with MTLTextureUsagePixelFormatView, we need // a new view to perform format reinterpretation. - if ((MetalTextureUsage(texture->GetFormat(), texture->GetInternalUsage(), - texture->GetSampleCount()) & + if ((MetalTextureUsage(texture->GetFormat(), texture->GetInternalUsage()) & MTLTextureUsagePixelFormatView) != 0) { return true; } @@ -652,7 +648,7 @@ NSRef Texture::CreateMetalTextureDescriptor() const { // Metal only allows format reinterpretation to happen on swizzle pattern or conversion // between linear space and sRGB. For example, creating bgra8Unorm texture view on // rgba8Unorm texture or creating rgba8Unorm_srgb texture view on rgab8Unorm texture. - mtlDesc.usage = MetalTextureUsage(GetFormat(), GetInternalUsage(), GetSampleCount()); + mtlDesc.usage = MetalTextureUsage(GetFormat(), GetInternalUsage()); mtlDesc.pixelFormat = MetalPixelFormat(GetFormat().format); mtlDesc.mipmapLevelCount = GetNumMipLevels(); mtlDesc.storageMode = MTLStorageModePrivate; @@ -932,6 +928,8 @@ MaybeError Texture::ClearTexture(CommandRecordingContext* commandContext, } } } else { + ASSERT(!IsMultisampledTexture()); + // Encode a buffer to texture copy to clear each subresource. for (Aspect aspect : IterateEnumMask(range.aspects)) { // Compute the buffer size big enough to fill the largest mip. @@ -1035,8 +1033,7 @@ MaybeError TextureView::Initialize(const TextureViewDescriptor* descriptor) { MTLTextureDescriptor* mtlDesc = mtlDescRef.Get(); mtlDesc.sampleCount = texture->GetSampleCount(); - mtlDesc.usage = MetalTextureUsage(texture->GetFormat(), texture->GetInternalUsage(), - texture->GetSampleCount()); + mtlDesc.usage = MetalTextureUsage(texture->GetFormat(), texture->GetInternalUsage()); mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format); mtlDesc.mipmapLevelCount = texture->GetNumMipLevels(); mtlDesc.storageMode = kIOSurfaceStorageMode; diff --git a/src/dawn/tests/end2end/NonzeroTextureCreationTests.cpp b/src/dawn/tests/end2end/NonzeroTextureCreationTests.cpp index 33cb2c1ce0..2c29f22416 100644 --- a/src/dawn/tests/end2end/NonzeroTextureCreationTests.cpp +++ b/src/dawn/tests/end2end/NonzeroTextureCreationTests.cpp @@ -414,8 +414,7 @@ DAWN_INSTANTIATE_TEST_P( {"lazy_clear_resource_on_first_use"})}, {wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::RGBA8Unorm}, {wgpu::TextureAspect::All}, - {wgpu::TextureUsage(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding), - wgpu::TextureUsage::TextureBinding}, + {wgpu::TextureUsage(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding)}, {wgpu::TextureDimension::e2D}, {1u}, // depth or array layers {1u}, // mip count diff --git a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp index 5784a3e5a1..7f12695a75 100644 --- a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp @@ -447,6 +447,7 @@ TEST_F(BindGroupValidationTest, StorageTextureUsage) { // Multisampled texture is invalid with storage buffer binding // Regression case for crbug.com/dawn/614 where this hit an ASSERT. descriptor.sampleCount = 4; + descriptor.usage |= wgpu::TextureUsage::RenderAttachment; view = device.CreateTexture(&descriptor).CreateView(); ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, view}})); } @@ -727,7 +728,7 @@ TEST_F(BindGroupValidationTest, MultisampledTexture) { // Control case: setting a multisampled 2D texture works wgpu::TextureDescriptor textureDesc; textureDesc.sampleCount = 4; - textureDesc.usage = wgpu::TextureUsage::TextureBinding; + textureDesc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment; textureDesc.dimension = wgpu::TextureDimension::e2D; textureDesc.format = wgpu::TextureFormat::RGBA8Unorm; textureDesc.size = {1, 1, 1}; diff --git a/src/dawn/tests/unittests/validation/CopyCommandsValidationTests.cpp b/src/dawn/tests/unittests/validation/CopyCommandsValidationTests.cpp index d68cead5e6..a6403d1103 100644 --- a/src/dawn/tests/unittests/validation/CopyCommandsValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/CopyCommandsValidationTests.cpp @@ -751,8 +751,9 @@ TEST_F(CopyCommandTest_B2T, IncorrectBufferOffsetForDepthStencilTexture) { TEST_F(CopyCommandTest_B2T, CopyToMultisampledTexture) { uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1); wgpu::Buffer source = CreateBuffer(bufferSize, wgpu::BufferUsage::CopySrc); - wgpu::Texture destination = Create2DTexture(2, 2, 1, 1, wgpu::TextureFormat::RGBA8Unorm, - wgpu::TextureUsage::CopyDst, 4); + wgpu::Texture destination = + Create2DTexture(2, 2, 1, 1, wgpu::TextureFormat::RGBA8Unorm, + wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 4); TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 2, destination, 0, {0, 0, 0}, {2, 2, 1}); @@ -1387,8 +1388,9 @@ TEST_F(CopyCommandTest_T2B, IncorrectBufferOffsetForDepthStencilTexture) { // Test multisampled textures cannot be used in T2B copies. TEST_F(CopyCommandTest_T2B, CopyFromMultisampledTexture) { - wgpu::Texture source = Create2DTexture(2, 2, 1, 1, wgpu::TextureFormat::RGBA8Unorm, - wgpu::TextureUsage::CopySrc, 4); + wgpu::Texture source = + Create2DTexture(2, 2, 1, 1, wgpu::TextureFormat::RGBA8Unorm, + wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment, 4); uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1); wgpu::Buffer destination = CreateBuffer(bufferSize, wgpu::BufferUsage::CopyDst); @@ -1956,10 +1958,12 @@ TEST_F(CopyCommandTest_T2T, SrgbFormatsCompatibility) { TEST_F(CopyCommandTest_T2T, MultisampledCopies) { wgpu::Texture sourceMultiSampled1x = Create2DTexture( 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopySrc, 1); - wgpu::Texture sourceMultiSampled4x = Create2DTexture( - 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopySrc, 4); - wgpu::Texture destinationMultiSampled4x = Create2DTexture( - 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopyDst, 4); + wgpu::Texture sourceMultiSampled4x = + Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, + wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment, 4); + wgpu::Texture destinationMultiSampled4x = + Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, + wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 4); // Success when entire multisampled subresource is copied { diff --git a/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp b/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp index 489a802fa6..5a4e1ec4b2 100644 --- a/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp +++ b/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp @@ -297,7 +297,9 @@ TEST_F(CopyTextureForBrowserTest, InvalidSampleCount) { wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 1); wgpu::Texture sourceMultiSampled4x = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, - wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding, 4); + wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding | + wgpu::TextureUsage::RenderAttachment, + 4); wgpu::Texture destinationMultiSampled4x = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 4); diff --git a/src/dawn/tests/unittests/validation/InternalUsageValidationTests.cpp b/src/dawn/tests/unittests/validation/InternalUsageValidationTests.cpp index 03a70d2ced..7e03799d91 100644 --- a/src/dawn/tests/unittests/validation/InternalUsageValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/InternalUsageValidationTests.cpp @@ -115,7 +115,7 @@ TEST_F(TextureInternalUsageValidationTest, UsageValidation) { { wgpu::TextureDescriptor textureDesc = {}; textureDesc.size = {1, 1}; - textureDesc.usage = wgpu::TextureUsage::CopySrc; + textureDesc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment; textureDesc.format = wgpu::TextureFormat::RGBA8Unorm; textureDesc.sampleCount = 4; diff --git a/src/dawn/tests/unittests/validation/QueueWriteTextureValidationTests.cpp b/src/dawn/tests/unittests/validation/QueueWriteTextureValidationTests.cpp index bb098fd8a3..9829ab3fda 100644 --- a/src/dawn/tests/unittests/validation/QueueWriteTextureValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/QueueWriteTextureValidationTests.cpp @@ -322,8 +322,9 @@ TEST_F(QueueWriteTextureValidationTest, DataOffset) { TEST_F(QueueWriteTextureValidationTest, WriteToMultisampledTexture) { uint64_t dataSize = utils::RequiredBytesInCopy(256, 0, {2, 2, 1}, wgpu::TextureFormat::RGBA8Unorm); - wgpu::Texture destination = Create2DTexture({2, 2, 1}, 1, wgpu::TextureFormat::RGBA8Unorm, - wgpu::TextureUsage::CopyDst, 4); + wgpu::Texture destination = + Create2DTexture({2, 2, 1}, 1, wgpu::TextureFormat::RGBA8Unorm, + wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 4); ASSERT_DEVICE_ERROR( TestWriteTexture(dataSize, 0, 256, 2, destination, 0, {0, 0, 0}, {2, 2, 1})); diff --git a/src/dawn/tests/unittests/validation/TextureValidationTests.cpp b/src/dawn/tests/unittests/validation/TextureValidationTests.cpp index 253354b961..a4da293325 100644 --- a/src/dawn/tests/unittests/validation/TextureValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/TextureValidationTests.cpp @@ -143,9 +143,12 @@ TEST_F(TextureValidationTest, SampleCount) { { wgpu::TextureDescriptor descriptor = defaultDescriptor; descriptor.sampleCount = 4; - descriptor.usage = wgpu::TextureUsage::TextureBinding; for (wgpu::TextureFormat format : utils::kFormatsInCoreSpec) { + if (!utils::TextureFormatSupportsRendering(format)) { + continue; + } + descriptor.format = format; if (utils::TextureFormatSupportsMultisampling(format)) { device.CreateTexture(&descriptor); @@ -172,6 +175,16 @@ TEST_F(TextureValidationTest, SampleCount) { ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); } + + // It is an error to create a texture without TextureUsage::RenderAttachment usage when + // sampleCount > 1. + { + wgpu::TextureDescriptor descriptor = defaultDescriptor; + descriptor.sampleCount = 4; + descriptor.usage = wgpu::TextureUsage::TextureBinding; + + ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); + } } // Test the validation of the mip level count diff --git a/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp b/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp index 9ecd9c1dba..dd2eeae604 100644 --- a/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp @@ -41,7 +41,7 @@ wgpu::Texture Create2DArrayTexture(wgpu::Device& device, descriptor.sampleCount = sampleCount; descriptor.format = kDefaultTextureFormat; descriptor.mipLevelCount = mipLevelCount; - descriptor.usage = wgpu::TextureUsage::TextureBinding; + descriptor.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment; return device.CreateTexture(&descriptor); }