Commit 37c768e9 authored by Kai Ninomiya's avatar Kai Ninomiya Committed by Commit Bot

Update naming for vertex state

Specification change:
https://github.com/gpuweb/gpuweb/pull/469

Dawn roll:
https://dawn.googlesource.com/dawn/+log/c3284fa40ec6b12731ed66c2f2a9256ae3fa692e..ae1f25fee85ebf2773b24a0a4f39c160839b1dbb

CTS roll:
https://github.com/gpuweb/cts/compare/3dc37c83a70667e9a92df773f34d154ec600d203...e114192747a54f34157eb65754e037701fbdf98b

TBR: haraken@chromium.org
Bug: dawn:22
Change-Id: Ib427760b9fba4b2cc4290de046c4a31d77e0b67a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1900807Reviewed-by: default avatarAustin Eng <enga@chromium.org>
Reviewed-by: default avatarYunchao He <yunchao.he@intel.com>
Reviewed-by: default avatarCorentin Wallez <cwallez@chromium.org>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713682}
parent 38512b7a
......@@ -307,7 +307,7 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed
# and whatever else without interference from each other.
'dawn_revision': 'c3284fa40ec6b12731ed66c2f2a9256ae3fa692e',
'dawn_revision': 'ae1f25fee85ebf2773b24a0a4f39c160839b1dbb',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed
# and whatever else without interference from each other.
......
......@@ -867,8 +867,8 @@ modules_dictionary_idl_files =
"webgpu/gpu_texture_view_descriptor.idl",
"webgpu/gpu_uncaptured_error_event_init.idl",
"webgpu/gpu_vertex_attribute_descriptor.idl",
"webgpu/gpu_vertex_buffer_descriptor.idl",
"webgpu/gpu_vertex_input_descriptor.idl",
"webgpu/gpu_vertex_buffer_layout_descriptor.idl",
"webgpu/gpu_vertex_state_descriptor.idl",
"webmidi/midi_connection_event_init.idl",
"webmidi/midi_message_event_init.idl",
"webmidi/midi_options.idl",
......
......@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_vertex_buffer_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_vertex_buffer_layout_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_blend_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.h"
......@@ -12,8 +12,8 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_vertex_input_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_layout_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_vertex_state_descriptor.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
......@@ -84,21 +84,21 @@ WGPUDepthStencilStateDescriptor AsDawnType(
return dawn_desc;
}
using WGPUVertexInputInfo = std::tuple<WGPUVertexInputDescriptor,
Vector<WGPUVertexBufferDescriptor>,
using WGPUVertexStateInfo = std::tuple<WGPUVertexStateDescriptor,
Vector<WGPUVertexBufferLayoutDescriptor>,
Vector<WGPUVertexAttributeDescriptor>>;
WGPUVertexInputInfo GPUVertexInputAsWGPUInputState(
WGPUVertexStateInfo GPUVertexStateAsWGPUVertexState(
v8::Isolate* isolate,
const GPUVertexInputDescriptor* descriptor,
const GPUVertexStateDescriptor* descriptor,
ExceptionState& exception_state) {
WGPUVertexInputDescriptor dawn_desc = {};
WGPUVertexStateDescriptor dawn_desc = {};
dawn_desc.indexFormat =
AsDawnEnum<WGPUIndexFormat>(descriptor->indexFormat());
dawn_desc.bufferCount = 0;
dawn_desc.buffers = nullptr;
dawn_desc.vertexBufferCount = 0;
dawn_desc.vertexBuffers = nullptr;
Vector<WGPUVertexBufferDescriptor> dawn_vertex_buffers;
Vector<WGPUVertexBufferLayoutDescriptor> dawn_vertex_buffers;
Vector<WGPUVertexAttributeDescriptor> dawn_vertex_attributes;
if (descriptor->hasVertexBuffers()) {
......@@ -116,18 +116,18 @@ WGPUVertexInputInfo GPUVertexInputAsWGPUInputState(
v8::Local<v8::Array> vertex_buffers = vertex_buffers_value.As<v8::Array>();
// First we collect all the descriptors but we don't set
// WGPUVertexBufferDescriptor::attributes
// WGPUVertexBufferLayoutDescriptor::attributes
// TODO(cwallez@chromium.org): Should we validate the Length() first so we
// don't risk creating HUGE vectors of WGPUVertexBufferDescriptor from the
// sparse array?
// don't risk creating HUGE vectors of WGPUVertexBufferLayoutDescriptor from
// the sparse array?
for (uint32_t i = 0; i < vertex_buffers->Length(); ++i) {
// This array can be sparse. Skip empty slots.
v8::MaybeLocal<v8::Value> maybe_value = vertex_buffers->Get(context, i);
v8::Local<v8::Value> value;
if (!maybe_value.ToLocal(&value) || value.IsEmpty() ||
value->IsNullOrUndefined()) {
WGPUVertexBufferDescriptor dawn_vertex_buffer = {};
dawn_vertex_buffer.stride = 0;
WGPUVertexBufferLayoutDescriptor dawn_vertex_buffer = {};
dawn_vertex_buffer.arrayStride = 0;
dawn_vertex_buffer.stepMode = WGPUInputStepMode_Vertex;
dawn_vertex_buffer.attributeCount = 0;
dawn_vertex_buffer.attributes = nullptr;
......@@ -135,26 +135,26 @@ WGPUVertexInputInfo GPUVertexInputAsWGPUInputState(
continue;
}
GPUVertexBufferDescriptor vertex_buffer;
V8GPUVertexBufferDescriptor::ToImpl(isolate, value, &vertex_buffer,
exception_state);
GPUVertexBufferLayoutDescriptor vertex_buffer;
V8GPUVertexBufferLayoutDescriptor::ToImpl(isolate, value, &vertex_buffer,
exception_state);
if (exception_state.HadException()) {
return std::make_tuple(dawn_desc, std::move(dawn_vertex_buffers),
std::move(dawn_vertex_attributes));
}
WGPUVertexBufferDescriptor dawn_vertex_buffer = {};
dawn_vertex_buffer.stride = vertex_buffer.stride();
WGPUVertexBufferLayoutDescriptor dawn_vertex_buffer = {};
dawn_vertex_buffer.arrayStride = vertex_buffer.arrayStride();
dawn_vertex_buffer.stepMode =
AsDawnEnum<WGPUInputStepMode>(vertex_buffer.stepMode());
dawn_vertex_buffer.attributeCount =
static_cast<uint32_t>(vertex_buffer.attributeSet().size());
static_cast<uint32_t>(vertex_buffer.attributes().size());
dawn_vertex_buffer.attributes = nullptr;
dawn_vertex_buffers.push_back(dawn_vertex_buffer);
for (wtf_size_t j = 0; j < vertex_buffer.attributeSet().size(); ++j) {
for (wtf_size_t j = 0; j < vertex_buffer.attributes().size(); ++j) {
const GPUVertexAttributeDescriptor* attribute =
vertex_buffer.attributeSet()[j];
vertex_buffer.attributes()[j];
WGPUVertexAttributeDescriptor dawn_vertex_attribute = {};
dawn_vertex_attribute.shaderLocation = attribute->shaderLocation();
dawn_vertex_attribute.offset = attribute->offset();
......@@ -164,10 +164,11 @@ WGPUVertexInputInfo GPUVertexInputAsWGPUInputState(
}
}
// Set up pointers in DawnVertexBufferDescriptor::attributes only after we
// stopped appending to the vector so the pointers aren't invalidated.
// Set up pointers in DawnVertexBufferLayoutDescriptor::attributes only
// after we stopped appending to the vector so the pointers aren't
// invalidated.
uint32_t attributeIndex = 0;
for (WGPUVertexBufferDescriptor& buffer : dawn_vertex_buffers) {
for (WGPUVertexBufferLayoutDescriptor& buffer : dawn_vertex_buffers) {
if (buffer.attributeCount == 0) {
continue;
}
......@@ -176,8 +177,9 @@ WGPUVertexInputInfo GPUVertexInputAsWGPUInputState(
}
}
dawn_desc.bufferCount = static_cast<uint32_t>(dawn_vertex_buffers.size());
dawn_desc.buffers = dawn_vertex_buffers.data();
dawn_desc.vertexBufferCount =
static_cast<uint32_t>(dawn_vertex_buffers.size());
dawn_desc.vertexBuffers = dawn_vertex_buffers.data();
return std::make_tuple(dawn_desc, std::move(dawn_vertex_buffers),
std::move(dawn_vertex_attributes));
......@@ -226,13 +228,12 @@ GPURenderPipeline* GPURenderPipeline::Create(
dawn_desc.fragmentStage = nullptr;
}
// TODO(crbug.com/dawn/131): Update Dawn to match WebGPU vertex input
v8::Isolate* isolate = script_state->GetIsolate();
ExceptionState exception_state(isolate, ExceptionState::kConstructionContext,
"GPUVertexInputDescriptor");
WGPUVertexInputInfo vertex_input_info = GPUVertexInputAsWGPUInputState(
isolate, webgpu_desc->vertexInput(), exception_state);
dawn_desc.vertexInput = &std::get<0>(vertex_input_info);
"GPUVertexStateDescriptor");
WGPUVertexStateInfo vertex_state_info = GPUVertexStateAsWGPUVertexState(
isolate, webgpu_desc->vertexState(), exception_state);
dawn_desc.vertexState = &std::get<0>(vertex_state_info);
if (exception_state.HadException()) {
return nullptr;
......
......@@ -12,7 +12,7 @@ dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
GPURasterizationStateDescriptor rasterizationState = {};
required sequence<GPUColorStateDescriptor> colorStates;
GPUDepthStencilStateDescriptor depthStencilState;
GPUVertexInputDescriptor vertexInput = {};
GPUVertexStateDescriptor vertexState = {};
unsigned long sampleCount = 1;
......
......@@ -4,10 +4,10 @@
// https://gpuweb.github.io/gpuweb/
dictionary GPUVertexBufferDescriptor {
required GPUBufferSize stride;
dictionary GPUVertexBufferLayoutDescriptor {
required GPUBufferSize arrayStride;
GPUInputStepMode stepMode = "vertex";
required sequence<GPUVertexAttributeDescriptor> attributeSet;
required sequence<GPUVertexAttributeDescriptor> attributes;
};
enum GPUInputStepMode {
......
......@@ -4,10 +4,10 @@
// https://gpuweb.github.io/gpuweb/
dictionary GPUVertexInputDescriptor {
dictionary GPUVertexStateDescriptor {
GPUIndexFormat indexFormat = "uint32";
// TODO(crbug.com/951629): Make this a sequence of nullables.
object vertexBuffers; // We validate this is an array of nullable GPUVertexBufferDescriptor
object vertexBuffers; // We validate this is an array of nullable GPUVertexBufferLayoutDescriptor
};
enum GPUIndexFormat {
......
......@@ -39,6 +39,17 @@
width: 100%;
height: 15em;
}
/* Test Name column */
#results > tbody > tr > td:nth-child(2) {
word-break: break-word;
}
/* Message column */
#results > tbody > tr > td:nth-child(3) {
white-space: pre-wrap;
word-break: break-word;
}
</style>
<textarea id=results></textarea>
......@@ -74,4 +85,4 @@
<meta name=variant content='?q=cts:validation/setStencilReference:'>
<meta name=variant content='?q=cts:validation/setVertexBuffer:'>
<meta name=variant content='?q=cts:validation/setViewport:'>
<meta name=variant content='?q=cts:validation/vertex_input:'>
<meta name=variant content='?q=cts:validation/vertex_state:'>
......@@ -27,11 +27,7 @@ export class Fixture {
async init() {}
debug(msg) {
this.rec.debug(msg);
}
log(msg) {
this.rec.log(msg);
this.rec.debug(new Error(msg));
}
skip(msg) {
......@@ -47,11 +43,11 @@ export class Fixture {
}
warn(msg) {
this.rec.warn(msg);
this.rec.warn(new Error(msg));
}
fail(msg) {
this.rec.fail(msg);
this.rec.fail(new Error(msg));
}
async immediateAsyncExpectation(fn) {
......@@ -62,35 +58,40 @@ export class Fixture {
}
eventualAsyncExpectation(fn) {
const promise = fn();
const promise = fn(new Error());
this.eventualExpectations.push(promise);
return promise;
}
expectErrorValue(expectedName, ex, m) {
expectErrorValue(expectedName, ex, niceStack) {
if (!(ex instanceof Error)) {
this.fail('THREW non-error value, of type ' + typeof ex);
niceStack.message = 'THREW non-error value, of type ' + typeof ex + niceStack.message;
this.rec.fail(niceStack);
return;
}
const actualName = ex.name;
if (actualName !== expectedName) {
this.fail(`THREW ${actualName}, instead of ${expectedName}${m}`);
niceStack.message = `THREW ${actualName}, instead of ${expectedName}` + niceStack.message;
this.rec.fail(niceStack);
} else {
this.debug(`OK: threw ${actualName}${m}`);
niceStack.message = 'OK: threw ' + actualName + niceStack.message;
this.rec.debug(niceStack);
}
}
shouldReject(expectedName, p, msg) {
this.eventualAsyncExpectation(async () => {
this.eventualAsyncExpectation(async niceStack => {
const m = msg ? ': ' + msg : '';
try {
await p;
this.fail('DID NOT THROW' + m);
niceStack.message = 'DID NOT THROW' + m;
this.rec.fail(niceStack);
} catch (ex) {
this.expectErrorValue(expectedName, ex, m);
niceStack.message = m;
this.expectErrorValue(expectedName, ex, niceStack);
}
});
}
......@@ -100,18 +101,18 @@ export class Fixture {
try {
fn();
this.fail('DID NOT THROW' + m);
this.rec.fail(new Error('DID NOT THROW' + m));
} catch (ex) {
this.expectErrorValue(expectedName, ex, m);
this.expectErrorValue(expectedName, ex, new Error(m));
}
}
expect(cond, msg) {
if (cond) {
const m = msg ? ': ' + msg : '';
this.debug('expect OK' + m);
this.rec.debug(new Error('expect OK' + m));
} else {
this.rec.fail(msg);
this.rec.fail(new Error(msg));
}
return cond;
......
......@@ -9,6 +9,34 @@ import { makeQueryString } from './url_query.js';
import { extractPublicParams } from './url_query.js';
import { getStackTrace, now } from './util/index.js';
import { version } from './version.js';
class LogMessageWithStack extends Error {
constructor(name, ex) {
super(ex.message);
this.name = name;
this.stack = ex.stack;
}
toJSON() {
let m = this.name;
if (this.message) {
m += ': ' + this.message;
}
m += '\n' + getStackTrace(this);
return m;
}
}
class LogMessageWithoutStack extends LogMessageWithStack {
toJSON() {
return this.message;
}
}
export class Logger {
constructor() {
_defineProperty(this, "results", []);
......@@ -94,46 +122,27 @@ export class TestCaseRecorder {
this.debugging = false;
}
debug(msg) {
debug(ex) {
if (!this.debugging) {
return;
}
this.log('DEBUG: ' + msg);
this.logs.push(new LogMessageWithoutStack('DEBUG', ex));
}
log(msg) {
this.logs.push(msg);
}
warn(msg) {
warn(ex) {
this.setState(PassState.warn);
let m = 'WARN';
if (msg) {
m += ': ' + msg;
}
m += ' ' + getStackTrace(new Error());
this.log(m);
this.logs.push(new LogMessageWithStack('WARN', ex));
}
fail(msg) {
fail(ex) {
this.setState(PassState.fail);
let m = 'FAIL';
if (msg) {
m += ': ' + msg;
}
m += '\n' + getStackTrace(new Error());
this.log(m);
this.logs.push(new LogMessageWithStack('FAIL', ex));
}
skipped(ex) {
this.setState(PassState.skip);
const m = 'SKIPPED: ' + getStackTrace(ex);
this.log(m);
this.logs.push(new LogMessageWithStack('SKIP', ex));
}
threw(ex) {
......@@ -143,7 +152,7 @@ export class TestCaseRecorder {
}
this.setState(PassState.fail);
this.log('EXCEPTION: ' + ex.name + ':\n' + ex.message + '\n' + getStackTrace(ex));
this.logs.push(new LogMessageWithStack('EXCEPTION', ex));
}
setState(state) {
......
// AUTO-GENERATED - DO NOT EDIT. See tools/gen_version.
export const version = '3dc37c83a70667e9a92df773f34d154ec600d203';
export const version = 'e114192747a54f34157eb65754e037701fbdf98b';
......@@ -41,7 +41,7 @@ import { TestWorker } from './helper/test_worker.js';
this.step(() => {
// Unfortunately, it seems not possible to surface any logs for warn/skip.
if (r.status === 'fail') {
throw (r.logs || []).join('\n');
throw (r.logs || []).map(s => s.toJSON()).join('\n\n');
}
});
this.done();
......
......@@ -73,7 +73,7 @@ g.test('fullscreen quad', async t => {
alphaBlend: {},
colorBlend: {}
}],
vertexInput: {
vertexState: {
indexFormat: 'uint16',
vertexBuffers: []
}
......
......@@ -112,41 +112,61 @@ export class GPUTest extends Fixture {
const c = this.device.createCommandEncoder();
c.copyBufferToBuffer(src, 0, dst, 0, size);
this.queue.submit([c.finish()]);
this.eventualAsyncExpectation(async () => {
this.eventualAsyncExpectation(async niceStack => {
const actual = new Uint8Array((await dst.mapReadAsync()));
this.expectBuffer(actual, exp);
const check = this.checkBuffer(actual, exp);
if (check !== undefined) {
niceStack.message = check;
this.rec.fail(niceStack);
}
dst.destroy();
});
}
expectBuffer(actual, exp) {
const check = this.checkBuffer(actual, exp);
if (check !== undefined) {
this.rec.fail(new Error(check));
}
}
checkBuffer(actual, exp) {
const size = exp.byteLength;
if (actual.byteLength !== size) {
this.rec.fail('size mismatch');
return;
return 'size mismatch';
}
const lines = [];
let failedPixels = 0;
for (let i = 0; i < size; ++i) {
if (actual[i] !== exp[i]) {
if (failedPixels > 4) {
this.rec.fail('... and more');
lines.push('... and more');
break;
}
failedPixels++;
this.rec.fail(`at [${i}], expected ${exp[i]}, got ${actual[i]}`);
lines.push(`at [${i}], expected ${exp[i]}, got ${actual[i]}`);
}
}
if (size <= 256 && failedPixels > 0) {
const expHex = Array.from(exp).map(x => x.toString(16).padStart(2, '0')).join('');
const actHex = Array.from(actual).map(x => x.toString(16).padStart(2, '0')).join('');
this.rec.log('EXPECT: ' + expHex);
this.rec.log('ACTUAL: ' + actHex);
lines.push('EXPECT: ' + expHex);
lines.push('ACTUAL: ' + actHex);
}
if (failedPixels) {
return lines.join('\n');
}
return undefined;
}
}
......
......@@ -130,7 +130,7 @@ export const listing = [
"description": "setViewport validation tests."
},
{
"path": "validation/vertex_input",
"description": "vertexInput validation tests."
"path": "validation/vertex_state",
"description": "vertexState validation tests."
}
];
......@@ -29,11 +29,12 @@ class F extends ValidationTest {
colorStates: [{
format: 'rgba8unorm'
}],
vertexInput: {
vertexState: {
vertexBuffers: [{
stride: 3 * 4,
attributeSet: range(bufferCount, i => ({
arrayStride: 3 * 4,
attributes: range(bufferCount, i => ({
format: 'float3',
offset: 0,
shaderLocation: i
}))
}]
......
......@@ -25,13 +25,15 @@ export class ValidationTest extends GPUTest {
this.device.pushErrorScope('validation');
fn();
const promise = this.device.popErrorScope();
this.eventualAsyncExpectation(async () => {
this.eventualAsyncExpectation(async niceStack => {
const gpuValidationError = await promise;
if (!gpuValidationError) {
this.fail('Validation error was expected.');
niceStack.message = 'Validation error was expected.';
this.rec.fail(niceStack);
} else if (gpuValidationError instanceof GPUValidationError) {
this.debug(`Captured validation error - ${gpuValidationError.message}`);
niceStack.message = `Captured validation error - ${gpuValidationError.message}`;
this.rec.debug(niceStack);
}
});
}
......
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