Compare commits

..

1 Commits

Author SHA1 Message Date
Run Yu
8c1167ddb8 Use GetMappedRange early but still get null pointer sometimes 2025-11-21 13:34:57 -05:00
3 changed files with 57 additions and 39 deletions

View File

@@ -86,23 +86,43 @@ void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor const& bufferDescriptor,
const size_t mainBulk = bufferDescriptor.size - remainder; const size_t mainBulk = bufferDescriptor.size - remainder;
const size_t stagingBufferSize = const size_t stagingBufferSize =
remainder == 0 ? bufferDescriptor.size : mainBulk + FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS; remainder == 0 ? bufferDescriptor.size : mainBulk + FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS;
//
// // create a staging buffer
// wgpu::BufferDescriptor descriptor{
// .label = "Filament WebGPU Staging Buffer",
// .usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc,
// .size = stagingBufferSize,
// .mappedAtCreation = true };
// wgpu::Buffer stagingBuffer = device.CreateBuffer(&descriptor);
MappedStage mappedStage = webGPUStagePool->acquireBuffer(stagingBufferSize);
Stage stage = webGPUStagePool->acquireBuffer(stagingBufferSize); std::string mappedRangeIsNull = mappedStage.mappedRange
std::string mappedRangeIsNull = stage.mappedRange
? "no" ? "no"
: "yes"; : "yes";
std::cout << "Run Yu: got mapped range on the staging buffer with size " std::cout << "Run Yu: got mapped range on the staging buffer with size "
<< stage.buffer.GetSize() << " and it is null? " << mappedRangeIsNull << std::endl; << mappedStage.buffer.GetSize() << " and it is null? " << mappedRangeIsNull << std::endl;
memcpy(stage.mappedRange, bufferDescriptor.buffer, bufferDescriptor.size); memcpy(mappedStage.mappedRange, bufferDescriptor.buffer, bufferDescriptor.size);
stage.buffer.Unmap(); // Make sure the padded memory is set to 0 to have deterministic behaviors
// if (remainder != 0) {
// uint8_t* paddingStart = static_cast<uint8_t*>(mappedRange) + bufferDescriptor.size;
// memset(paddingStart, 0, FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS - remainder);
// }
// size_t stagingBufferSize = stagingBuffer.GetSize();
// if (stagingBufferSize != bufferDescriptor.size) {
// assert(stagingBufferSize > bufferDescriptor.size);
// assert(stagingBufferSize % FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS == 0);
// uint8_t* paddingStart = static_cast<uint8_t*>(mappedRange) + bufferDescriptor.size;
// memset(paddingStart, 0, FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS - (stagingBuffer.GetSize() - bufferDescriptor.size));
// }
mappedStage.buffer.Unmap();
std::cout << "Run Yu: about to issue copy command with actual staging buffer of size " std::cout << "Run Yu: about to issue copy command with actual staging buffer of size "
<< stage.buffer.GetSize() << ", and computed size of " << stagingBufferSize << mappedStage.buffer.GetSize() << ", and computed size of " << stagingBufferSize
<< ". The mBuffer size is " << mBuffer.GetSize() << std::endl; << ". The mBuffer size is " << mBuffer.GetSize() << std::endl;
// Copy the staging buffer contents to the destination buffer. // Copy the staging buffer contents to the destination buffer.
webGPUQueueManager->getCommandEncoder().CopyBufferToBuffer(stage.buffer, 0, mBuffer, webGPUQueueManager->getCommandEncoder().CopyBufferToBuffer(mappedStage.buffer, 0, mBuffer,
byteOffset, byteOffset,
remainder == 0 ? bufferDescriptor.size remainder == 0 ? bufferDescriptor.size
: mainBulk + FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS); : mainBulk + FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS);
@@ -113,22 +133,18 @@ void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor const& bufferDescriptor,
WebGPUStagePool* webGPUStagePool; WebGPUStagePool* webGPUStagePool;
}; };
auto userData = std::make_unique<UserData>( auto userData = std::make_unique<UserData>(
UserData{ .stagingBuffer = stage.buffer, .webGPUStagePool = webGPUStagePool }); UserData{ .stagingBuffer = mappedStage.buffer, .webGPUStagePool = webGPUStagePool });
stage.buffer.MapAsync(wgpu::MapMode::Write, 0, stagingBufferSize, mappedStage.buffer.MapAsync(
wgpu::CallbackMode::AllowSpontaneous, wgpu::MapMode::Write, 0, stagingBufferSize, wgpu::CallbackMode::AllowSpontaneous,
[data = std::move(userData)](wgpu::MapAsyncStatus status, const char* message) { [](wgpu::MapAsyncStatus status, const char* message, UserData* userData) {
if (UTILS_LIKELY(status == wgpu::MapAsyncStatus::Success)) { if (UTILS_LIKELY(status == wgpu::MapAsyncStatus::Success)) {
std::cout << "Run Yu: successfully mapped a buffer with size " std::unique_ptr<UserData> data(static_cast<UserData*>(userData));
<< data->stagingBuffer.GetSize() << std::endl; userData->webGPUStagePool->addBufferToPool(userData->stagingBuffer);
void* mappedRange = data->stagingBuffer.GetMappedRange();
if (!mappedRange) {
std::cout << "Run Yu: MAPPED RANGE IS NULL RIGHT AWAY!!\n";
}
data->webGPUStagePool->addBufferToPool(data->stagingBuffer, mappedRange);
} else { } else {
std::cout << "Run Yu: MAPPING UNSUCCESSFUL!!\n"; std::cout << "Run Yu: MAPPING UNSUCCESSFUL!!\n";
} }
}); },
userData.release());
} }
} // namespace filament::backend } // namespace filament::backend

View File

@@ -26,50 +26,52 @@ WebGPUStagePool::WebGPUStagePool(wgpu::Device const& device) : mDevice(device) {
WebGPUStagePool::~WebGPUStagePool() = default; WebGPUStagePool::~WebGPUStagePool() = default;
Stage WebGPUStagePool::acquireBuffer(size_t requiredSize) { MappedStage WebGPUStagePool::acquireBuffer(size_t requiredSize) {
std::cout << "Run Yu: required size in acquireBuffer: " << requiredSize << std::endl; std::cout << "Run Yu: required size in acquireBuffer: " << requiredSize << std::endl;
std::cout << "Run Yu: the pool size is " << mBuffers.size() << std::endl; std::cout << "Run Yu: the pool size is " << mBuffers.size() << std::endl;
{ {
std::lock_guard<std::mutex> lock(mMutex); std::lock_guard<std::mutex> lock(mMutex);
auto iter = mBuffers.lower_bound(requiredSize); auto iter = mBuffers.lower_bound(requiredSize);
if (iter != mBuffers.end()) { if (iter != mBuffers.end()) {
const Stage& fromPool = iter->second; std::cout << "Run Yu: found buffer in the pool with size " << iter->second.GetSize()
std::cout << "Run Yu: found buffer in the pool with size " << fromPool.buffer.GetSize()
<< std::endl; << std::endl;
if (fromPool.buffer.GetMapState() != wgpu::BufferMapState::Mapped) { if (iter->second.GetMapState() != wgpu::BufferMapState::Mapped) {
std::cout << "Run Yu: buffer from pool is not mapped!!" << std::endl; std::cout << "Run Yu: before GetMappedRange the buffer state is not mapped!\n";
}
MappedStage mappedStage = { .buffer = iter->second,
.mappedRange = iter->second.GetMappedRange() };
if (!mappedStage.mappedRange) {
std::cout << "Run Yu: mapped range is null in acquireBuffer!\n";
}
if (mappedStage.buffer.GetMapState() != wgpu::BufferMapState::Mapped) {
std::cout << "Run Yu: after GetMappedRange the buffer state is not mapped!\n";
} }
Stage result{ .buffer = fromPool.buffer, .mappedRange = fromPool.mappedRange };
mBuffers.erase(iter); mBuffers.erase(iter);
return result; return mappedStage;
} }
} }
wgpu::Buffer newBuffer = createNewBuffer(requiredSize); wgpu::Buffer newBuffer = createNewBuffer(requiredSize);
return { .buffer = newBuffer, .mappedRange = newBuffer.GetMappedRange() }; return { .buffer = newBuffer, .mappedRange = newBuffer.GetMappedRange() };
} }
void WebGPUStagePool::addBufferToPool(wgpu::Buffer buffer, void* mappedRange) { void WebGPUStagePool::addBufferToPool(wgpu::Buffer buffer) {
std::lock_guard<std::mutex> lock(mMutex); std::lock_guard<std::mutex> lock(mMutex);
std::cout << "Run Yu: adding buffer to the pool with size " << buffer.GetSize() << std::endl; std::cout << "Run Yu: adding buffer to the pool with size " << buffer.GetSize() << std::endl;
Stage stage {.buffer = buffer, .mappedRange = mappedRange}; mBuffers.insert({buffer.GetSize(), buffer});
mBuffers.emplace(buffer.GetSize(), stage);
std::cout << "Run Yu: added buffer to the pool with size " << buffer.GetSize() << std::endl; std::cout << "Run Yu: added buffer to the pool with size " << buffer.GetSize() << std::endl;
bool allMapped = true; bool allMapped = true;
for (const auto& pair : mBuffers) { for (const auto& pair : mBuffers) {
auto state = pair.second.buffer.GetMapState(); auto state = pair.second.GetMapState();
if (state != wgpu::BufferMapState::Mapped) { if (state != wgpu::BufferMapState::Mapped) {
allMapped = false; allMapped = false;
std::cout << "Run Yu: the buffer with size " << pair.second.buffer.GetSize() std::cout << "Run Yu: the buffer with size " << pair.second.GetSize()
<< " is not mapped but somehow was added to the pool, its state is " << " is not mapped but somehow was added to the pool, its state is "
<< static_cast<int>(state) << std::endl; << static_cast<int>(state) << std::endl;
} }
} }
if (!allMapped) { if (!allMapped) {
std::cout << "Run Yu: found buffers that are not mapped\n"; std::cout << "Run Yu: found buffers that are not mapped\n";
} else {
std::cout << "Run Yu: all buffers are mapped\n";
} }
} }

View File

@@ -24,7 +24,7 @@
namespace filament::backend { namespace filament::backend {
struct Stage { struct MappedStage {
wgpu::Buffer buffer; wgpu::Buffer buffer;
void* mappedRange; void* mappedRange;
}; };
@@ -34,11 +34,11 @@ public:
WebGPUStagePool(wgpu::Device const& device); WebGPUStagePool(wgpu::Device const& device);
~WebGPUStagePool(); ~WebGPUStagePool();
Stage acquireBuffer(size_t requiredSize); MappedStage acquireBuffer(size_t requiredSize);
void addBufferToPool(wgpu::Buffer buffer, void* mappedRange); void addBufferToPool(wgpu::Buffer buffer);
private: private:
wgpu::Buffer createNewBuffer(size_t bufferSize); wgpu::Buffer createNewBuffer(size_t bufferSize);
std::multimap<uint32_t, Stage> mBuffers; std::multimap<uint32_t, wgpu::Buffer> mBuffers;
mutable std::mutex mMutex; mutable std::mutex mMutex;
wgpu::Device mDevice; wgpu::Device mDevice;