Commit b5207f1f authored by Kai Ninomiya's avatar Kai Ninomiya Committed by Commit Bot

Convert bytesPerRow/rowsPerImage undefined to WGPU_STRIDE_UNDEFINED

Blink must also validate against 0xFFFF'FFFF coming in from JS, to
prevent it from being interpreted as WGPU_STRIDE_UNDEFINED by Dawn.
Currently this is done as an exception, but later needs to be an error
injected into the command encoder.

Bug: dawn:520, dawn:566
Change-Id: Ie9c992ffab82830090d0dfc3120731e89cd9691c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2504584Reviewed-by: default avatarAustin Eng <enga@chromium.org>
Reviewed-by: default avatarCorentin Wallez <cwallez@chromium.org>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825653}
parent 75d12e6a
......@@ -857,15 +857,40 @@ WGPUTextureCopyView AsDawnType(const GPUTextureCopyView* webgpu_view,
return dawn_view;
}
WGPUTextureDataLayout AsDawnType(const GPUTextureDataLayout* webgpu_layout) {
// Dawn represents `undefined` as the special uint32_t value
// WGPU_STRIDE_UNDEFINED (0xFFFF'FFFF). Blink must make sure that an actual
// value of 0xFFFF'FFFF coming in from JS is not treated as
// WGPU_STRIDE_UNDEFINED, so it injects an error in that case.
const char* ValidateTextureDataLayout(const GPUTextureDataLayout* webgpu_layout,
WGPUTextureDataLayout* dawn_layout) {
DCHECK(webgpu_layout);
WGPUTextureDataLayout dawn_layout = {};
dawn_layout.offset = webgpu_layout->offset();
dawn_layout.bytesPerRow = webgpu_layout->bytesPerRow();
dawn_layout.rowsPerImage = webgpu_layout->rowsPerImage();
uint32_t bytesPerRow = 0;
if (webgpu_layout->hasBytesPerRow()) {
bytesPerRow = webgpu_layout->bytesPerRow();
if (bytesPerRow == WGPU_STRIDE_UNDEFINED) {
return "bytesPerRow must be a multiple of 256";
}
} else {
bytesPerRow = WGPU_STRIDE_UNDEFINED;
}
uint32_t rowsPerImage = 0;
if (webgpu_layout->hasRowsPerImage()) {
rowsPerImage = webgpu_layout->rowsPerImage();
if (rowsPerImage == WGPU_STRIDE_UNDEFINED) {
return "rowsPerImage is too large";
}
} else {
rowsPerImage = WGPU_STRIDE_UNDEFINED;
}
*dawn_layout = {};
dawn_layout->offset = webgpu_layout->offset();
dawn_layout->bytesPerRow = bytesPerRow;
dawn_layout->rowsPerImage = rowsPerImage;
return dawn_layout;
return nullptr;
}
OwnedProgrammableStageDescriptor AsDawnType(
......
......@@ -49,7 +49,8 @@ WGPUOrigin3D AsDawnType(
const UnsignedLongEnforceRangeSequenceOrGPUOrigin3DDict*);
WGPUTextureCopyView AsDawnType(const GPUTextureCopyView* webgpu_view,
GPUDevice* device);
WGPUTextureDataLayout AsDawnType(const GPUTextureDataLayout* webgpu_layout);
const char* ValidateTextureDataLayout(const GPUTextureDataLayout* webgpu_layout,
WGPUTextureDataLayout* layout);
using OwnedProgrammableStageDescriptor =
std::tuple<WGPUProgrammableStageDescriptor, std::unique_ptr<char[]>>;
OwnedProgrammableStageDescriptor AsDawnType(
......
......@@ -108,16 +108,27 @@ WGPURenderPassDepthStencilAttachmentDescriptor AsDawnType(
return dawn_desc;
}
WGPUBufferCopyView AsDawnType(const GPUBufferCopyView* webgpu_view) {
WGPUBufferCopyView ValidateAndConvertBufferCopyView(
const GPUBufferCopyView* webgpu_view,
ExceptionState& exception_state) {
DCHECK(webgpu_view);
DCHECK(webgpu_view->buffer());
WGPUBufferCopyView dawn_view = {};
dawn_view.nextInChain = nullptr;
dawn_view.buffer = webgpu_view->buffer()->GetHandle();
dawn_view.layout.offset = webgpu_view->offset();
dawn_view.layout.bytesPerRow = webgpu_view->bytesPerRow();
dawn_view.layout.rowsPerImage = webgpu_view->rowsPerImage();
{
const char* error =
ValidateTextureDataLayout(webgpu_view, &dawn_view.layout);
if (error) {
// TODO(crbug.com/dawn/566): This error needs to be injected into the
// encoder, instead of thrown as an exception.
exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
error);
}
}
return dawn_view;
}
......@@ -253,15 +264,17 @@ void GPUCommandEncoder::copyBufferToTexture(
GPUTextureCopyView* destination,
UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size,
ExceptionState& exception_state) {
base::Optional<WGPUBufferCopyView> dawn_source = AsDawnType(source);
if (!dawn_source) {
WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size);
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
WGPUBufferCopyView dawn_source =
ValidateAndConvertBufferCopyView(source, exception_state);
if (exception_state.HadException()) {
return;
}
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size);
GetProcs().commandEncoderCopyBufferToTexture(
GetHandle(), &*dawn_source, &dawn_destination, &dawn_copy_size);
GetHandle(), &dawn_source, &dawn_destination, &dawn_copy_size);
}
void GPUCommandEncoder::copyTextureToBuffer(
......@@ -269,15 +282,17 @@ void GPUCommandEncoder::copyTextureToBuffer(
GPUBufferCopyView* destination,
UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size,
ExceptionState& exception_state) {
WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size);
WGPUTextureCopyView dawn_source = AsDawnType(source, device_);
base::Optional<WGPUBufferCopyView> dawn_destination = AsDawnType(destination);
if (!dawn_destination) {
WGPUBufferCopyView dawn_destination =
ValidateAndConvertBufferCopyView(destination, exception_state);
if (exception_state.HadException()) {
return;
}
WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size);
GetProcs().commandEncoderCopyTextureToBuffer(
GetHandle(), &dawn_source, &*dawn_destination, &dawn_copy_size);
GetHandle(), &dawn_source, &dawn_destination, &dawn_copy_size);
}
void GPUCommandEncoder::copyTextureToTexture(
......
......@@ -95,6 +95,10 @@ GPUDevice::~GPUDevice() {
GetProcs().deviceRelease(GetHandle());
}
void GPUDevice::InjectError(WGPUErrorType type, const char* message) {
GetProcs().deviceInjectError(GetHandle(), type, message);
}
void GPUDevice::AddConsoleWarning(const char* message) {
ExecutionContext* execution_context = GetExecutionContext();
if (execution_context && allowed_console_warnings_remaining_ > 0) {
......
......@@ -109,6 +109,7 @@ class GPUDevice final : public EventTargetWithInlineData,
const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const override;
void InjectError(WGPUErrorType type, const char* message);
void AddConsoleWarning(const char* message);
private:
......
......@@ -304,9 +304,18 @@ void GPUQueue::WriteTextureImpl(
GPUTextureDataLayout* data_layout,
UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& write_size,
ExceptionState& exception_state) {
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
WGPUTextureDataLayout dawn_data_layout = AsDawnType(data_layout);
WGPUExtent3D dawn_write_size = AsDawnType(&write_size);
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
WGPUTextureDataLayout dawn_data_layout = {};
{
const char* error =
ValidateTextureDataLayout(data_layout, &dawn_data_layout);
if (error) {
device_->InjectError(WGPUErrorType_Validation, error);
return;
}
}
GetProcs().queueWriteTexture(GetHandle(), &dawn_destination, data, data_size,
&dawn_data_layout, &dawn_write_size);
......
......@@ -6,6 +6,6 @@
dictionary GPUTextureDataLayout {
GPUSize64 offset = 0;
required GPUSize32 bytesPerRow;
GPUSize32 rowsPerImage = 0;
GPUSize32 bytesPerRow;
GPUSize32 rowsPerImage;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment