mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-17 04:41:23 +00:00
Validate if device is alive in EncodeFunction of EncodingContext::TryEncode
GetOrCreateAttachmentState access mCaches in Device even if device is already destroyed. Gate the function by checking if encoder is destroyed. Bug: chromium:1323310 Change-Id: I8151c5ec696e4da28b8296d9142f3120379782ef Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/89860 Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Shrek Shao <shrekshao@google.com>
This commit is contained in:
parent
83fc247d4b
commit
8faaad9b5e
@ -25,7 +25,10 @@
|
|||||||
namespace dawn::native {
|
namespace dawn::native {
|
||||||
|
|
||||||
EncodingContext::EncodingContext(DeviceBase* device, const ApiObjectBase* initialEncoder)
|
EncodingContext::EncodingContext(DeviceBase* device, const ApiObjectBase* initialEncoder)
|
||||||
: mDevice(device), mTopLevelEncoder(initialEncoder), mCurrentEncoder(initialEncoder) {}
|
: mDevice(device),
|
||||||
|
mTopLevelEncoder(initialEncoder),
|
||||||
|
mCurrentEncoder(initialEncoder),
|
||||||
|
mDestroyed(device->IsLost()) {}
|
||||||
|
|
||||||
EncodingContext::~EncodingContext() {
|
EncodingContext::~EncodingContext() {
|
||||||
Destroy();
|
Destroy();
|
||||||
|
@ -79,10 +79,13 @@ class EncodingContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool CheckCurrentEncoder(const ApiObjectBase* encoder) {
|
inline bool CheckCurrentEncoder(const ApiObjectBase* encoder) {
|
||||||
|
if (mDestroyed) {
|
||||||
|
HandleError(
|
||||||
|
DAWN_FORMAT_VALIDATION_ERROR("Recording in a destroyed %s.", mCurrentEncoder));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) {
|
if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) {
|
||||||
if (mDestroyed) {
|
if (mCurrentEncoder != mTopLevelEncoder) {
|
||||||
HandleError(DAWN_FORMAT_VALIDATION_ERROR("Recording in a destroyed %s.", encoder));
|
|
||||||
} else if (mCurrentEncoder != mTopLevelEncoder) {
|
|
||||||
// The top level encoder was used when a pass encoder was current.
|
// The top level encoder was used when a pass encoder was current.
|
||||||
HandleError(DAWN_FORMAT_VALIDATION_ERROR(
|
HandleError(DAWN_FORMAT_VALIDATION_ERROR(
|
||||||
"Command cannot be recorded while %s is active.", mCurrentEncoder));
|
"Command cannot be recorded while %s is active.", mCurrentEncoder));
|
||||||
|
@ -31,12 +31,12 @@ TEST_F(CommandBufferValidationTest, Empty) {
|
|||||||
|
|
||||||
// Test that a command buffer cannot be ended mid render pass
|
// Test that a command buffer cannot be ended mid render pass
|
||||||
TEST_F(CommandBufferValidationTest, EndedMidRenderPass) {
|
TEST_F(CommandBufferValidationTest, EndedMidRenderPass) {
|
||||||
PlaceholderRenderPass PlaceholderRenderPass(device);
|
PlaceholderRenderPass placeholderRenderPass(device);
|
||||||
|
|
||||||
// Control case, command buffer ended after the pass is ended.
|
// Control case, command buffer ended after the pass is ended.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
encoder.Finish();
|
encoder.Finish();
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ TEST_F(CommandBufferValidationTest, EndedMidRenderPass) {
|
|||||||
// Error case, command buffer ended mid-pass.
|
// Error case, command buffer ended mid-pass.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
ASSERT_DEVICE_ERROR(
|
ASSERT_DEVICE_ERROR(
|
||||||
encoder.Finish(),
|
encoder.Finish(),
|
||||||
HasSubstr("Command buffer recording ended before [RenderPassEncoder] was ended."));
|
HasSubstr("Command buffer recording ended before [RenderPassEncoder] was ended."));
|
||||||
@ -54,7 +54,7 @@ TEST_F(CommandBufferValidationTest, EndedMidRenderPass) {
|
|||||||
// should fail too.
|
// should fail too.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
ASSERT_DEVICE_ERROR(
|
ASSERT_DEVICE_ERROR(
|
||||||
encoder.Finish(),
|
encoder.Finish(),
|
||||||
HasSubstr("Command buffer recording ended before [RenderPassEncoder] was ended."));
|
HasSubstr("Command buffer recording ended before [RenderPassEncoder] was ended."));
|
||||||
@ -97,12 +97,12 @@ TEST_F(CommandBufferValidationTest, EndedMidComputePass) {
|
|||||||
|
|
||||||
// Test that a render pass cannot be ended twice
|
// Test that a render pass cannot be ended twice
|
||||||
TEST_F(CommandBufferValidationTest, RenderPassEndedTwice) {
|
TEST_F(CommandBufferValidationTest, RenderPassEndedTwice) {
|
||||||
PlaceholderRenderPass PlaceholderRenderPass(device);
|
PlaceholderRenderPass placeholderRenderPass(device);
|
||||||
|
|
||||||
// Control case, pass is ended once
|
// Control case, pass is ended once
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
encoder.Finish();
|
encoder.Finish();
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ TEST_F(CommandBufferValidationTest, RenderPassEndedTwice) {
|
|||||||
// Error case, pass ended twice
|
// Error case, pass ended twice
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
pass.End();
|
pass.End();
|
||||||
ASSERT_DEVICE_ERROR(
|
ASSERT_DEVICE_ERROR(
|
||||||
@ -143,12 +143,12 @@ TEST_F(CommandBufferValidationTest, ComputePassEndedTwice) {
|
|||||||
|
|
||||||
// Test that beginning a compute pass before ending the previous pass causes an error.
|
// Test that beginning a compute pass before ending the previous pass causes an error.
|
||||||
TEST_F(CommandBufferValidationTest, BeginComputePassBeforeEndPreviousPass) {
|
TEST_F(CommandBufferValidationTest, BeginComputePassBeforeEndPreviousPass) {
|
||||||
PlaceholderRenderPass PlaceholderRenderPass(device);
|
PlaceholderRenderPass placeholderRenderPass(device);
|
||||||
|
|
||||||
// Beginning a compute pass before ending a render pass causes an error.
|
// Beginning a compute pass before ending a render pass causes an error.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
|
wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
|
||||||
computePass.End();
|
computePass.End();
|
||||||
renderPass.End();
|
renderPass.End();
|
||||||
@ -168,13 +168,13 @@ TEST_F(CommandBufferValidationTest, BeginComputePassBeforeEndPreviousPass) {
|
|||||||
|
|
||||||
// Test that beginning a render pass before ending the previous pass causes an error.
|
// Test that beginning a render pass before ending the previous pass causes an error.
|
||||||
TEST_F(CommandBufferValidationTest, BeginRenderPassBeforeEndPreviousPass) {
|
TEST_F(CommandBufferValidationTest, BeginRenderPassBeforeEndPreviousPass) {
|
||||||
PlaceholderRenderPass PlaceholderRenderPass(device);
|
PlaceholderRenderPass placeholderRenderPass(device);
|
||||||
|
|
||||||
// Beginning a render pass before ending the render pass causes an error.
|
// Beginning a render pass before ending the render pass causes an error.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder renderPass1 = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder renderPass1 = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
wgpu::RenderPassEncoder renderPass2 = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder renderPass2 = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
renderPass2.End();
|
renderPass2.End();
|
||||||
renderPass1.End();
|
renderPass1.End();
|
||||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
@ -184,7 +184,7 @@ TEST_F(CommandBufferValidationTest, BeginRenderPassBeforeEndPreviousPass) {
|
|||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
|
wgpu::ComputePassEncoder computePass = encoder.BeginComputePass();
|
||||||
wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
renderPass.End();
|
renderPass.End();
|
||||||
computePass.End();
|
computePass.End();
|
||||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
@ -229,12 +229,12 @@ TEST_F(CommandBufferValidationTest, CallsAfterAFailedFinish) {
|
|||||||
// Test that passes which are de-referenced prior to ending still allow the correct errors to be
|
// Test that passes which are de-referenced prior to ending still allow the correct errors to be
|
||||||
// produced.
|
// produced.
|
||||||
TEST_F(CommandBufferValidationTest, PassDereferenced) {
|
TEST_F(CommandBufferValidationTest, PassDereferenced) {
|
||||||
PlaceholderRenderPass PlaceholderRenderPass(device);
|
PlaceholderRenderPass placeholderRenderPass(device);
|
||||||
|
|
||||||
// Control case, command buffer ended after the pass is ended.
|
// Control case, command buffer ended after the pass is ended.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
encoder.Finish();
|
encoder.Finish();
|
||||||
}
|
}
|
||||||
@ -242,7 +242,7 @@ TEST_F(CommandBufferValidationTest, PassDereferenced) {
|
|||||||
// Error case, no reference is kept to a render pass.
|
// Error case, no reference is kept to a render pass.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
encoder.BeginRenderPass(&PlaceholderRenderPass);
|
encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
ASSERT_DEVICE_ERROR(
|
ASSERT_DEVICE_ERROR(
|
||||||
encoder.Finish(),
|
encoder.Finish(),
|
||||||
HasSubstr("Command buffer recording ended before [RenderPassEncoder] was ended."));
|
HasSubstr("Command buffer recording ended before [RenderPassEncoder] was ended."));
|
||||||
@ -260,7 +260,7 @@ TEST_F(CommandBufferValidationTest, PassDereferenced) {
|
|||||||
// Error case, beginning a new pass after failing to end a de-referenced pass.
|
// Error case, beginning a new pass after failing to end a de-referenced pass.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
encoder.BeginRenderPass(&PlaceholderRenderPass);
|
encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||||
pass.End();
|
pass.End();
|
||||||
ASSERT_DEVICE_ERROR(
|
ASSERT_DEVICE_ERROR(
|
||||||
@ -301,12 +301,12 @@ TEST_F(CommandBufferValidationTest, DestroyEncoder) {
|
|||||||
// only way to trigger the destroy call is by losing all references which means we cannot
|
// only way to trigger the destroy call is by losing all references which means we cannot
|
||||||
// call finish.
|
// call finish.
|
||||||
DAWN_SKIP_TEST_IF(UsesWire());
|
DAWN_SKIP_TEST_IF(UsesWire());
|
||||||
PlaceholderRenderPass PlaceholderRenderPass(device);
|
PlaceholderRenderPass placeholderRenderPass(device);
|
||||||
|
|
||||||
// Control case, command buffer ended after the pass is ended.
|
// Control case, command buffer ended after the pass is ended.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
encoder.Finish();
|
encoder.Finish();
|
||||||
}
|
}
|
||||||
@ -314,7 +314,7 @@ TEST_F(CommandBufferValidationTest, DestroyEncoder) {
|
|||||||
// Destroyed encoder with encoded commands should emit error on finish.
|
// Destroyed encoder with encoded commands should emit error on finish.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
dawn::native::FromAPI(encoder.Get())->Destroy();
|
dawn::native::FromAPI(encoder.Get())->Destroy();
|
||||||
ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
|
ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
|
||||||
@ -323,7 +323,7 @@ TEST_F(CommandBufferValidationTest, DestroyEncoder) {
|
|||||||
// Destroyed encoder with encoded commands shouldn't emit an error if never finished.
|
// Destroyed encoder with encoded commands shouldn't emit an error if never finished.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
dawn::native::FromAPI(encoder.Get())->Destroy();
|
dawn::native::FromAPI(encoder.Get())->Destroy();
|
||||||
}
|
}
|
||||||
@ -332,7 +332,7 @@ TEST_F(CommandBufferValidationTest, DestroyEncoder) {
|
|||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
dawn::native::FromAPI(encoder.Get())->Destroy();
|
dawn::native::FromAPI(encoder.Get())->Destroy();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
|
ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
|
||||||
}
|
}
|
||||||
@ -341,14 +341,14 @@ TEST_F(CommandBufferValidationTest, DestroyEncoder) {
|
|||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
dawn::native::FromAPI(encoder.Get())->Destroy();
|
dawn::native::FromAPI(encoder.Get())->Destroy();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroying a finished encoder should not emit any errors.
|
// Destroying a finished encoder should not emit any errors.
|
||||||
{
|
{
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&PlaceholderRenderPass);
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
pass.End();
|
pass.End();
|
||||||
encoder.Finish();
|
encoder.Finish();
|
||||||
dawn::native::FromAPI(encoder.Get())->Destroy();
|
dawn::native::FromAPI(encoder.Get())->Destroy();
|
||||||
@ -369,3 +369,32 @@ TEST_F(CommandBufferValidationTest, DestroyEncoder) {
|
|||||||
ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
|
ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CommandBufferValidationTest, EncodeAfterDeviceDestroyed) {
|
||||||
|
PlaceholderRenderPass placeholderRenderPass(device);
|
||||||
|
|
||||||
|
// Device destroyed before encoding.
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
ExpectDeviceDestruction();
|
||||||
|
device.Destroy();
|
||||||
|
// The encoder should not accessing any device info if device is destroyed when try
|
||||||
|
// encoding.
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
|
pass.End();
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device destroyed after encoding.
|
||||||
|
{
|
||||||
|
ExpectDeviceDestruction();
|
||||||
|
device.Destroy();
|
||||||
|
ASSERT_DEVICE_ERROR(wgpu::CommandEncoder encoder = device.CreateCommandEncoder(),
|
||||||
|
HasSubstr("[Device] is lost"));
|
||||||
|
// The encoder should not accessing any device info if device is destroyed when try
|
||||||
|
// encoding.
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass);
|
||||||
|
pass.End();
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("[Invalid CommandEncoder] is invalid."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user