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