mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-19 01:46:35 +00:00
Fix crash from async callback calling Queue::Submit
An async callback which calls Queue::Submit will cause reentrance in QueueBase::Tick and CreatePipelineAsyncTracker::Tick, which invalidates the task queue being used by the original call, and leads to a crash from an invalid pointer. The Tick functions should remove the tasks from the queues before the callbacks are called, so invalidation doesn't cause a crash. Bug: dawn:729 Change-Id: I0d952d51040a3d1a475767400de3333a8b9b0821 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/45900 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
98028718e1
commit
7f8c91cdde
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "tests/unittests/validation/ValidationTest.h"
|
||||
|
||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||
#include "utils/WGPUHelpers.h"
|
||||
|
||||
namespace {
|
||||
@@ -129,4 +130,95 @@ namespace {
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
}
|
||||
|
||||
// Test that submitting in a buffer mapping callback doesn't cause re-entrance problems.
|
||||
TEST_F(QueueSubmitValidationTest, SubmitInBufferMapCallback) {
|
||||
// Create a buffer for mapping, to run our callback.
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::MapWrite;
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||
|
||||
struct CallbackData {
|
||||
wgpu::Device device;
|
||||
wgpu::Buffer buffer;
|
||||
} callbackData = {device, buffer};
|
||||
|
||||
const auto callback = [](WGPUBufferMapAsyncStatus status, void* userdata) {
|
||||
CallbackData* data = reinterpret_cast<CallbackData*>(userdata);
|
||||
|
||||
data->buffer.Unmap();
|
||||
|
||||
wgpu::Queue queue = data->device.GetQueue();
|
||||
queue.Submit(0, nullptr);
|
||||
};
|
||||
|
||||
buffer.MapAsync(wgpu::MapMode::Write, 0, descriptor.size, callback, &callbackData);
|
||||
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
// Test that submitting in a render pipeline creation callback doesn't cause re-entrance
|
||||
// problems.
|
||||
TEST_F(QueueSubmitValidationTest, SubmitInCreateRenderPipelineAsyncCallback) {
|
||||
struct CallbackData {
|
||||
wgpu::Device device;
|
||||
} callbackData = {device};
|
||||
|
||||
const auto callback = [](WGPUCreatePipelineAsyncStatus status, WGPURenderPipeline pipeline,
|
||||
char const* message, void* userdata) {
|
||||
CallbackData* data = reinterpret_cast<CallbackData*>(userdata);
|
||||
|
||||
wgpuRenderPipelineRelease(pipeline);
|
||||
|
||||
wgpu::Queue queue = data->device.GetQueue();
|
||||
queue.Submit(0, nullptr);
|
||||
};
|
||||
|
||||
wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
|
||||
[[builtin(position)]] var<out> Position : vec4<f32>;
|
||||
[[stage(vertex)]] fn main() -> void {
|
||||
Position = vec4<f32>(0.0, 0.0, 0.0, 1.0);
|
||||
})");
|
||||
|
||||
wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
|
||||
[[location(0)]] var<out> fragColor : vec4<f32>;
|
||||
[[stage(fragment)]] fn main() -> void {
|
||||
fragColor = vec4<f32>(0.0, 1.0, 0.0, 1.0);
|
||||
})");
|
||||
|
||||
utils::ComboRenderPipelineDescriptor2 descriptor;
|
||||
descriptor.vertex.module = vsModule;
|
||||
descriptor.cFragment.module = fsModule;
|
||||
device.CreateRenderPipelineAsync(&descriptor, callback, &callbackData);
|
||||
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
// Test that submitting in a compute pipeline creation callback doesn't cause re-entrance
|
||||
// problems.
|
||||
TEST_F(QueueSubmitValidationTest, SubmitInCreateComputePipelineAsyncCallback) {
|
||||
struct CallbackData {
|
||||
wgpu::Device device;
|
||||
} callbackData = {device};
|
||||
|
||||
const auto callback = [](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline pipeline,
|
||||
char const* message, void* userdata) {
|
||||
CallbackData* data = reinterpret_cast<CallbackData*>(userdata);
|
||||
|
||||
wgpuComputePipelineRelease(pipeline);
|
||||
|
||||
wgpu::Queue queue = data->device.GetQueue();
|
||||
queue.Submit(0, nullptr);
|
||||
};
|
||||
|
||||
wgpu::ComputePipelineDescriptor descriptor;
|
||||
descriptor.computeStage.module = utils::CreateShaderModule(device, R"(
|
||||
[[stage(compute)]] fn main() -> void {
|
||||
})");
|
||||
descriptor.computeStage.entryPoint = "main";
|
||||
device.CreateComputePipelineAsync(&descriptor, callback, &callbackData);
|
||||
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
Reference in New Issue
Block a user