Compare commits
1 Commits
pf/mesa-us
...
MapAsyncEx
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f14ebba87 |
@@ -63,7 +63,7 @@ WebGPUBufferBase::WebGPUBufferBase(wgpu::Device const& device, const wgpu::Buffe
|
||||
// WebGPU requires that the size of the data copied from the staging buffer to the GPU buffer is a
|
||||
// multiple of 4. This function handles cases where the buffer descriptor's size is not a multiple
|
||||
// of 4 by padding with zeros.
|
||||
void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor const& bufferDescriptor,
|
||||
void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor&& bufferDescriptor,
|
||||
const uint32_t byteOffset, wgpu::Device const& device,
|
||||
WebGPUQueueManager* const webGPUQueueManager) {
|
||||
FILAMENT_CHECK_PRECONDITION(bufferDescriptor.buffer)
|
||||
@@ -89,24 +89,49 @@ void WebGPUBufferBase::updateGPUBuffer(BufferDescriptor const& bufferDescriptor,
|
||||
wgpu::BufferDescriptor descriptor{
|
||||
.label = "Filament WebGPU Staging Buffer",
|
||||
.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc,
|
||||
.size = stagingBufferSize,
|
||||
.mappedAtCreation = true };
|
||||
.size = stagingBufferSize};
|
||||
wgpu::Buffer stagingBuffer = device.CreateBuffer(&descriptor);
|
||||
|
||||
void* mappedRange = stagingBuffer.GetMappedRange();
|
||||
memcpy(mappedRange, bufferDescriptor.buffer, bufferDescriptor.size);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
stagingBuffer.Unmap();
|
||||
|
||||
// Copy the staging buffer contents to the destination buffer.
|
||||
webGPUQueueManager->getCommandEncoder().CopyBufferToBuffer(stagingBuffer, 0, mBuffer,
|
||||
byteOffset, stagingBufferSize);
|
||||
struct UserData final {
|
||||
uint32_t byteOffset;
|
||||
size_t stagingBufferSize;
|
||||
size_t remainder;
|
||||
BufferDescriptor srcBufferDescriptor;
|
||||
wgpu::Buffer stagingBuffer;
|
||||
WebGPUQueueManager* const webGPUQueueManager;
|
||||
wgpu::Buffer dstBuffer;
|
||||
};
|
||||
auto userData = std::make_unique<UserData>(UserData{
|
||||
.byteOffset = byteOffset,
|
||||
.stagingBufferSize = stagingBufferSize,
|
||||
.remainder = remainder,
|
||||
.srcBufferDescriptor = std::move(bufferDescriptor),
|
||||
.stagingBuffer = stagingBuffer,
|
||||
.webGPUQueueManager = webGPUQueueManager,
|
||||
.dstBuffer = mBuffer});
|
||||
stagingBuffer.MapAsync(
|
||||
wgpu::MapMode::Write, 0, stagingBufferSize, wgpu::CallbackMode::AllowProcessEvents,
|
||||
[](wgpu::MapAsyncStatus status, const char* message, UserData* userdata) {
|
||||
std::unique_ptr<UserData> data(static_cast<UserData*>(userdata));
|
||||
if (UTILS_LIKELY(status == wgpu::MapAsyncStatus::Success)) {
|
||||
void* mappedRange = data->stagingBuffer.GetMappedRange();
|
||||
memcpy(mappedRange, data->srcBufferDescriptor.buffer,
|
||||
data->srcBufferDescriptor.size);
|
||||
if (data->remainder != 0) {
|
||||
uint8_t* paddingStart =
|
||||
static_cast<uint8_t*>(mappedRange) + data->srcBufferDescriptor.size;
|
||||
memset(paddingStart, 0,
|
||||
FILAMENT_WEBGPU_BUFFER_SIZE_MODULUS - data->remainder);
|
||||
}
|
||||
data->stagingBuffer.Unmap();
|
||||
data->webGPUQueueManager->getCommandEncoder().CopyBufferToBuffer(
|
||||
data->stagingBuffer, 0, data->dstBuffer, data->byteOffset,
|
||||
data->stagingBufferSize);
|
||||
} else {
|
||||
FWGPU_LOGE << "Failed to map staging buffer for readPixels: " << message;
|
||||
}
|
||||
},
|
||||
userData.release());
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
* happen after draw commands encoded in the encoder. Submitting any commands up to this point
|
||||
* ensures the calls happen in the expected sequence.
|
||||
*/
|
||||
void updateGPUBuffer(BufferDescriptor const&, uint32_t byteOffset, wgpu::Device const& device,
|
||||
void updateGPUBuffer(BufferDescriptor&&, uint32_t byteOffset, wgpu::Device const& device,
|
||||
WebGPUQueueManager* const webGPUQueueManager);
|
||||
|
||||
[[nodiscard]] wgpu::Buffer const& getBuffer() const { return mBuffer; }
|
||||
|
||||
@@ -856,7 +856,7 @@ void WebGPUDriver::updateIndexBuffer(Handle<HwIndexBuffer> indexBufferHandle,
|
||||
// draw calls are made.
|
||||
flush();
|
||||
handleCast<WebGPUIndexBuffer>(indexBufferHandle)
|
||||
->updateGPUBuffer(bufferDescriptor, byteOffset, mDevice, &mQueueManager);
|
||||
->updateGPUBuffer(std::move(bufferDescriptor), byteOffset, mDevice, &mQueueManager);
|
||||
scheduleDestroy(std::move(bufferDescriptor));
|
||||
}
|
||||
|
||||
@@ -867,14 +867,14 @@ void WebGPUDriver::updateBufferObject(Handle<HwBufferObject> bufferObjectHandle,
|
||||
// draw calls are made.
|
||||
flush();
|
||||
handleCast<WebGPUBufferObject>(bufferObjectHandle)
|
||||
->updateGPUBuffer(bufferDescriptor, byteOffset, mDevice, &mQueueManager);
|
||||
->updateGPUBuffer(std::move(bufferDescriptor), byteOffset, mDevice, &mQueueManager);
|
||||
scheduleDestroy(std::move(bufferDescriptor));
|
||||
}
|
||||
|
||||
void WebGPUDriver::updateBufferObjectUnsynchronized(Handle<HwBufferObject> bufferObjectHandle,
|
||||
BufferDescriptor&& bufferDescriptor, const uint32_t byteOffset) {
|
||||
handleCast<WebGPUBufferObject>(bufferObjectHandle)
|
||||
->updateGPUBuffer(bufferDescriptor, byteOffset, mDevice, &mQueueManager);
|
||||
->updateGPUBuffer(std::move(bufferDescriptor), byteOffset, mDevice, &mQueueManager);
|
||||
scheduleDestroy(std::move(bufferDescriptor));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -58,6 +59,7 @@ WebGPUQueueManager::WebGPUQueueManager(wgpu::Device const& device)
|
||||
WebGPUQueueManager::~WebGPUQueueManager() = default;
|
||||
|
||||
wgpu::CommandEncoder WebGPUQueueManager::getCommandEncoder() {
|
||||
// std::unique_lock<std::mutex> lock(mLock);
|
||||
if (!mCommandEncoder) {
|
||||
wgpu::CommandEncoderDescriptor commandEncoderDescriptor = {
|
||||
.label = "Filament Command Encoder",
|
||||
@@ -90,7 +92,9 @@ std::shared_ptr<WebGPUSubmissionState> WebGPUQueueManager::getLatestSubmissionSt
|
||||
}
|
||||
|
||||
void WebGPUQueueManager::submit() {
|
||||
// std::unique_lock<std::mutex> lock(mLock);
|
||||
if (!mCommandEncoder) {
|
||||
std::cout << "Run Yu: no mCommandEncoder found!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ private:
|
||||
wgpu::Queue mQueue;
|
||||
wgpu::CommandEncoder mCommandEncoder;
|
||||
std::shared_ptr<WebGPUSubmissionState> mLatestSubmissionState;
|
||||
std::mutex mLock;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
Reference in New Issue
Block a user