Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/dawn-ci.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ if (WIN32)
set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION "$ENV{WIN10_SDK_VERSION}" CACHE STRING "")
endif ()
set(DAWN_FETCH_DEPENDENCIES ON CACHE BOOL "")
set(DAWN_ENABLE_INSTALL ON CACHE BOOL "")
# set(DAWN_ENABLE_INSTALL ON CACHE BOOL "")
set(DAWN_ENABLE_INSTALL OFF CACHE BOOL "")


if (CMAKE_SYTEM_NAME STREQUAL "Linux")
# `sccache` seems effective only on linux.
Expand Down
23 changes: 17 additions & 6 deletions src/dawn/native/Buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,17 +566,24 @@ Future BufferBase::APIMapAsync(wgpu::MapMode mode,
size_t offset,
size_t size,
const WGPUBufferMapCallbackInfo& callbackInfo) {
// TODO(crbug.com/dawn/2052): Once we always return a future, change this to log to the instance
// (note, not raise a validation error to the device) and return the null future.
DAWN_ASSERT(callbackInfo.nextInChain == nullptr);

Ref<MapAsyncEvent> event;
{
auto deviceGuard = GetDevice()->GetGuard();

// Handle the defaulting of size required by WebGPU, even if in webgpu_cpp.h it is not
// possible to default the function argument (because there is the callback later in the
// argument list)
// Remove redundant early-exit validation.
// Let ValidateMapAsync and MapAsyncImpl handle invalid states,
// so errors are reported through the device's uncaptured error mechanism.
// We can still log a warning for developer visibility.
BufferState currentState = mState.load(std::memory_order::acquire);
if (currentState == BufferState::Mapped || currentState == BufferState::MappedAtCreation) {
dawn::EmitWarning(GetDevice(),
"Attempted to map a buffer that is already mapped. "
"Call Unmap() before calling MapAsync again.");
}

// Handle the defaulting of size required by WebGPU
if ((size == wgpu::kWholeMapSize) && (offset <= mSize)) {
size = mSize - offset;
}
Expand Down Expand Up @@ -611,9 +618,13 @@ Future BufferBase::APIMapAsync(wgpu::MapMode mode,

DAWN_ASSERT(event);
FutureID futureID = GetInstance()->GetEventManager()->TrackEvent(std::move(event));
return {futureID};
return {futureID}; // Always return a valid FutureID
}



//****************************************************************************************************** */

void* BufferBase::APIGetMappedRange(size_t offset, size_t size) {
return GetMappedRange(offset, size, true);
}
Expand Down
39 changes: 39 additions & 0 deletions src/dawn/tests/end2end/BufferTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,45 @@ TEST_P(BufferTests, CreateErrorBuffer) {
ASSERT_EQ(buffer, nullptr);
}

// Test that MapAsync fails if called twice on the same buffer without unmapping.
TEST_P(BufferValidationTests, MapAsyncFailsWhenAlreadyMapped) {
// Create a writable buffer with MapWrite and CopyDst usage.
wgpu::BufferDescriptor desc;
desc.size = 64;
desc.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopyDst;

wgpu::Buffer buffer = device.CreateBuffer(&desc);

// First call to MapAsync should succeed.
bool callback1Called = false;
buffer.MapAsync(wgpu::MapMode::Write, 0, 64,
[&](WGPUMapAsyncStatus status) {
// Expect the first mapping to succeed.
EXPECT_EQ(status, WGPUMapAsyncStatus_Success);
callback1Called = true;
});

// Immediately call MapAsync again without unmapping.
bool callback2Called = false;
buffer.MapAsync(wgpu::MapMode::Write, 0, 64,
[&](WGPUMapAsyncStatus status) {
// The second mapping should fail and return an error.
EXPECT_EQ(status, WGPUMapAsyncStatus_Error);
callback2Called = true;
});

// Process the commands and trigger callbacks.
device.Tick();

// Ensure both callbacks were actually called.
EXPECT_TRUE(callback1Called);
EXPECT_TRUE(callback2Called);

// Cleanup: Unmap the buffer after use.
buffer.Unmap();
}


// Test that mapping an OOM buffer fails gracefully
TEST_P(BufferTests, CreateBufferOOMMapAsync) {
// TODO(crbug.com/346377856): fails on ANGLE/D3D11, but is likely a Dawn/GL bug that only
Expand Down
Loading