Respect external clear status for Textures

Use ExternalImageDescriptor->isCleared to set the clear status of
subresources so it can be correctly lazy cleared when used.

Also remove old Wrap path that uses regular texture descriptors
since we have moved to use ExternalImageDescriptor.

Bug: chromium:1036080
Change-Id: Icb605dbf3cf3f0dc8a30287e8b9b8d9134805112
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16320
Commit-Queue: Natasha Lee <natlee@microsoft.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Natasha Lee 2020-03-06 19:05:15 +00:00 committed by Commit Bot service account
parent 2538aaf304
commit 7d20b44501
8 changed files with 54 additions and 40 deletions

View File

@ -58,15 +58,4 @@ namespace dawn_native { namespace d3d12 {
return reinterpret_cast<WGPUTexture>(texture);
}
WGPUTexture WrapSharedHandle(WGPUDevice device,
const WGPUTextureDescriptor* descriptor,
HANDLE sharedHandle,
uint64_t acquireMutexKey) {
Device* backendDevice = reinterpret_cast<Device*>(device);
ExternalImageDescriptorDXGISharedHandle externalDescriptor = {};
externalDescriptor.cTextureDescriptor = descriptor;
TextureBase* texture =
backendDevice->WrapSharedHandle(&externalDescriptor, sharedHandle, acquireMutexKey);
return reinterpret_cast<WGPUTexture>(texture);
}
}} // namespace dawn_native::d3d12

View File

@ -290,6 +290,10 @@ namespace dawn_native { namespace d3d12 {
AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedExternal));
DAWN_TRY(dawnTexture->InitializeAsExternalTexture(textureDescriptor, sharedHandle,
acquireMutexKey));
dawnTexture->SetIsSubresourceContentInitialized(descriptor->isCleared, 0,
textureDescriptor->mipLevelCount, 0,
textureDescriptor->arrayLayerCount);
return dawnTexture.Detach();
}
@ -321,9 +325,6 @@ namespace dawn_native { namespace d3d12 {
info.mMethod = AllocationMethod::kDirect;
mResourceAllocation = {info, 0, std::move(d3d12Resource)};
SetIsSubresourceContentInitialized(true, 0, descriptor->mipLevelCount, 0,
descriptor->arrayLayerCount);
return {};
}

View File

@ -39,18 +39,6 @@ namespace dawn_native { namespace metal {
return reinterpret_cast<WGPUTexture>(texture);
}
WGPUTexture WrapIOSurface(WGPUDevice cDevice,
const WGPUTextureDescriptor* cDescriptor,
IOSurfaceRef ioSurface,
uint32_t plane) {
Device* device = reinterpret_cast<Device*>(cDevice);
ExternalImageDescriptorIOSurface descriptor = {};
descriptor.cTextureDescriptor = cDescriptor;
TextureBase* texture =
device->CreateTextureWrappingIOSurface(&descriptor, ioSurface, plane);
return reinterpret_cast<WGPUTexture>(texture);
}
void WaitForCommandsToBeScheduled(WGPUDevice cDevice) {
Device* device = reinterpret_cast<Device*>(cDevice);
device->WaitForCommandsToBeScheduled();

View File

@ -349,8 +349,7 @@ namespace dawn_native { namespace metal {
plane:plane];
[mtlDesc release];
// TODO(enga): Set as uninitialized if IOSurface isn't initialized.
SetIsSubresourceContentInitialized(true, 0, 1, 0, 1);
SetIsSubresourceContentInitialized(descriptor->isCleared, 0, 1, 0, 1);
}
Texture::~Texture() {

View File

@ -42,11 +42,6 @@ namespace dawn_native { namespace d3d12 {
DAWN_NATIVE_EXPORT WGPUTexture
WrapSharedHandle(WGPUDevice device, const ExternalImageDescriptorDXGISharedHandle* descriptor);
// Note: SharedHandle must be a handle to a texture object.
DAWN_NATIVE_EXPORT WGPUTexture WrapSharedHandle(WGPUDevice device,
const WGPUTextureDescriptor* descriptor,
HANDLE sharedHandle,
uint64_t acquireMutexKey);
}} // namespace dawn_native::d3d12
#endif // DAWNNATIVE_D3D12BACKEND_H_

View File

@ -44,11 +44,6 @@ namespace dawn_native { namespace metal {
DAWN_NATIVE_EXPORT WGPUTexture
WrapIOSurface(WGPUDevice device, const ExternalImageDescriptorIOSurface* descriptor);
DAWN_NATIVE_EXPORT WGPUTexture WrapIOSurface(WGPUDevice device,
const WGPUTextureDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane);
// When making Metal interop with other APIs, we need to be careful that QueueSubmit doesn't
// mean that the operations will be visible to other APIs/Metal devices right away. macOS
// does have a global queue of graphics operations, but the command buffers are inserted there

View File

@ -301,7 +301,8 @@ class D3D12SharedHandleUsageTests : public D3D12ResourceTestBase {
wgpu::Texture* dawnTextureOut,
const wgpu::Color& clearColor,
ID3D11Texture2D** d3d11TextureOut,
IDXGIKeyedMutex** dxgiKeyedMutexOut) const {
IDXGIKeyedMutex** dxgiKeyedMutexOut,
bool isCleared = true) const {
ComPtr<ID3D11Texture2D> d3d11Texture;
HRESULT hr = mD3d11Device->CreateTexture2D(d3dDescriptor, nullptr, &d3d11Texture);
ASSERT_EQ(hr, S_OK);
@ -338,6 +339,7 @@ class D3D12SharedHandleUsageTests : public D3D12ResourceTestBase {
reinterpret_cast<const WGPUTextureDescriptor*>(dawnDescriptor);
externDesc.sharedHandle = sharedHandle;
externDesc.acquireMutexKey = 1;
externDesc.isCleared = isCleared;
WGPUTexture dawnTexture = dawn_native::d3d12::WrapSharedHandle(device.Get(), &externDesc);
*dawnTextureOut = wgpu::Texture::Acquire(dawnTexture);
@ -499,5 +501,23 @@ TEST_P(D3D12SharedHandleUsageTests, ClearTwiceInD3D12ReadbackInD3D11) {
ExpectPixelRGBA8EQ(2, d3d11Texture.Get(), dxgiKeyedMutex.Get(), d3d12ClearColor2);
}
// 1. Create and clear a D3D11 texture with clearColor
// 2. Import the texture with isCleared = false
// 3. Verify clearColor is not visible in wrapped texture
TEST_P(D3D12SharedHandleUsageTests, UnclearedTextureIsCleared) {
DAWN_SKIP_TEST_IF(UsesWire());
const wgpu::Color clearColor{1.0f, 0.0f, 0.0f, 1.0f};
wgpu::Texture dawnTexture;
ComPtr<ID3D11Texture2D> d3d11Texture;
ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex;
WrapAndClearD3D11Texture(&dawnDescriptor, &d3dDescriptor, &dawnTexture, clearColor,
&d3d11Texture, &dxgiKeyedMutex, false);
// Readback the destination texture and ensure it contains the colors we used
// to clear the source texture on the D3D device.
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), dawnTexture, 0, 0);
}
DAWN_INSTANTIATE_TEST(D3D12SharedHandleValidation, D3D12Backend());
DAWN_INSTANTIATE_TEST(D3D12SharedHandleUsageTests, D3D12Backend());

View File

@ -95,12 +95,14 @@ namespace {
public:
wgpu::Texture WrapIOSurface(const wgpu::TextureDescriptor* descriptor,
IOSurfaceRef ioSurface,
uint32_t plane) {
uint32_t plane,
bool isCleared = true) {
dawn_native::metal::ExternalImageDescriptorIOSurface externDesc;
externDesc.cTextureDescriptor =
reinterpret_cast<const WGPUTextureDescriptor*>(descriptor);
externDesc.ioSurface = ioSurface;
externDesc.plane = plane;
externDesc.isCleared = isCleared;
WGPUTexture texture = dawn_native::metal::WrapIOSurface(device.Get(), &externDesc);
return wgpu::Texture::Acquire(texture);
}
@ -442,5 +444,30 @@ TEST_P(IOSurfaceUsageTests, ClearRGBA8IOSurface) {
DoClearTest(ioSurface.get(), wgpu::TextureFormat::RGBA8Unorm, &data, sizeof(data));
}
// Test that texture with color is cleared when isCleared = false
TEST_P(IOSurfaceUsageTests, UnclearedTextureIsCleared) {
DAWN_SKIP_TEST_IF(UsesWire());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'RGBA', 4);
uint32_t data = 0x04030201;
IOSurfaceLock(ioSurface.get(), 0, nullptr);
memcpy(IOSurfaceGetBaseAddress(ioSurface.get()), &data, sizeof(data));
IOSurfaceUnlock(ioSurface.get(), 0, nullptr);
wgpu::TextureDescriptor textureDescriptor;
textureDescriptor.dimension = wgpu::TextureDimension::e2D;
textureDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
textureDescriptor.size = {1, 1, 1};
textureDescriptor.sampleCount = 1;
textureDescriptor.arrayLayerCount = 1;
textureDescriptor.mipLevelCount = 1;
textureDescriptor.usage = wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::CopySrc;
// wrap ioSurface and ensure color is not visible when isCleared set to false
wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface.get(), 0, false);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), ioSurfaceTexture, 0, 0);
}
DAWN_INSTANTIATE_TEST(IOSurfaceValidationTests, MetalBackend());
DAWN_INSTANTIATE_TEST(IOSurfaceUsageTests, MetalBackend());