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, ...@@ -857,15 +857,40 @@ WGPUTextureCopyView AsDawnType(const GPUTextureCopyView* webgpu_view,
return dawn_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); DCHECK(webgpu_layout);
WGPUTextureDataLayout dawn_layout = {}; uint32_t bytesPerRow = 0;
dawn_layout.offset = webgpu_layout->offset(); if (webgpu_layout->hasBytesPerRow()) {
dawn_layout.bytesPerRow = webgpu_layout->bytesPerRow(); bytesPerRow = webgpu_layout->bytesPerRow();
dawn_layout.rowsPerImage = webgpu_layout->rowsPerImage(); 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( OwnedProgrammableStageDescriptor AsDawnType(
......
...@@ -49,7 +49,8 @@ WGPUOrigin3D AsDawnType( ...@@ -49,7 +49,8 @@ WGPUOrigin3D AsDawnType(
const UnsignedLongEnforceRangeSequenceOrGPUOrigin3DDict*); const UnsignedLongEnforceRangeSequenceOrGPUOrigin3DDict*);
WGPUTextureCopyView AsDawnType(const GPUTextureCopyView* webgpu_view, WGPUTextureCopyView AsDawnType(const GPUTextureCopyView* webgpu_view,
GPUDevice* device); GPUDevice* device);
WGPUTextureDataLayout AsDawnType(const GPUTextureDataLayout* webgpu_layout); const char* ValidateTextureDataLayout(const GPUTextureDataLayout* webgpu_layout,
WGPUTextureDataLayout* layout);
using OwnedProgrammableStageDescriptor = using OwnedProgrammableStageDescriptor =
std::tuple<WGPUProgrammableStageDescriptor, std::unique_ptr<char[]>>; std::tuple<WGPUProgrammableStageDescriptor, std::unique_ptr<char[]>>;
OwnedProgrammableStageDescriptor AsDawnType( OwnedProgrammableStageDescriptor AsDawnType(
......
...@@ -108,16 +108,27 @@ WGPURenderPassDepthStencilAttachmentDescriptor AsDawnType( ...@@ -108,16 +108,27 @@ WGPURenderPassDepthStencilAttachmentDescriptor AsDawnType(
return dawn_desc; return dawn_desc;
} }
WGPUBufferCopyView AsDawnType(const GPUBufferCopyView* webgpu_view) { WGPUBufferCopyView ValidateAndConvertBufferCopyView(
const GPUBufferCopyView* webgpu_view,
ExceptionState& exception_state) {
DCHECK(webgpu_view); DCHECK(webgpu_view);
DCHECK(webgpu_view->buffer()); DCHECK(webgpu_view->buffer());
WGPUBufferCopyView dawn_view = {}; WGPUBufferCopyView dawn_view = {};
dawn_view.nextInChain = nullptr; dawn_view.nextInChain = nullptr;
dawn_view.buffer = webgpu_view->buffer()->GetHandle(); 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; return dawn_view;
} }
...@@ -253,15 +264,17 @@ void GPUCommandEncoder::copyBufferToTexture( ...@@ -253,15 +264,17 @@ void GPUCommandEncoder::copyBufferToTexture(
GPUTextureCopyView* destination, GPUTextureCopyView* destination,
UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size, UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size,
ExceptionState& exception_state) { ExceptionState& exception_state) {
base::Optional<WGPUBufferCopyView> dawn_source = AsDawnType(source); WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size);
if (!dawn_source) { WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
WGPUBufferCopyView dawn_source =
ValidateAndConvertBufferCopyView(source, exception_state);
if (exception_state.HadException()) {
return; return;
} }
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size);
GetProcs().commandEncoderCopyBufferToTexture( GetProcs().commandEncoderCopyBufferToTexture(
GetHandle(), &*dawn_source, &dawn_destination, &dawn_copy_size); GetHandle(), &dawn_source, &dawn_destination, &dawn_copy_size);
} }
void GPUCommandEncoder::copyTextureToBuffer( void GPUCommandEncoder::copyTextureToBuffer(
...@@ -269,15 +282,17 @@ void GPUCommandEncoder::copyTextureToBuffer( ...@@ -269,15 +282,17 @@ void GPUCommandEncoder::copyTextureToBuffer(
GPUBufferCopyView* destination, GPUBufferCopyView* destination,
UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size, UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& copy_size,
ExceptionState& exception_state) { ExceptionState& exception_state) {
WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size);
WGPUTextureCopyView dawn_source = AsDawnType(source, device_); 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; return;
} }
WGPUExtent3D dawn_copy_size = AsDawnType(&copy_size);
GetProcs().commandEncoderCopyTextureToBuffer( GetProcs().commandEncoderCopyTextureToBuffer(
GetHandle(), &dawn_source, &*dawn_destination, &dawn_copy_size); GetHandle(), &dawn_source, &dawn_destination, &dawn_copy_size);
} }
void GPUCommandEncoder::copyTextureToTexture( void GPUCommandEncoder::copyTextureToTexture(
......
...@@ -95,6 +95,10 @@ GPUDevice::~GPUDevice() { ...@@ -95,6 +95,10 @@ GPUDevice::~GPUDevice() {
GetProcs().deviceRelease(GetHandle()); GetProcs().deviceRelease(GetHandle());
} }
void GPUDevice::InjectError(WGPUErrorType type, const char* message) {
GetProcs().deviceInjectError(GetHandle(), type, message);
}
void GPUDevice::AddConsoleWarning(const char* message) { void GPUDevice::AddConsoleWarning(const char* message) {
ExecutionContext* execution_context = GetExecutionContext(); ExecutionContext* execution_context = GetExecutionContext();
if (execution_context && allowed_console_warnings_remaining_ > 0) { if (execution_context && allowed_console_warnings_remaining_ > 0) {
......
...@@ -109,6 +109,7 @@ class GPUDevice final : public EventTargetWithInlineData, ...@@ -109,6 +109,7 @@ class GPUDevice final : public EventTargetWithInlineData,
const AtomicString& InterfaceName() const override; const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const override; ExecutionContext* GetExecutionContext() const override;
void InjectError(WGPUErrorType type, const char* message);
void AddConsoleWarning(const char* message); void AddConsoleWarning(const char* message);
private: private:
......
...@@ -304,9 +304,18 @@ void GPUQueue::WriteTextureImpl( ...@@ -304,9 +304,18 @@ void GPUQueue::WriteTextureImpl(
GPUTextureDataLayout* data_layout, GPUTextureDataLayout* data_layout,
UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& write_size, UnsignedLongEnforceRangeSequenceOrGPUExtent3DDict& write_size,
ExceptionState& exception_state) { ExceptionState& exception_state) {
WGPUTextureCopyView dawn_destination = AsDawnType(destination, device_);
WGPUTextureDataLayout dawn_data_layout = AsDawnType(data_layout);
WGPUExtent3D dawn_write_size = AsDawnType(&write_size); 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, GetProcs().queueWriteTexture(GetHandle(), &dawn_destination, data, data_size,
&dawn_data_layout, &dawn_write_size); &dawn_data_layout, &dawn_write_size);
......
...@@ -6,6 +6,6 @@ ...@@ -6,6 +6,6 @@
dictionary GPUTextureDataLayout { dictionary GPUTextureDataLayout {
GPUSize64 offset = 0; GPUSize64 offset = 0;
required GPUSize32 bytesPerRow; GPUSize32 bytesPerRow;
GPUSize32 rowsPerImage = 0; 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