dawn.node: Implement writeBuffer up to spec.
Bug: dawn:1132 Change-Id: I5b088283c85305f8c8b662478a5a46169a0217fa Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/85503 Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
7b6609f19b
commit
e6359d6058
|
@ -149,6 +149,7 @@ namespace wgpu::binding {
|
|||
auto arr = v.ArrayBuffer();
|
||||
out.data = arr.Data();
|
||||
out.size = arr.ByteLength();
|
||||
out.bytesPerElement = v.ElementSize();
|
||||
},
|
||||
*view);
|
||||
return true;
|
||||
|
@ -156,6 +157,7 @@ namespace wgpu::binding {
|
|||
if (auto* arr = std::get_if<interop::ArrayBuffer>(&in)) {
|
||||
out.data = arr->Data();
|
||||
out.size = arr->ByteLength();
|
||||
out.bytesPerElement = 1;
|
||||
return true;
|
||||
}
|
||||
Napi::Error::New(env, "invalid value for BufferSource").ThrowAsJavaScriptException();
|
||||
|
|
|
@ -95,7 +95,8 @@ namespace wgpu::binding {
|
|||
// BufferSource is the converted type of interop::BufferSource.
|
||||
struct BufferSource {
|
||||
void* data;
|
||||
size_t size;
|
||||
size_t size; // in bytes
|
||||
size_t bytesPerElement; // 1 for ArrayBuffers
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "src/dawn/node/binding/GPUQueue.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#include "src/dawn/node/binding/Converter.h"
|
||||
|
@ -73,8 +75,8 @@ namespace wgpu::binding {
|
|||
interop::Interface<interop::GPUBuffer> buffer,
|
||||
interop::GPUSize64 bufferOffset,
|
||||
interop::BufferSource data,
|
||||
interop::GPUSize64 dataOffset,
|
||||
std::optional<interop::GPUSize64> size) {
|
||||
interop::GPUSize64 dataOffsetElements,
|
||||
std::optional<interop::GPUSize64> sizeElements) {
|
||||
wgpu::Buffer buf = *buffer.As<GPUBuffer>();
|
||||
Converter::BufferSource src{};
|
||||
Converter conv(env);
|
||||
|
@ -82,16 +84,43 @@ namespace wgpu::binding {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO(crbug.com/dawn/1132): Bounds check
|
||||
if (src.data) {
|
||||
src.data = reinterpret_cast<uint8_t*>(src.data) + dataOffset;
|
||||
// Note that in the JS semantics of WebGPU, writeBuffer works in number of elements of the
|
||||
// typed arrays.
|
||||
if (dataOffsetElements > uint64_t(src.size / src.bytesPerElement)) {
|
||||
binding::Errors::OperationError(env, "dataOffset is larger than data's size.")
|
||||
.ThrowAsJavaScriptException();
|
||||
return;
|
||||
}
|
||||
uint64_t dataOffset = dataOffsetElements * src.bytesPerElement;
|
||||
src.data = reinterpret_cast<uint8_t*>(src.data) + dataOffset;
|
||||
src.size -= dataOffset;
|
||||
if (size.has_value()) {
|
||||
src.size = size.value();
|
||||
|
||||
// Size defaults to dataSize - dataOffset. Instead of computing in elements, we directly
|
||||
// use it in bytes, and convert the provided value, if any, in bytes.
|
||||
uint64_t size64 = uint64_t(src.size);
|
||||
if (sizeElements.has_value()) {
|
||||
if (sizeElements.value() > std::numeric_limits<uint64_t>::max() / src.bytesPerElement) {
|
||||
binding::Errors::OperationError(env, "size overflows.")
|
||||
.ThrowAsJavaScriptException();
|
||||
return;
|
||||
}
|
||||
size64 = sizeElements.value() * src.bytesPerElement;
|
||||
}
|
||||
|
||||
queue_.WriteBuffer(buf, bufferOffset, src.data, src.size);
|
||||
if (size64 > uint64_t(src.size)) {
|
||||
binding::Errors::OperationError(env, "size + dataOffset is larger than data's size.")
|
||||
.ThrowAsJavaScriptException();
|
||||
return;
|
||||
}
|
||||
|
||||
if (size64 % 4 != 0) {
|
||||
binding::Errors::OperationError(env, "size is not a multiple of 4 bytes.")
|
||||
.ThrowAsJavaScriptException();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(size64 <= std::numeric_limits<size_t>::max());
|
||||
queue_.WriteBuffer(buf, bufferOffset, src.data, static_cast<size_t>(size64));
|
||||
}
|
||||
|
||||
void GPUQueue::writeTexture(Napi::Env env,
|
||||
|
|
Loading…
Reference in New Issue