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();
|
auto arr = v.ArrayBuffer();
|
||||||
out.data = arr.Data();
|
out.data = arr.Data();
|
||||||
out.size = arr.ByteLength();
|
out.size = arr.ByteLength();
|
||||||
|
out.bytesPerElement = v.ElementSize();
|
||||||
},
|
},
|
||||||
*view);
|
*view);
|
||||||
return true;
|
return true;
|
||||||
|
@ -156,6 +157,7 @@ namespace wgpu::binding {
|
||||||
if (auto* arr = std::get_if<interop::ArrayBuffer>(&in)) {
|
if (auto* arr = std::get_if<interop::ArrayBuffer>(&in)) {
|
||||||
out.data = arr->Data();
|
out.data = arr->Data();
|
||||||
out.size = arr->ByteLength();
|
out.size = arr->ByteLength();
|
||||||
|
out.bytesPerElement = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Napi::Error::New(env, "invalid value for BufferSource").ThrowAsJavaScriptException();
|
Napi::Error::New(env, "invalid value for BufferSource").ThrowAsJavaScriptException();
|
||||||
|
|
|
@ -95,7 +95,8 @@ namespace wgpu::binding {
|
||||||
// BufferSource is the converted type of interop::BufferSource.
|
// BufferSource is the converted type of interop::BufferSource.
|
||||||
struct BufferSource {
|
struct BufferSource {
|
||||||
void* data;
|
void* data;
|
||||||
size_t size;
|
size_t size; // in bytes
|
||||||
|
size_t bytesPerElement; // 1 for ArrayBuffers
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/dawn/node/binding/GPUQueue.h"
|
#include "src/dawn/node/binding/GPUQueue.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "src/dawn/node/binding/Converter.h"
|
#include "src/dawn/node/binding/Converter.h"
|
||||||
|
@ -73,8 +75,8 @@ namespace wgpu::binding {
|
||||||
interop::Interface<interop::GPUBuffer> buffer,
|
interop::Interface<interop::GPUBuffer> buffer,
|
||||||
interop::GPUSize64 bufferOffset,
|
interop::GPUSize64 bufferOffset,
|
||||||
interop::BufferSource data,
|
interop::BufferSource data,
|
||||||
interop::GPUSize64 dataOffset,
|
interop::GPUSize64 dataOffsetElements,
|
||||||
std::optional<interop::GPUSize64> size) {
|
std::optional<interop::GPUSize64> sizeElements) {
|
||||||
wgpu::Buffer buf = *buffer.As<GPUBuffer>();
|
wgpu::Buffer buf = *buffer.As<GPUBuffer>();
|
||||||
Converter::BufferSource src{};
|
Converter::BufferSource src{};
|
||||||
Converter conv(env);
|
Converter conv(env);
|
||||||
|
@ -82,16 +84,43 @@ namespace wgpu::binding {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(crbug.com/dawn/1132): Bounds check
|
// Note that in the JS semantics of WebGPU, writeBuffer works in number of elements of the
|
||||||
if (src.data) {
|
// typed arrays.
|
||||||
src.data = reinterpret_cast<uint8_t*>(src.data) + dataOffset;
|
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;
|
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,
|
void GPUQueue::writeTexture(Napi::Env env,
|
||||||
|
|
Loading…
Reference in New Issue