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>
This commit is contained in:
parent
dd0332ec91
commit
e958db0490
|
@ -1399,6 +1399,14 @@
|
|||
{
|
||||
"name": "destroy",
|
||||
"returns": "void"
|
||||
},
|
||||
{
|
||||
"name": "expire",
|
||||
"returns": "void"
|
||||
},
|
||||
{
|
||||
"name": "refresh",
|
||||
"returns": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -133,7 +133,7 @@ ExternalTextureBase::ExternalTextureBase(DeviceBase* device,
|
|||
: ApiObjectBase(device, descriptor->label),
|
||||
mVisibleOrigin(descriptor->visibleOrigin),
|
||||
mVisibleSize(descriptor->visibleSize),
|
||||
mState(ExternalTextureState::Alive) {
|
||||
mState(ExternalTextureState::Active) {
|
||||
GetObjectTrackingList()->Track(this);
|
||||
}
|
||||
|
||||
|
@ -324,8 +324,8 @@ const std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat>& ExternalTextureBase
|
|||
|
||||
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 @@ MaybeError ExternalTextureBase::ValidateCanUseInSubmitNow() const {
|
|||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,9 @@ class ExternalTextureBase : public ApiObjectBase {
|
|||
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 @@ class ExternalTextureBase : public ApiObjectBase {
|
|||
~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;
|
||||
|
|
|
@ -34,11 +34,68 @@ class ExternalTextureTest : public ValidationTest {
|
|||
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 @@ class ExternalTextureTest : public ValidationTest {
|
|||
std::array<float, 12> mPlaceholderConstantArray;
|
||||
|
||||
wgpu::Queue queue;
|
||||
wgpu::Texture defaultTexture;
|
||||
};
|
||||
|
||||
TEST_F(ExternalTextureTest, CreateExternalTextureValidation) {
|
||||
|
@ -273,55 +331,85 @@ TEST_F(ExternalTextureTest, CreateMultiplanarExternalTextureValidation) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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_F(ExternalTextureTest, SubmitDereferencedExternalTextureInRenderPass) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
|
Loading…
Reference in New Issue