Add ExternalTexture::Refresh() and ExternalTexture::Expire()
ExternalTexture has active, expired and destroyed states.
Only active state external texture is valid to submit.
Expired state external texture can be refresh to active but
destroyed external texture cannot be refresh.
Bug: chromium:1412338
Change-Id: Ic7f12d274d27b644f19ec3ef8b46c110610afa2b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/120982
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
diff --git a/dawn.json b/dawn.json
index 993cd05..fc3b0f5 100644
--- a/dawn.json
+++ b/dawn.json
@@ -1399,6 +1399,14 @@
{
"name": "destroy",
"returns": "void"
+ },
+ {
+ "name": "expire",
+ "returns": "void"
+ },
+ {
+ "name": "refresh",
+ "returns": "void"
}
]
},
diff --git a/src/dawn/native/ExternalTexture.cpp b/src/dawn/native/ExternalTexture.cpp
index 0e64216..118b25c 100644
--- a/src/dawn/native/ExternalTexture.cpp
+++ b/src/dawn/native/ExternalTexture.cpp
@@ -133,7 +133,7 @@
: ApiObjectBase(device, descriptor->label),
mVisibleOrigin(descriptor->visibleOrigin),
mVisibleSize(descriptor->visibleSize),
- mState(ExternalTextureState::Alive) {
+ mState(ExternalTextureState::Active) {
GetObjectTrackingList()->Track(this);
}
@@ -324,8 +324,8 @@
MaybeError ExternalTextureBase::ValidateCanUseInSubmitNow() const {
ASSERT(!IsError());
- DAWN_INVALID_IF(mState == ExternalTextureState::Destroyed,
- "Destroyed external texture %s is used in a submit.", this);
+ DAWN_INVALID_IF(mState != ExternalTextureState::Active,
+ "External texture %s used in a submit is not active.", this);
for (uint32_t i = 0; i < kMaxPlanesPerFormat; ++i) {
if (mTextureViews[i] != nullptr) {
@@ -336,10 +336,33 @@
return {};
}
-void ExternalTextureBase::APIDestroy() {
- if (GetDevice()->ConsumedError(GetDevice()->ValidateObject(this))) {
+MaybeError ExternalTextureBase::ValidateRefresh() {
+ DAWN_TRY(GetDevice()->ValidateObject(this));
+ DAWN_INVALID_IF(mState == ExternalTextureState::Destroyed, "%s is destroyed.", this);
+ return {};
+}
+
+MaybeError ExternalTextureBase::ValidateExpire() {
+ DAWN_TRY(GetDevice()->ValidateObject(this));
+ DAWN_INVALID_IF(mState != ExternalTextureState::Active, "%s is not active.", this);
+ return {};
+}
+
+void ExternalTextureBase::APIRefresh() {
+ if (GetDevice()->ConsumedError(ValidateRefresh(), "calling %s.Refresh()", this)) {
return;
}
+ mState = ExternalTextureState::Active;
+}
+
+void ExternalTextureBase::APIExpire() {
+ if (GetDevice()->ConsumedError(ValidateExpire(), "calling %s.Expire()", this)) {
+ return;
+ }
+ mState = ExternalTextureState::Expired;
+}
+
+void ExternalTextureBase::APIDestroy() {
Destroy();
}
diff --git a/src/dawn/native/ExternalTexture.h b/src/dawn/native/ExternalTexture.h
index 6cdeb13..b804bf7 100644
--- a/src/dawn/native/ExternalTexture.h
+++ b/src/dawn/native/ExternalTexture.h
@@ -57,7 +57,9 @@
MaybeError ValidateCanUseInSubmitNow() const;
static ExternalTextureBase* MakeError(DeviceBase* device);
+ void APIExpire();
void APIDestroy();
+ void APIRefresh();
protected:
ExternalTextureBase(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
@@ -68,9 +70,12 @@
~ExternalTextureBase() override;
private:
- enum class ExternalTextureState { Alive, Destroyed };
+ enum class ExternalTextureState { Active, Expired, Destroyed };
ExternalTextureBase(DeviceBase* device, ObjectBase::ErrorTag tag);
+ MaybeError ValidateRefresh();
+ MaybeError ValidateExpire();
+
Ref<TextureBase> mPlaceholderTexture;
Ref<BufferBase> mParamsBuffer;
std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat> mTextureViews;
diff --git a/src/dawn/tests/unittests/validation/ExternalTextureTests.cpp b/src/dawn/tests/unittests/validation/ExternalTextureTests.cpp
index b778c03..9a424c2 100644
--- a/src/dawn/tests/unittests/validation/ExternalTextureTests.cpp
+++ b/src/dawn/tests/unittests/validation/ExternalTextureTests.cpp
@@ -34,11 +34,68 @@
return descriptor;
}
+ wgpu::ExternalTexture CreateDefaultExternalTexture() {
+ wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
+ externalDesc.plane0 = defaultTexture.CreateView();
+ return device.CreateExternalTexture(&externalDesc);
+ }
+
+ void SubmitExternalTextureInDefaultRenderPass(wgpu::ExternalTexture externalTexture,
+ bool success) {
+ // Create a bind group that contains the external texture.
+ wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
+ device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
+ wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
+
+ // Create another texture to use as a color attachment.
+ wgpu::TextureDescriptor renderTextureDescriptor = CreateTextureDescriptor();
+ wgpu::Texture renderTexture = device.CreateTexture(&renderTextureDescriptor);
+ wgpu::TextureView renderView = renderTexture.CreateView();
+
+ utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
+ pass.SetBindGroup(0, bindGroup);
+ pass.End();
+ wgpu::CommandBuffer commands = encoder.Finish();
+
+ if (success) {
+ queue.Submit(1, &commands);
+ } else {
+ ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
+ }
+ }
+
+ void SubmitExternalTextureInDefaultComputePass(wgpu::ExternalTexture externalTexture,
+ bool success) {
+ // Create a bind group that contains the external texture.
+ wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
+ device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
+ wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
+
+ wgpu::ComputePassDescriptor computePass;
+
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ wgpu::ComputePassEncoder pass = encoder.BeginComputePass(&computePass);
+ pass.SetBindGroup(0, bindGroup);
+ pass.End();
+ wgpu::CommandBuffer commands = encoder.Finish();
+
+ if (success) {
+ queue.Submit(1, &commands);
+ } else {
+ ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
+ }
+ }
+
protected:
void SetUp() override {
ValidationTest::SetUp();
queue = device.GetQueue();
+
+ wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
+ defaultTexture = device.CreateTexture(&textureDescriptor);
}
wgpu::ExternalTextureDescriptor CreateDefaultExternalTextureDescriptor() {
@@ -67,6 +124,7 @@
std::array<float, 12> mPlaceholderConstantArray;
wgpu::Queue queue;
+ wgpu::Texture defaultTexture;
};
TEST_F(ExternalTextureTest, CreateExternalTextureValidation) {
@@ -273,55 +331,85 @@
}
}
-// Test that submitting a render pass that contains a destroyed external texture results in
-// an error.
+// Test that refresh on an expired/active external texture.
+TEST_F(ExternalTextureTest, RefreshExternalTexture) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+
+ externalTexture.Refresh();
+ externalTexture.Expire();
+ externalTexture.Refresh();
+}
+
+// Test that refresh on a destroyed external texture results in an error.
+TEST_F(ExternalTextureTest, RefreshDestroyedExternalTexture) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+
+ // Refresh on destroyed external texture should result in an error.
+ externalTexture.Destroy();
+ ASSERT_DEVICE_ERROR(externalTexture.Refresh());
+}
+
+// Test that expire on a destroyed external texture results in an error.
+TEST_F(ExternalTextureTest, ExpireDestroyedExternalTexture) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+
+ externalTexture.Destroy();
+ ASSERT_DEVICE_ERROR(externalTexture.Expire());
+}
+
+// Test that submitting a render pass that contains an active external texture.
+TEST_F(ExternalTextureTest, SubmitActiveExternalTextureInRenderPass) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+ SubmitExternalTextureInDefaultRenderPass(externalTexture, true /* success = true */);
+}
+
+// Test that submitting a render pass that contains an expired external texture results in an error.
+TEST_F(ExternalTextureTest, SubmitExpiredExternalTextureInRenderPass) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+ externalTexture.Expire();
+ SubmitExternalTextureInDefaultRenderPass(externalTexture, false /* success = false */);
+}
+
+// Test that submitting a render pass that contains an destroyed external texture results in an
+// error.
TEST_F(ExternalTextureTest, SubmitDestroyedExternalTextureInRenderPass) {
- wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
- wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+ externalTexture.Destroy();
+ SubmitExternalTextureInDefaultRenderPass(externalTexture, false /* success = false */);
+}
- wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
- externalDesc.plane0 = texture.CreateView();
- wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
+// Test that submitting a compute pass that contains an active external.
+TEST_F(ExternalTextureTest, SubmitActiveExternalTextureInComputePass) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+ SubmitExternalTextureInDefaultComputePass(externalTexture, true /* success = true */);
+}
- // Create a bind group that contains the external texture.
- wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
- device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
- wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
+// Test that submitting a compute pass that contains an expired external texture results in an
+// error.
+TEST_F(ExternalTextureTest, SubmitExpiredExternalTextureInComputePass) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+ externalTexture.Expire();
+ SubmitExternalTextureInDefaultComputePass(externalTexture, false /* success = false */);
+}
- // Create another texture to use as a color attachment.
- wgpu::TextureDescriptor renderTextureDescriptor = CreateTextureDescriptor();
- wgpu::Texture renderTexture = device.CreateTexture(&renderTextureDescriptor);
- wgpu::TextureView renderView = renderTexture.CreateView();
+// Test that submitting a compute pass that contains an active external texture should success.
+TEST_F(ExternalTextureTest, SubmitDestroyedExternalTextureInComputePass) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+ externalTexture.Destroy();
+ SubmitExternalTextureInDefaultComputePass(externalTexture, false /* success = false */);
+}
- utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
+// Test that refresh an expired external texture and submit a compute pass with it.
+TEST_F(ExternalTextureTest, RefreshExpiredExternalTexture) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+ externalTexture.Expire();
- // Control case should succeed.
- {
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
- {
- pass.SetBindGroup(0, bindGroup);
- pass.End();
- }
+ // Submit with expired external texture results in error
+ SubmitExternalTextureInDefaultComputePass(externalTexture, false /* success = false */);
- wgpu::CommandBuffer commands = encoder.Finish();
-
- queue.Submit(1, &commands);
- }
-
- // Destroying the external texture should result in an error.
- {
- externalTexture.Destroy();
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
- {
- pass.SetBindGroup(0, bindGroup);
- pass.End();
- }
-
- wgpu::CommandBuffer commands = encoder.Finish();
- ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
- }
+ externalTexture.Refresh();
+ // Refreshed external texture could be submitted.
+ SubmitExternalTextureInDefaultComputePass(externalTexture, true /* success = true */);
}
// Test that submitting a render pass that contains a dereferenced external texture results in
@@ -375,148 +463,6 @@
}
}
-// Test that submitting a render pass that contains a destroyed external texture plane
-// results in an error.
-TEST_F(ExternalTextureTest, SubmitDestroyedExternalTexturePlaneInRenderPass) {
- wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
- wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
-
- wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
- externalDesc.plane0 = texture.CreateView();
- wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
-
- // Create a bind group that contains the external texture.
- wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
- device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
- wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
-
- // Create another texture to use as a color attachment.
- wgpu::TextureDescriptor renderTextureDescriptor = CreateTextureDescriptor();
- wgpu::Texture renderTexture = device.CreateTexture(&renderTextureDescriptor);
- wgpu::TextureView renderView = renderTexture.CreateView();
-
- utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
-
- // Control case should succeed.
- {
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
- {
- pass.SetBindGroup(0, bindGroup);
- pass.End();
- }
-
- wgpu::CommandBuffer commands = encoder.Finish();
-
- queue.Submit(1, &commands);
- }
-
- // Destroying an external texture underlying plane should result in an error.
- {
- texture.Destroy();
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
- {
- pass.SetBindGroup(0, bindGroup);
- pass.End();
- }
-
- wgpu::CommandBuffer commands = encoder.Finish();
- ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
- }
-}
-
-// Test that submitting a compute pass that contains a destroyed external texture results in
-// an error.
-TEST_F(ExternalTextureTest, SubmitDestroyedExternalTextureInComputePass) {
- wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
- wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
-
- wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
- externalDesc.plane0 = texture.CreateView();
- wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
-
- // Create a bind group that contains the external texture.
- wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
- device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
- wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
-
- wgpu::ComputePassDescriptor computePass;
-
- // Control case should succeed.
- {
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::ComputePassEncoder pass = encoder.BeginComputePass(&computePass);
- {
- pass.SetBindGroup(0, bindGroup);
- pass.End();
- }
-
- wgpu::CommandBuffer commands = encoder.Finish();
-
- queue.Submit(1, &commands);
- }
-
- // Destroying the external texture should result in an error.
- {
- externalTexture.Destroy();
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::ComputePassEncoder pass = encoder.BeginComputePass(&computePass);
- {
- pass.SetBindGroup(0, bindGroup);
- pass.End();
- }
-
- wgpu::CommandBuffer commands = encoder.Finish();
- ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
- }
-}
-
-// Test that submitting a compute pass that contains a destroyed external texture plane
-// results in an error.
-TEST_F(ExternalTextureTest, SubmitDestroyedExternalTexturePlaneInComputePass) {
- wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
- wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
-
- wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
- externalDesc.plane0 = texture.CreateView();
- wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
-
- // Create a bind group that contains the external texture.
- wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
- device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
- wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
-
- wgpu::ComputePassDescriptor computePass;
-
- // Control case should succeed.
- {
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::ComputePassEncoder pass = encoder.BeginComputePass(&computePass);
- {
- pass.SetBindGroup(0, bindGroup);
- pass.End();
- }
-
- wgpu::CommandBuffer commands = encoder.Finish();
- queue.Submit(1, &commands);
- }
-
- // Destroying an external texture underlying plane should result in an error.
- {
- texture.Destroy();
- wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
- wgpu::ComputePassEncoder pass = encoder.BeginComputePass(&computePass);
- {
- pass.SetBindGroup(0, bindGroup);
- pass.End();
- }
-
- wgpu::CommandBuffer commands = encoder.Finish();
- ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
- }
-}
-
// Ensure that bind group validation catches external textures mimatched from the BGL.
TEST_F(ExternalTextureTest, BindGroupDoesNotMatchLayout) {
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();