Update naming for vertex state

- VertexInputDescriptor -> VertexStateDescriptor
- VertexBufferDescriptor -> VertexBufferLayoutDescriptor
- VertexBufferDescriptor.stride -> .arrayStride
- VertexAttributeDescriptor.offset no longer optional

gpuweb PR: https://github.com/gpuweb/gpuweb/pull/469

Bug: dawn:22
Change-Id: I5431df4ba22cfbdb1bc81e6709e562cd736892a3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/13100
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Kai Ninomiya 2019-11-07 22:23:29 +00:00 committed by Commit Bot service account
parent c3284fa40e
commit ae1f25fee8
39 changed files with 507 additions and 497 deletions

View File

@ -839,7 +839,7 @@ test("dawn_unittests") {
"src/tests/unittests/validation/ValidationTest.cpp", "src/tests/unittests/validation/ValidationTest.cpp",
"src/tests/unittests/validation/ValidationTest.h", "src/tests/unittests/validation/ValidationTest.h",
"src/tests/unittests/validation/VertexBufferValidationTests.cpp", "src/tests/unittests/validation/VertexBufferValidationTests.cpp",
"src/tests/unittests/validation/VertexInputValidationTests.cpp", "src/tests/unittests/validation/VertexStateValidationTests.cpp",
"src/tests/unittests/wire/WireArgumentTests.cpp", "src/tests/unittests/wire/WireArgumentTests.cpp",
"src/tests/unittests/wire/WireBasicTests.cpp", "src/tests/unittests/wire/WireBasicTests.cpp",
"src/tests/unittests/wire/WireBufferMappingTests.cpp", "src/tests/unittests/wire/WireBufferMappingTests.cpp",
@ -918,7 +918,7 @@ source_set("dawn_end2end_tests_sources") {
"src/tests/end2end/TextureViewTests.cpp", "src/tests/end2end/TextureViewTests.cpp",
"src/tests/end2end/TextureZeroInitTests.cpp", "src/tests/end2end/TextureZeroInitTests.cpp",
"src/tests/end2end/VertexFormatTests.cpp", "src/tests/end2end/VertexFormatTests.cpp",
"src/tests/end2end/VertexInputTests.cpp", "src/tests/end2end/VertexStateTests.cpp",
"src/tests/end2end/ViewportOrientationTests.cpp", "src/tests/end2end/ViewportOrientationTests.cpp",
"src/tests/end2end/ViewportTests.cpp", "src/tests/end2end/ViewportTests.cpp",
] ]

View File

@ -693,28 +693,28 @@
"category": "structure", "category": "structure",
"extensible": false, "extensible": false,
"members": [ "members": [
{"name": "shader location", "type": "uint32_t"}, {"name": "format", "type": "vertex format"},
{"name": "offset", "type": "uint64_t", "default": "0"}, {"name": "offset", "type": "uint64_t"},
{"name": "format", "type": "vertex format"} {"name": "shader location", "type": "uint32_t"}
] ]
}, },
"vertex buffer descriptor": { "vertex buffer layout descriptor": {
"category": "structure", "category": "structure",
"extensible": false, "extensible": false,
"members": [ "members": [
{"name": "stride", "type": "uint64_t"}, {"name": "array stride", "type": "uint64_t"},
{"name": "step mode", "type": "input step mode", "default": "vertex"}, {"name": "step mode", "type": "input step mode", "default": "vertex"},
{"name": "attribute count", "type": "uint32_t"}, {"name": "attribute count", "type": "uint32_t"},
{"name": "attributes", "type": "vertex attribute descriptor", "annotation": "const*", "length": "attribute count"} {"name": "attributes", "type": "vertex attribute descriptor", "annotation": "const*", "length": "attribute count"}
] ]
}, },
"vertex input descriptor": { "vertex state descriptor": {
"category": "structure", "category": "structure",
"extensible": true, "extensible": true,
"members": [ "members": [
{"name": "index format", "type": "index format", "default": "uint32"}, {"name": "index format", "type": "index format", "default": "uint32"},
{"name": "buffer count", "type": "uint32_t", "default": 0}, {"name": "vertex buffer count", "type": "uint32_t", "default": 0},
{"name": "buffers", "type": "vertex buffer descriptor", "annotation": "const*", "length": "buffer count"} {"name": "vertex buffers", "type": "vertex buffer layout descriptor", "annotation": "const*", "length": "vertex buffer count"}
] ]
}, },
"input step mode": { "input step mode": {
@ -1102,7 +1102,7 @@
{"name": "layout", "type": "pipeline layout"}, {"name": "layout", "type": "pipeline layout"},
{"name": "vertex stage", "type": "programmable stage descriptor"}, {"name": "vertex stage", "type": "programmable stage descriptor"},
{"name": "fragment stage", "type": "programmable stage descriptor", "annotation": "const*", "optional": true}, {"name": "fragment stage", "type": "programmable stage descriptor", "annotation": "const*", "optional": true},
{"name": "vertex input", "type": "vertex input descriptor", "annotation": "const*", "optional": true}, {"name": "vertex state", "type": "vertex state descriptor", "annotation": "const*", "optional": true},
{"name": "primitive topology", "type": "primitive topology"}, {"name": "primitive topology", "type": "primitive topology"},
{"name": "rasterization state", "type": "rasterization state descriptor", "annotation": "const*", "optional": true}, {"name": "rasterization state", "type": "rasterization state descriptor", "annotation": "const*", "optional": true},
{"name": "sample count", "type": "uint32_t", "default": "1"}, {"name": "sample count", "type": "uint32_t", "default": "1"},

View File

@ -95,12 +95,12 @@ void init() {
pl.bindGroupLayouts = nullptr; pl.bindGroupLayouts = nullptr;
descriptor.layout = wgpuDeviceCreatePipelineLayout(device, &pl); descriptor.layout = wgpuDeviceCreatePipelineLayout(device, &pl);
WGPUVertexInputDescriptor vertexInput; WGPUVertexStateDescriptor vertexState;
vertexInput.nextInChain = nullptr; vertexState.nextInChain = nullptr;
vertexInput.indexFormat = WGPUIndexFormat_Uint32; vertexState.indexFormat = WGPUIndexFormat_Uint32;
vertexInput.bufferCount = 0; vertexState.vertexBufferCount = 0;
vertexInput.buffers = nullptr; vertexState.vertexBuffers = nullptr;
descriptor.vertexInput = &vertexInput; descriptor.vertexState = &vertexState;
WGPURasterizationStateDescriptor rasterizationState; WGPURasterizationStateDescriptor rasterizationState;
rasterizationState.nextInChain = nullptr; rasterizationState.nextInChain = nullptr;

View File

@ -125,20 +125,20 @@ void initRender() {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.cVertexInput.bufferCount = 2; descriptor.cVertexState.vertexBufferCount = 2;
descriptor.cVertexInput.cBuffers[0].stride = sizeof(Particle); descriptor.cVertexState.cVertexBuffers[0].arrayStride = sizeof(Particle);
descriptor.cVertexInput.cBuffers[0].stepMode = wgpu::InputStepMode::Instance; descriptor.cVertexState.cVertexBuffers[0].stepMode = wgpu::InputStepMode::Instance;
descriptor.cVertexInput.cBuffers[0].attributeCount = 2; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 2;
descriptor.cVertexInput.cAttributes[0].offset = offsetof(Particle, pos); descriptor.cVertexState.cAttributes[0].offset = offsetof(Particle, pos);
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float2; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float2;
descriptor.cVertexInput.cAttributes[1].shaderLocation = 1; descriptor.cVertexState.cAttributes[1].shaderLocation = 1;
descriptor.cVertexInput.cAttributes[1].offset = offsetof(Particle, vel); descriptor.cVertexState.cAttributes[1].offset = offsetof(Particle, vel);
descriptor.cVertexInput.cAttributes[1].format = wgpu::VertexFormat::Float2; descriptor.cVertexState.cAttributes[1].format = wgpu::VertexFormat::Float2;
descriptor.cVertexInput.cBuffers[1].stride = sizeof(glm::vec2); descriptor.cVertexState.cVertexBuffers[1].arrayStride = sizeof(glm::vec2);
descriptor.cVertexInput.cBuffers[1].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[1].attributeCount = 1;
descriptor.cVertexInput.cBuffers[1].attributes = &descriptor.cVertexInput.cAttributes[2]; descriptor.cVertexState.cVertexBuffers[1].attributes = &descriptor.cVertexState.cAttributes[2];
descriptor.cVertexInput.cAttributes[2].shaderLocation = 2; descriptor.cVertexState.cAttributes[2].shaderLocation = 2;
descriptor.cVertexInput.cAttributes[2].format = wgpu::VertexFormat::Float2; descriptor.cVertexState.cAttributes[2].format = wgpu::VertexFormat::Float2;
descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.depthStencilState = &descriptor.cDepthStencilState;
descriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8; descriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8;
descriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat(); descriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat();

View File

@ -129,10 +129,10 @@ void init() {
descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl); descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl);
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.depthStencilState = &descriptor.cDepthStencilState;
descriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8; descriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8;
descriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat(); descriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat();

View File

@ -160,15 +160,15 @@ void init() {
fragColor = vec4(mix(f_col, vec3(0.5, 0.5, 0.5), 0.5), 1.0); fragColor = vec4(mix(f_col, vec3(0.5, 0.5, 0.5), 0.5), 1.0);
})"); })");
utils::ComboVertexInputDescriptor vertexInput; utils::ComboVertexStateDescriptor vertexState;
vertexInput.cBuffers[0].attributeCount = 2; vertexState.cVertexBuffers[0].attributeCount = 2;
vertexInput.cAttributes[0].format = wgpu::VertexFormat::Float3; vertexState.cAttributes[0].format = wgpu::VertexFormat::Float3;
vertexInput.cAttributes[1].shaderLocation = 1; vertexState.cAttributes[1].shaderLocation = 1;
vertexInput.cAttributes[1].offset = 3 * sizeof(float); vertexState.cAttributes[1].offset = 3 * sizeof(float);
vertexInput.cAttributes[1].format = wgpu::VertexFormat::Float3; vertexState.cAttributes[1].format = wgpu::VertexFormat::Float3;
vertexInput.bufferCount = 1; vertexState.vertexBufferCount = 1;
vertexInput.cBuffers[0].stride = 6 * sizeof(float); vertexState.cVertexBuffers[0].arrayStride = 6 * sizeof(float);
auto bgl = utils::MakeBindGroupLayout( auto bgl = utils::MakeBindGroupLayout(
device, { device, {
@ -207,7 +207,7 @@ void init() {
descriptor.layout = pl; descriptor.layout = pl;
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.vertexInput = &vertexInput; descriptor.vertexState = &vertexState;
descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.depthStencilState = &descriptor.cDepthStencilState;
descriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8; descriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8;
descriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat(); descriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat();
@ -220,7 +220,7 @@ void init() {
pDescriptor.layout = pl; pDescriptor.layout = pl;
pDescriptor.vertexStage.module = vsModule; pDescriptor.vertexStage.module = vsModule;
pDescriptor.cFragmentStage.module = fsModule; pDescriptor.cFragmentStage.module = fsModule;
pDescriptor.vertexInput = &vertexInput; pDescriptor.vertexState = &vertexState;
pDescriptor.depthStencilState = &pDescriptor.cDepthStencilState; pDescriptor.depthStencilState = &pDescriptor.cDepthStencilState;
pDescriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8; pDescriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8;
pDescriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat(); pDescriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat();
@ -234,7 +234,7 @@ void init() {
rfDescriptor.layout = pl; rfDescriptor.layout = pl;
rfDescriptor.vertexStage.module = vsModule; rfDescriptor.vertexStage.module = vsModule;
rfDescriptor.cFragmentStage.module = fsReflectionModule; rfDescriptor.cFragmentStage.module = fsReflectionModule;
rfDescriptor.vertexInput = &vertexInput; rfDescriptor.vertexState = &vertexState;
rfDescriptor.depthStencilState = &rfDescriptor.cDepthStencilState; rfDescriptor.depthStencilState = &rfDescriptor.cDepthStencilState;
rfDescriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8; rfDescriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8;
rfDescriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat(); rfDescriptor.cColorStates[0].format = GetPreferredSwapChainTextureFormat();

View File

@ -106,8 +106,9 @@ namespace dawn_native {
if (aspects[VALIDATION_ASPECT_VERTEX_BUFFERS]) { if (aspects[VALIDATION_ASPECT_VERTEX_BUFFERS]) {
ASSERT(mLastRenderPipeline != nullptr); ASSERT(mLastRenderPipeline != nullptr);
auto requiredInputs = mLastRenderPipeline->GetInputsSetMask(); const std::bitset<kMaxVertexBuffers>& requiredVertexBuffers =
if ((mInputsSet & requiredInputs) == requiredInputs) { mLastRenderPipeline->GetVertexBufferSlotsUsed();
if ((mVertexBufferSlotsUsed & requiredVertexBuffers) == requiredVertexBuffers) {
mAspects.set(VALIDATION_ASPECT_VERTEX_BUFFERS); mAspects.set(VALIDATION_ASPECT_VERTEX_BUFFERS);
} }
} }
@ -153,7 +154,7 @@ namespace dawn_native {
} }
void CommandBufferStateTracker::SetVertexBuffer(uint32_t slot) { void CommandBufferStateTracker::SetVertexBuffer(uint32_t slot) {
mInputsSet.set(slot); mVertexBufferSlotsUsed.set(slot);
} }
void CommandBufferStateTracker::SetPipelineCommon(PipelineBase* pipeline) { void CommandBufferStateTracker::SetPipelineCommon(PipelineBase* pipeline) {

View File

@ -53,7 +53,7 @@ namespace dawn_native {
ValidationAspects mAspects; ValidationAspects mAspects;
std::array<BindGroupBase*, kMaxBindGroups> mBindgroups = {}; std::array<BindGroupBase*, kMaxBindGroups> mBindgroups = {};
std::bitset<kMaxVertexBuffers> mInputsSet; std::bitset<kMaxVertexBuffers> mVertexBufferSlotsUsed;
PipelineLayoutBase* mLastPipelineLayout = nullptr; PipelineLayoutBase* mLastPipelineLayout = nullptr;
RenderPipelineBase* mLastRenderPipeline = nullptr; RenderPipelineBase* mLastRenderPipeline = nullptr;

View File

@ -61,44 +61,44 @@ namespace dawn_native {
return {}; return {};
} }
MaybeError ValidateVertexBufferDescriptor( MaybeError ValidateVertexBufferLayoutDescriptor(
const VertexBufferDescriptor* buffer, const VertexBufferLayoutDescriptor* buffer,
std::bitset<kMaxVertexAttributes>* attributesSetMask) { std::bitset<kMaxVertexAttributes>* attributesSetMask) {
DAWN_TRY(ValidateInputStepMode(buffer->stepMode)); DAWN_TRY(ValidateInputStepMode(buffer->stepMode));
if (buffer->stride > kMaxVertexBufferStride) { if (buffer->arrayStride > kMaxVertexBufferStride) {
return DAWN_VALIDATION_ERROR("Setting input stride out of bounds"); return DAWN_VALIDATION_ERROR("Setting arrayStride out of bounds");
} }
if (buffer->stride % 4 != 0) { if (buffer->arrayStride % 4 != 0) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"Stride of Vertex buffer needs to be a multiple of 4 bytes"); "arrayStride of Vertex buffer needs to be a multiple of 4 bytes");
} }
for (uint32_t i = 0; i < buffer->attributeCount; ++i) { for (uint32_t i = 0; i < buffer->attributeCount; ++i) {
DAWN_TRY(ValidateVertexAttributeDescriptor(&buffer->attributes[i], buffer->stride, DAWN_TRY(ValidateVertexAttributeDescriptor(&buffer->attributes[i],
attributesSetMask)); buffer->arrayStride, attributesSetMask));
} }
return {}; return {};
} }
MaybeError ValidateVertexInputDescriptor( MaybeError ValidateVertexStateDescriptor(
const VertexInputDescriptor* descriptor, const VertexStateDescriptor* descriptor,
std::bitset<kMaxVertexAttributes>* attributesSetMask) { std::bitset<kMaxVertexAttributes>* attributesSetMask) {
if (descriptor->nextInChain != nullptr) { if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
} }
DAWN_TRY(ValidateIndexFormat(descriptor->indexFormat)); DAWN_TRY(ValidateIndexFormat(descriptor->indexFormat));
if (descriptor->bufferCount > kMaxVertexBuffers) { if (descriptor->vertexBufferCount > kMaxVertexBuffers) {
return DAWN_VALIDATION_ERROR("Vertex Inputs number exceeds maximum"); return DAWN_VALIDATION_ERROR("Vertex buffer count exceeds maximum");
} }
uint32_t totalAttributesNum = 0; uint32_t totalAttributesNum = 0;
for (uint32_t i = 0; i < descriptor->bufferCount; ++i) { for (uint32_t i = 0; i < descriptor->vertexBufferCount; ++i) {
DAWN_TRY( DAWN_TRY(ValidateVertexBufferLayoutDescriptor(&descriptor->vertexBuffers[i],
ValidateVertexBufferDescriptor(&descriptor->buffers[i], attributesSetMask)); attributesSetMask));
totalAttributesNum += descriptor->buffers[i].attributeCount; totalAttributesNum += descriptor->vertexBuffers[i].attributeCount;
} }
// Every vertex attribute has a member called shaderLocation, and there are some // Every vertex attribute has a member called shaderLocation, and there are some
@ -288,8 +288,8 @@ namespace dawn_native {
} }
std::bitset<kMaxVertexAttributes> attributesSetMask; std::bitset<kMaxVertexAttributes> attributesSetMask;
if (descriptor->vertexInput) { if (descriptor->vertexState) {
DAWN_TRY(ValidateVertexInputDescriptor(descriptor->vertexInput, &attributesSetMask)); DAWN_TRY(ValidateVertexStateDescriptor(descriptor->vertexState, &attributesSetMask));
} }
DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology)); DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology));
@ -305,7 +305,7 @@ namespace dawn_native {
if ((descriptor->vertexStage.module->GetUsedVertexAttributes() & ~attributesSetMask) if ((descriptor->vertexStage.module->GetUsedVertexAttributes() & ~attributesSetMask)
.any()) { .any()) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"Pipeline vertex stage uses inputs not in the input state"); "Pipeline vertex stage uses vertex buffers not in the vertex state");
} }
if (!IsValidSampleCount(descriptor->sampleCount)) { if (!IsValidSampleCount(descriptor->sampleCount)) {
@ -378,29 +378,31 @@ namespace dawn_native {
mVertexEntryPoint(descriptor->vertexStage.entryPoint), mVertexEntryPoint(descriptor->vertexStage.entryPoint),
mFragmentModule(descriptor->fragmentStage->module), mFragmentModule(descriptor->fragmentStage->module),
mFragmentEntryPoint(descriptor->fragmentStage->entryPoint) { mFragmentEntryPoint(descriptor->fragmentStage->entryPoint) {
if (descriptor->vertexInput != nullptr) { if (descriptor->vertexState != nullptr) {
mVertexInput = *descriptor->vertexInput; mVertexState = *descriptor->vertexState;
} else { } else {
mVertexInput = VertexInputDescriptor(); mVertexState = VertexStateDescriptor();
} }
for (uint32_t slot = 0; slot < mVertexInput.bufferCount; ++slot) { for (uint32_t slot = 0; slot < mVertexState.vertexBufferCount; ++slot) {
if (mVertexInput.buffers[slot].attributeCount == 0) { if (mVertexState.vertexBuffers[slot].attributeCount == 0) {
continue; continue;
} }
mInputsSetMask.set(slot); mVertexBufferSlotsUsed.set(slot);
mInputInfos[slot].stride = mVertexInput.buffers[slot].stride; mVertexBufferInfos[slot].arrayStride = mVertexState.vertexBuffers[slot].arrayStride;
mInputInfos[slot].stepMode = mVertexInput.buffers[slot].stepMode; mVertexBufferInfos[slot].stepMode = mVertexState.vertexBuffers[slot].stepMode;
uint32_t location = 0; uint32_t location = 0;
for (uint32_t i = 0; i < mVertexInput.buffers[slot].attributeCount; ++i) { for (uint32_t i = 0; i < mVertexState.vertexBuffers[slot].attributeCount; ++i) {
location = mVertexInput.buffers[slot].attributes[i].shaderLocation; location = mVertexState.vertexBuffers[slot].attributes[i].shaderLocation;
mAttributesSetMask.set(location); mAttributeLocationsUsed.set(location);
mAttributeInfos[location].shaderLocation = location; mAttributeInfos[location].shaderLocation = location;
mAttributeInfos[location].inputSlot = slot; mAttributeInfos[location].vertexBufferSlot = slot;
mAttributeInfos[location].offset = mVertexInput.buffers[slot].attributes[i].offset; mAttributeInfos[location].offset =
mAttributeInfos[location].format = mVertexInput.buffers[slot].attributes[i].format; mVertexState.vertexBuffers[slot].attributes[i].offset;
mAttributeInfos[location].format =
mVertexState.vertexBuffers[slot].attributes[i].format;
} }
} }
@ -454,31 +456,31 @@ namespace dawn_native {
} }
} }
const VertexInputDescriptor* RenderPipelineBase::GetVertexInputDescriptor() const { const VertexStateDescriptor* RenderPipelineBase::GetVertexStateDescriptor() const {
ASSERT(!IsError()); ASSERT(!IsError());
return &mVertexInput; return &mVertexState;
} }
const std::bitset<kMaxVertexAttributes>& RenderPipelineBase::GetAttributesSetMask() const { const std::bitset<kMaxVertexAttributes>& RenderPipelineBase::GetAttributeLocationsUsed() const {
ASSERT(!IsError()); ASSERT(!IsError());
return mAttributesSetMask; return mAttributeLocationsUsed;
} }
const VertexAttributeInfo& RenderPipelineBase::GetAttribute(uint32_t location) const { const VertexAttributeInfo& RenderPipelineBase::GetAttribute(uint32_t location) const {
ASSERT(!IsError()); ASSERT(!IsError());
ASSERT(mAttributesSetMask[location]); ASSERT(mAttributeLocationsUsed[location]);
return mAttributeInfos[location]; return mAttributeInfos[location];
} }
const std::bitset<kMaxVertexBuffers>& RenderPipelineBase::GetInputsSetMask() const { const std::bitset<kMaxVertexBuffers>& RenderPipelineBase::GetVertexBufferSlotsUsed() const {
ASSERT(!IsError()); ASSERT(!IsError());
return mInputsSetMask; return mVertexBufferSlotsUsed;
} }
const VertexBufferInfo& RenderPipelineBase::GetInput(uint32_t slot) const { const VertexBufferInfo& RenderPipelineBase::GetVertexBuffer(uint32_t slot) const {
ASSERT(!IsError()); ASSERT(!IsError());
ASSERT(mInputsSetMask[slot]); ASSERT(mVertexBufferSlotsUsed[slot]);
return mInputInfos[slot]; return mVertexBufferInfos[slot];
} }
const ColorStateDescriptor* RenderPipelineBase::GetColorStateDescriptor( const ColorStateDescriptor* RenderPipelineBase::GetColorStateDescriptor(
@ -540,10 +542,10 @@ namespace dawn_native {
return mAttachmentState.Get(); return mAttachmentState.Get();
} }
std::bitset<kMaxVertexAttributes> RenderPipelineBase::GetAttributesUsingInput( std::bitset<kMaxVertexAttributes> RenderPipelineBase::GetAttributesUsingVertexBuffer(
uint32_t slot) const { uint32_t slot) const {
ASSERT(!IsError()); ASSERT(!IsError());
return attributesUsingInput[slot]; return attributesUsingVertexBuffer[slot];
} }
size_t RenderPipelineBase::HashFunc::operator()(const RenderPipelineBase* pipeline) const { size_t RenderPipelineBase::HashFunc::operator()(const RenderPipelineBase* pipeline) const {
@ -578,20 +580,21 @@ namespace dawn_native {
desc.stencilBack.depthFailOp, desc.stencilBack.passOp); desc.stencilBack.depthFailOp, desc.stencilBack.passOp);
} }
// Hash vertex input state // Hash vertex state
HashCombine(&hash, pipeline->mAttributesSetMask); HashCombine(&hash, pipeline->mAttributeLocationsUsed);
for (uint32_t i : IterateBitSet(pipeline->mAttributesSetMask)) { for (uint32_t i : IterateBitSet(pipeline->mAttributeLocationsUsed)) {
const VertexAttributeInfo& desc = pipeline->GetAttribute(i); const VertexAttributeInfo& desc = pipeline->GetAttribute(i);
HashCombine(&hash, desc.shaderLocation, desc.inputSlot, desc.offset, desc.format); HashCombine(&hash, desc.shaderLocation, desc.vertexBufferSlot, desc.offset,
desc.format);
} }
HashCombine(&hash, pipeline->mInputsSetMask); HashCombine(&hash, pipeline->mVertexBufferSlotsUsed);
for (uint32_t i : IterateBitSet(pipeline->mInputsSetMask)) { for (uint32_t i : IterateBitSet(pipeline->mVertexBufferSlotsUsed)) {
const VertexBufferInfo& desc = pipeline->GetInput(i); const VertexBufferInfo& desc = pipeline->GetVertexBuffer(i);
HashCombine(&hash, desc.stride, desc.stepMode); HashCombine(&hash, desc.arrayStride, desc.stepMode);
} }
HashCombine(&hash, pipeline->mVertexInput.indexFormat); HashCombine(&hash, pipeline->mVertexState.indexFormat);
// Hash rasterization state // Hash rasterization state
{ {
@ -666,34 +669,34 @@ namespace dawn_native {
} }
} }
// Check vertex input state // Check vertex state
if (a->mAttributesSetMask != b->mAttributesSetMask) { if (a->mAttributeLocationsUsed != b->mAttributeLocationsUsed) {
return false; return false;
} }
for (uint32_t i : IterateBitSet(a->mAttributesSetMask)) { for (uint32_t i : IterateBitSet(a->mAttributeLocationsUsed)) {
const VertexAttributeInfo& descA = a->GetAttribute(i); const VertexAttributeInfo& descA = a->GetAttribute(i);
const VertexAttributeInfo& descB = b->GetAttribute(i); const VertexAttributeInfo& descB = b->GetAttribute(i);
if (descA.shaderLocation != descB.shaderLocation || if (descA.shaderLocation != descB.shaderLocation ||
descA.inputSlot != descB.inputSlot || descA.offset != descB.offset || descA.vertexBufferSlot != descB.vertexBufferSlot || descA.offset != descB.offset ||
descA.format != descB.format) { descA.format != descB.format) {
return false; return false;
} }
} }
if (a->mInputsSetMask != b->mInputsSetMask) { if (a->mVertexBufferSlotsUsed != b->mVertexBufferSlotsUsed) {
return false; return false;
} }
for (uint32_t i : IterateBitSet(a->mInputsSetMask)) { for (uint32_t i : IterateBitSet(a->mVertexBufferSlotsUsed)) {
const VertexBufferInfo& descA = a->GetInput(i); const VertexBufferInfo& descA = a->GetVertexBuffer(i);
const VertexBufferInfo& descB = b->GetInput(i); const VertexBufferInfo& descB = b->GetVertexBuffer(i);
if (descA.stride != descB.stride || descA.stepMode != descB.stepMode) { if (descA.arrayStride != descB.arrayStride || descA.stepMode != descB.stepMode) {
return false; return false;
} }
} }
if (a->mVertexInput.indexFormat != b->mVertexInput.indexFormat) { if (a->mVertexState.indexFormat != b->mVertexState.indexFormat) {
return false; return false;
} }

View File

@ -41,14 +41,14 @@ namespace dawn_native {
bool BlendEnabled(const ColorStateDescriptor* mColorState); bool BlendEnabled(const ColorStateDescriptor* mColorState);
struct VertexAttributeInfo { struct VertexAttributeInfo {
uint32_t shaderLocation;
uint32_t inputSlot;
uint64_t offset;
wgpu::VertexFormat format; wgpu::VertexFormat format;
uint64_t offset;
uint32_t shaderLocation;
uint32_t vertexBufferSlot;
}; };
struct VertexBufferInfo { struct VertexBufferInfo {
uint64_t stride; uint64_t arrayStride;
wgpu::InputStepMode stepMode; wgpu::InputStepMode stepMode;
}; };
@ -59,11 +59,11 @@ namespace dawn_native {
static RenderPipelineBase* MakeError(DeviceBase* device); static RenderPipelineBase* MakeError(DeviceBase* device);
const VertexInputDescriptor* GetVertexInputDescriptor() const; const VertexStateDescriptor* GetVertexStateDescriptor() const;
const std::bitset<kMaxVertexAttributes>& GetAttributesSetMask() const; const std::bitset<kMaxVertexAttributes>& GetAttributeLocationsUsed() const;
const VertexAttributeInfo& GetAttribute(uint32_t location) const; const VertexAttributeInfo& GetAttribute(uint32_t location) const;
const std::bitset<kMaxVertexBuffers>& GetInputsSetMask() const; const std::bitset<kMaxVertexBuffers>& GetVertexBufferSlotsUsed() const;
const VertexBufferInfo& GetInput(uint32_t slot) const; const VertexBufferInfo& GetVertexBuffer(uint32_t slot) const;
const ColorStateDescriptor* GetColorStateDescriptor(uint32_t attachmentSlot) const; const ColorStateDescriptor* GetColorStateDescriptor(uint32_t attachmentSlot) const;
const DepthStencilStateDescriptor* GetDepthStencilStateDescriptor() const; const DepthStencilStateDescriptor* GetDepthStencilStateDescriptor() const;
@ -79,8 +79,9 @@ namespace dawn_native {
const AttachmentState* GetAttachmentState() const; const AttachmentState* GetAttachmentState() const;
std::bitset<kMaxVertexAttributes> GetAttributesUsingInput(uint32_t slot) const; std::bitset<kMaxVertexAttributes> GetAttributesUsingVertexBuffer(uint32_t slot) const;
std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexBuffers> attributesUsingInput; std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexBuffers>
attributesUsingVertexBuffer;
// Functors necessary for the unordered_set<RenderPipelineBase*>-based cache. // Functors necessary for the unordered_set<RenderPipelineBase*>-based cache.
struct HashFunc { struct HashFunc {
@ -93,12 +94,12 @@ namespace dawn_native {
private: private:
RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag); RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
// Vertex input // Vertex state
VertexInputDescriptor mVertexInput; VertexStateDescriptor mVertexState;
std::bitset<kMaxVertexAttributes> mAttributesSetMask; std::bitset<kMaxVertexAttributes> mAttributeLocationsUsed;
std::array<VertexAttributeInfo, kMaxVertexAttributes> mAttributeInfos; std::array<VertexAttributeInfo, kMaxVertexAttributes> mAttributeInfos;
std::bitset<kMaxVertexBuffers> mInputsSetMask; std::bitset<kMaxVertexBuffers> mVertexBufferSlotsUsed;
std::array<VertexBufferInfo, kMaxVertexBuffers> mInputInfos; std::array<VertexBufferInfo, kMaxVertexBuffers> mVertexBufferInfos;
// Attachments // Attachments
Ref<AttachmentState> mAttachmentState; Ref<AttachmentState> mAttachmentState;

View File

@ -397,29 +397,30 @@ namespace dawn_native { namespace d3d12 {
auto* d3d12BufferView = &mD3D12BufferViews[slot]; auto* d3d12BufferView = &mD3D12BufferViews[slot];
d3d12BufferView->BufferLocation = buffer->GetVA() + offset; d3d12BufferView->BufferLocation = buffer->GetVA() + offset;
d3d12BufferView->SizeInBytes = buffer->GetSize() - offset; d3d12BufferView->SizeInBytes = buffer->GetSize() - offset;
// The bufferView stride is set based on the input state before a draw. // The bufferView stride is set based on the vertex state before a draw.
} }
void Apply(ID3D12GraphicsCommandList* commandList, void Apply(ID3D12GraphicsCommandList* commandList,
const RenderPipeline* renderPipeline) { const RenderPipeline* renderPipeline) {
ASSERT(renderPipeline != nullptr); ASSERT(renderPipeline != nullptr);
std::bitset<kMaxVertexBuffers> inputsMask = renderPipeline->GetInputsSetMask(); std::bitset<kMaxVertexBuffers> vertexBufferSlotsUsed =
renderPipeline->GetVertexBufferSlotsUsed();
uint32_t startSlot = mStartSlot; uint32_t startSlot = mStartSlot;
uint32_t endSlot = mEndSlot; uint32_t endSlot = mEndSlot;
// If the input state has changed, we need to update the StrideInBytes // If the vertex state has changed, we need to update the StrideInBytes
// for the D3D12 buffer views. We also need to extend the dirty range to // for the D3D12 buffer views. We also need to extend the dirty range to
// touch all these slots because the stride may have changed. // touch all these slots because the stride may have changed.
if (mLastAppliedRenderPipeline != renderPipeline) { if (mLastAppliedRenderPipeline != renderPipeline) {
mLastAppliedRenderPipeline = renderPipeline; mLastAppliedRenderPipeline = renderPipeline;
for (uint32_t slot : IterateBitSet(inputsMask)) { for (uint32_t slot : IterateBitSet(vertexBufferSlotsUsed)) {
startSlot = std::min(startSlot, slot); startSlot = std::min(startSlot, slot);
endSlot = std::max(endSlot, slot + 1); endSlot = std::max(endSlot, slot + 1);
mD3D12BufferViews[slot].StrideInBytes = mD3D12BufferViews[slot].StrideInBytes =
renderPipeline->GetInput(slot).stride; renderPipeline->GetVertexBuffer(slot).arrayStride;
} }
} }
@ -462,7 +463,7 @@ namespace dawn_native { namespace d3d12 {
void OnSetPipeline(const RenderPipelineBase* pipeline) { void OnSetPipeline(const RenderPipelineBase* pipeline) {
mD3D12BufferView.Format = mD3D12BufferView.Format =
DXGIIndexFormat(pipeline->GetVertexInputDescriptor()->indexFormat); DXGIIndexFormat(pipeline->GetVertexStateDescriptor()->indexFormat);
} }
void Apply(ID3D12GraphicsCommandList* commandList) { void Apply(ID3D12GraphicsCommandList* commandList) {

View File

@ -359,7 +359,7 @@ namespace dawn_native { namespace d3d12 {
// D3D12 logs warnings if any empty input state is used // D3D12 logs warnings if any empty input state is used
std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes> inputElementDescriptors; std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes> inputElementDescriptors;
if (GetAttributesSetMask().any()) { if (GetAttributeLocationsUsed().any()) {
descriptorD3D12.InputLayout = ComputeInputLayout(&inputElementDescriptors); descriptorD3D12.InputLayout = ComputeInputLayout(&inputElementDescriptors);
} }
@ -423,7 +423,7 @@ namespace dawn_native { namespace d3d12 {
D3D12_INPUT_LAYOUT_DESC RenderPipeline::ComputeInputLayout( D3D12_INPUT_LAYOUT_DESC RenderPipeline::ComputeInputLayout(
std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes>* inputElementDescriptors) { std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes>* inputElementDescriptors) {
unsigned int count = 0; unsigned int count = 0;
for (auto i : IterateBitSet(GetAttributesSetMask())) { for (auto i : IterateBitSet(GetAttributeLocationsUsed())) {
D3D12_INPUT_ELEMENT_DESC& inputElementDescriptor = (*inputElementDescriptors)[count++]; D3D12_INPUT_ELEMENT_DESC& inputElementDescriptor = (*inputElementDescriptors)[count++];
const VertexAttributeInfo& attribute = GetAttribute(i); const VertexAttributeInfo& attribute = GetAttribute(i);
@ -433,9 +433,9 @@ namespace dawn_native { namespace d3d12 {
inputElementDescriptor.SemanticName = "TEXCOORD"; inputElementDescriptor.SemanticName = "TEXCOORD";
inputElementDescriptor.SemanticIndex = static_cast<uint32_t>(i); inputElementDescriptor.SemanticIndex = static_cast<uint32_t>(i);
inputElementDescriptor.Format = VertexFormatType(attribute.format); inputElementDescriptor.Format = VertexFormatType(attribute.format);
inputElementDescriptor.InputSlot = attribute.inputSlot; inputElementDescriptor.InputSlot = attribute.vertexBufferSlot;
const VertexBufferInfo& input = GetInput(attribute.inputSlot); const VertexBufferInfo& input = GetVertexBuffer(attribute.vertexBufferSlot);
inputElementDescriptor.AlignedByteOffset = attribute.offset; inputElementDescriptor.AlignedByteOffset = attribute.offset;
inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode); inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode);

View File

@ -549,7 +549,7 @@ namespace dawn_native { namespace metal {
// Keeps track of the dirty vertex buffer values so they can be lazily applied when we know // Keeps track of the dirty vertex buffer values so they can be lazily applied when we know
// all the relevant state. // all the relevant state.
class VertexInputBufferTracker { class VertexBufferTracker {
public: public:
void OnSetVertexBuffer(uint32_t slot, Buffer* buffer, uint64_t offset) { void OnSetVertexBuffer(uint32_t slot, Buffer* buffer, uint64_t offset) {
mVertexBuffers[slot] = buffer->GetMTLBuffer(); mVertexBuffers[slot] = buffer->GetMTLBuffer();
@ -564,12 +564,12 @@ namespace dawn_native { namespace metal {
// When a new pipeline is bound we must set all the vertex buffers again because // When a new pipeline is bound we must set all the vertex buffers again because
// they might have been offset by the pipeline layout, and they might be packed // they might have been offset by the pipeline layout, and they might be packed
// differently from the previous pipeline. // differently from the previous pipeline.
mDirtyVertexBuffers |= pipeline->GetInputsSetMask(); mDirtyVertexBuffers |= pipeline->GetVertexBufferSlotsUsed();
} }
void Apply(id<MTLRenderCommandEncoder> encoder, RenderPipeline* pipeline) { void Apply(id<MTLRenderCommandEncoder> encoder, RenderPipeline* pipeline) {
std::bitset<kMaxVertexBuffers> vertexBuffersToApply = std::bitset<kMaxVertexBuffers> vertexBuffersToApply =
mDirtyVertexBuffers & pipeline->GetInputsSetMask(); mDirtyVertexBuffers & pipeline->GetVertexBufferSlotsUsed();
for (uint32_t dawnIndex : IterateBitSet(vertexBuffersToApply)) { for (uint32_t dawnIndex : IterateBitSet(vertexBuffersToApply)) {
uint32_t metalIndex = pipeline->GetMtlVertexBufferIndex(dawnIndex); uint32_t metalIndex = pipeline->GetMtlVertexBufferIndex(dawnIndex);
@ -904,7 +904,7 @@ namespace dawn_native { namespace metal {
RenderPipeline* lastPipeline = nullptr; RenderPipeline* lastPipeline = nullptr;
id<MTLBuffer> indexBuffer = nil; id<MTLBuffer> indexBuffer = nil;
uint32_t indexBufferBaseOffset = 0; uint32_t indexBufferBaseOffset = 0;
VertexInputBufferTracker vertexInputBuffers; VertexBufferTracker vertexBuffers;
StorageBufferLengthTracker storageBufferLengths = {}; StorageBufferLengthTracker storageBufferLengths = {};
BindGroupTracker bindGroups(&storageBufferLengths); BindGroupTracker bindGroups(&storageBufferLengths);
@ -917,7 +917,7 @@ namespace dawn_native { namespace metal {
case Command::Draw: { case Command::Draw: {
DrawCmd* draw = iter->NextCommand<DrawCmd>(); DrawCmd* draw = iter->NextCommand<DrawCmd>();
vertexInputBuffers.Apply(encoder, lastPipeline); vertexBuffers.Apply(encoder, lastPipeline);
bindGroups.Apply(encoder); bindGroups.Apply(encoder);
storageBufferLengths.Apply(encoder, lastPipeline); storageBufferLengths.Apply(encoder, lastPipeline);
@ -934,9 +934,9 @@ namespace dawn_native { namespace metal {
case Command::DrawIndexed: { case Command::DrawIndexed: {
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>(); DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
size_t formatSize = size_t formatSize =
IndexFormatSize(lastPipeline->GetVertexInputDescriptor()->indexFormat); IndexFormatSize(lastPipeline->GetVertexStateDescriptor()->indexFormat);
vertexInputBuffers.Apply(encoder, lastPipeline); vertexBuffers.Apply(encoder, lastPipeline);
bindGroups.Apply(encoder); bindGroups.Apply(encoder);
storageBufferLengths.Apply(encoder, lastPipeline); storageBufferLengths.Apply(encoder, lastPipeline);
@ -957,7 +957,7 @@ namespace dawn_native { namespace metal {
case Command::DrawIndirect: { case Command::DrawIndirect: {
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>(); DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
vertexInputBuffers.Apply(encoder, lastPipeline); vertexBuffers.Apply(encoder, lastPipeline);
bindGroups.Apply(encoder); bindGroups.Apply(encoder);
storageBufferLengths.Apply(encoder, lastPipeline); storageBufferLengths.Apply(encoder, lastPipeline);
@ -971,7 +971,7 @@ namespace dawn_native { namespace metal {
case Command::DrawIndexedIndirect: { case Command::DrawIndexedIndirect: {
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>(); DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
vertexInputBuffers.Apply(encoder, lastPipeline); vertexBuffers.Apply(encoder, lastPipeline);
bindGroups.Apply(encoder); bindGroups.Apply(encoder);
storageBufferLengths.Apply(encoder, lastPipeline); storageBufferLengths.Apply(encoder, lastPipeline);
@ -1013,7 +1013,7 @@ namespace dawn_native { namespace metal {
SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>(); SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
RenderPipeline* newPipeline = ToBackend(cmd->pipeline).Get(); RenderPipeline* newPipeline = ToBackend(cmd->pipeline).Get();
vertexInputBuffers.OnSetPipeline(lastPipeline, newPipeline); vertexBuffers.OnSetPipeline(lastPipeline, newPipeline);
bindGroups.OnSetPipeline(newPipeline); bindGroups.OnSetPipeline(newPipeline);
[encoder setDepthStencilState:newPipeline->GetMTLDepthStencilState()]; [encoder setDepthStencilState:newPipeline->GetMTLDepthStencilState()];
@ -1045,8 +1045,8 @@ namespace dawn_native { namespace metal {
case Command::SetVertexBuffer: { case Command::SetVertexBuffer: {
SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>(); SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();
vertexInputBuffers.OnSetVertexBuffer(cmd->slot, ToBackend(cmd->buffer.Get()), vertexBuffers.OnSetVertexBuffer(cmd->slot, ToBackend(cmd->buffer.Get()),
cmd->offset); cmd->offset);
} break; } break;
default: default:

View File

@ -313,7 +313,7 @@ namespace dawn_native { namespace metal {
RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor) RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
: RenderPipelineBase(device, descriptor), : RenderPipelineBase(device, descriptor),
mMtlIndexType(MTLIndexFormat(GetVertexInputDescriptor()->indexFormat)), mMtlIndexType(MTLIndexFormat(GetVertexStateDescriptor()->indexFormat)),
mMtlPrimitiveTopology(MTLPrimitiveTopology(GetPrimitiveTopology())), mMtlPrimitiveTopology(MTLPrimitiveTopology(GetPrimitiveTopology())),
mMtlFrontFace(MTLFrontFace(GetFrontFace())), mMtlFrontFace(MTLFrontFace(GetFrontFace())),
mMtlCullMode(ToMTLCullMode(GetCullMode())) { mMtlCullMode(ToMTLCullMode(GetCullMode())) {
@ -432,49 +432,49 @@ namespace dawn_native { namespace metal {
uint32_t mtlVertexBufferIndex = uint32_t mtlVertexBufferIndex =
ToBackend(GetLayout())->GetBufferBindingCount(SingleShaderStage::Vertex); ToBackend(GetLayout())->GetBufferBindingCount(SingleShaderStage::Vertex);
for (uint32_t dawnVertexBufferIndex : IterateBitSet(GetInputsSetMask())) { for (uint32_t dawnVertexBufferSlot : IterateBitSet(GetVertexBufferSlotsUsed())) {
const VertexBufferInfo& info = GetInput(dawnVertexBufferIndex); const VertexBufferInfo& info = GetVertexBuffer(dawnVertexBufferSlot);
MTLVertexBufferLayoutDescriptor* layoutDesc = [MTLVertexBufferLayoutDescriptor new]; MTLVertexBufferLayoutDescriptor* layoutDesc = [MTLVertexBufferLayoutDescriptor new];
if (info.stride == 0) { if (info.arrayStride == 0) {
// For MTLVertexStepFunctionConstant, the stepRate must be 0, // For MTLVertexStepFunctionConstant, the stepRate must be 0,
// but the stride must NOT be 0, so we made up it with // but the arrayStride must NOT be 0, so we made up it with
// max(attrib.offset + sizeof(attrib) for each attrib) // max(attrib.offset + sizeof(attrib) for each attrib)
size_t max_stride = 0; size_t maxArrayStride = 0;
for (uint32_t attribIndex : IterateBitSet(GetAttributesSetMask())) { for (uint32_t attribIndex : IterateBitSet(GetAttributeLocationsUsed())) {
const VertexAttributeInfo& attrib = GetAttribute(attribIndex); const VertexAttributeInfo& attrib = GetAttribute(attribIndex);
// Only use the attributes that use the current input // Only use the attributes that use the current input
if (attrib.inputSlot != dawnVertexBufferIndex) { if (attrib.vertexBufferSlot != dawnVertexBufferSlot) {
continue; continue;
} }
max_stride = std::max(max_stride, maxArrayStride = std::max(
VertexFormatSize(attrib.format) + size_t(attrib.offset)); maxArrayStride, VertexFormatSize(attrib.format) + size_t(attrib.offset));
} }
layoutDesc.stepFunction = MTLVertexStepFunctionConstant; layoutDesc.stepFunction = MTLVertexStepFunctionConstant;
layoutDesc.stepRate = 0; layoutDesc.stepRate = 0;
// Metal requires the stride must be a multiple of 4 bytes, align it with next // Metal requires the stride must be a multiple of 4 bytes, align it with next
// multiple of 4 if it's not. // multiple of 4 if it's not.
layoutDesc.stride = Align(max_stride, 4); layoutDesc.stride = Align(maxArrayStride, 4);
} else { } else {
layoutDesc.stepFunction = InputStepModeFunction(info.stepMode); layoutDesc.stepFunction = InputStepModeFunction(info.stepMode);
layoutDesc.stepRate = 1; layoutDesc.stepRate = 1;
layoutDesc.stride = info.stride; layoutDesc.stride = info.arrayStride;
} }
mtlVertexDescriptor.layouts[mtlVertexBufferIndex] = layoutDesc; mtlVertexDescriptor.layouts[mtlVertexBufferIndex] = layoutDesc;
[layoutDesc release]; [layoutDesc release];
mMtlVertexBufferIndices[dawnVertexBufferIndex] = mtlVertexBufferIndex; mMtlVertexBufferIndices[dawnVertexBufferSlot] = mtlVertexBufferIndex;
mtlVertexBufferIndex++; mtlVertexBufferIndex++;
} }
for (uint32_t i : IterateBitSet(GetAttributesSetMask())) { for (uint32_t i : IterateBitSet(GetAttributeLocationsUsed())) {
const VertexAttributeInfo& info = GetAttribute(i); const VertexAttributeInfo& info = GetAttribute(i);
auto attribDesc = [MTLVertexAttributeDescriptor new]; auto attribDesc = [MTLVertexAttributeDescriptor new];
attribDesc.format = VertexFormatType(info.format); attribDesc.format = VertexFormatType(info.format);
attribDesc.offset = info.offset; attribDesc.offset = info.offset;
attribDesc.bufferIndex = mMtlVertexBufferIndices[info.inputSlot]; attribDesc.bufferIndex = mMtlVertexBufferIndices[info.vertexBufferSlot];
mtlVertexDescriptor.attributes[i] = attribDesc; mtlVertexDescriptor.attributes[i] = attribDesc;
[attribDesc release]; [attribDesc release];
} }

View File

@ -133,9 +133,9 @@ namespace dawn_native { namespace opengl {
} }
// Vertex buffers and index buffers are implemented as part of an OpenGL VAO that // Vertex buffers and index buffers are implemented as part of an OpenGL VAO that
// corresponds to an VertexInput. On the contrary in Dawn they are part of the global state. // corresponds to a VertexState. On the contrary in Dawn they are part of the global state.
// This means that we have to re-apply these buffers on an VertexInput change. // This means that we have to re-apply these buffers on a VertexState change.
class InputBufferTracker { class VertexStateBufferBindingTracker {
public: public:
void OnSetIndexBuffer(BufferBase* buffer) { void OnSetIndexBuffer(BufferBase* buffer) {
mIndexBufferDirty = true; mIndexBufferDirty = true;
@ -157,7 +157,7 @@ namespace dawn_native { namespace opengl {
} }
mIndexBufferDirty = true; mIndexBufferDirty = true;
mDirtyVertexBuffers |= pipeline->GetInputsSetMask(); mDirtyVertexBuffers |= pipeline->GetVertexBufferSlotsUsed();
mLastPipeline = pipeline; mLastPipeline = pipeline;
} }
@ -168,30 +168,32 @@ namespace dawn_native { namespace opengl {
mIndexBufferDirty = false; mIndexBufferDirty = false;
} }
for (uint32_t slot : for (uint32_t slot : IterateBitSet(mDirtyVertexBuffers &
IterateBitSet(mDirtyVertexBuffers & mLastPipeline->GetInputsSetMask())) { mLastPipeline->GetVertexBufferSlotsUsed())) {
for (uint32_t location : for (uint32_t location :
IterateBitSet(mLastPipeline->GetAttributesUsingInput(slot))) { IterateBitSet(mLastPipeline->GetAttributesUsingVertexBuffer(slot))) {
auto attribute = mLastPipeline->GetAttribute(location); const VertexAttributeInfo& attribute =
mLastPipeline->GetAttribute(location);
GLuint buffer = mVertexBuffers[slot]->GetHandle(); GLuint buffer = mVertexBuffers[slot]->GetHandle();
uint64_t offset = mVertexBufferOffsets[slot]; uint64_t offset = mVertexBufferOffsets[slot];
auto input = mLastPipeline->GetInput(slot); const VertexBufferInfo& vertexBuffer = mLastPipeline->GetVertexBuffer(slot);
auto components = VertexFormatNumComponents(attribute.format); uint32_t components = VertexFormatNumComponents(attribute.format);
auto formatType = VertexFormatType(attribute.format); GLenum formatType = VertexFormatType(attribute.format);
GLboolean normalized = VertexFormatIsNormalized(attribute.format); GLboolean normalized = VertexFormatIsNormalized(attribute.format);
gl.BindBuffer(GL_ARRAY_BUFFER, buffer); gl.BindBuffer(GL_ARRAY_BUFFER, buffer);
if (VertexFormatIsInt(attribute.format)) { if (VertexFormatIsInt(attribute.format)) {
gl.VertexAttribIPointer(location, components, formatType, input.stride, gl.VertexAttribIPointer(
reinterpret_cast<void*>(static_cast<intptr_t>( location, components, formatType, vertexBuffer.arrayStride,
offset + attribute.offset)));
} else {
gl.VertexAttribPointer(
location, components, formatType, normalized, input.stride,
reinterpret_cast<void*>( reinterpret_cast<void*>(
static_cast<intptr_t>(offset + attribute.offset))); static_cast<intptr_t>(offset + attribute.offset)));
} else {
gl.VertexAttribPointer(location, components, formatType, normalized,
vertexBuffer.arrayStride,
reinterpret_cast<void*>(static_cast<intptr_t>(
offset + attribute.offset)));
} }
} }
} }
@ -855,14 +857,14 @@ namespace dawn_native { namespace opengl {
RenderPipeline* lastPipeline = nullptr; RenderPipeline* lastPipeline = nullptr;
uint64_t indexBufferBaseOffset = 0; uint64_t indexBufferBaseOffset = 0;
InputBufferTracker inputBuffers; VertexStateBufferBindingTracker vertexStateBufferBindingTracker;
BindGroupTracker bindGroupTracker = {}; BindGroupTracker bindGroupTracker = {};
auto DoRenderBundleCommand = [&](CommandIterator* iter, Command type) { auto DoRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) { switch (type) {
case Command::Draw: { case Command::Draw: {
DrawCmd* draw = iter->NextCommand<DrawCmd>(); DrawCmd* draw = iter->NextCommand<DrawCmd>();
inputBuffers.Apply(gl); vertexStateBufferBindingTracker.Apply(gl);
bindGroupTracker.Apply(gl); bindGroupTracker.Apply(gl);
if (draw->firstInstance > 0) { if (draw->firstInstance > 0) {
@ -879,11 +881,11 @@ namespace dawn_native { namespace opengl {
case Command::DrawIndexed: { case Command::DrawIndexed: {
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>(); DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
inputBuffers.Apply(gl); vertexStateBufferBindingTracker.Apply(gl);
bindGroupTracker.Apply(gl); bindGroupTracker.Apply(gl);
wgpu::IndexFormat indexFormat = wgpu::IndexFormat indexFormat =
lastPipeline->GetVertexInputDescriptor()->indexFormat; lastPipeline->GetVertexStateDescriptor()->indexFormat;
size_t formatSize = IndexFormatSize(indexFormat); size_t formatSize = IndexFormatSize(indexFormat);
GLenum formatType = IndexFormatType(indexFormat); GLenum formatType = IndexFormatType(indexFormat);
@ -905,7 +907,7 @@ namespace dawn_native { namespace opengl {
case Command::DrawIndirect: { case Command::DrawIndirect: {
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>(); DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
inputBuffers.Apply(gl); vertexStateBufferBindingTracker.Apply(gl);
bindGroupTracker.Apply(gl); bindGroupTracker.Apply(gl);
uint64_t indirectBufferOffset = draw->indirectOffset; uint64_t indirectBufferOffset = draw->indirectOffset;
@ -919,11 +921,11 @@ namespace dawn_native { namespace opengl {
case Command::DrawIndexedIndirect: { case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>(); DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
inputBuffers.Apply(gl); vertexStateBufferBindingTracker.Apply(gl);
bindGroupTracker.Apply(gl); bindGroupTracker.Apply(gl);
wgpu::IndexFormat indexFormat = wgpu::IndexFormat indexFormat =
lastPipeline->GetVertexInputDescriptor()->indexFormat; lastPipeline->GetVertexStateDescriptor()->indexFormat;
GLenum formatType = IndexFormatType(indexFormat); GLenum formatType = IndexFormatType(indexFormat);
uint64_t indirectBufferOffset = draw->indirectOffset; uint64_t indirectBufferOffset = draw->indirectOffset;
@ -948,7 +950,7 @@ namespace dawn_native { namespace opengl {
lastPipeline = ToBackend(cmd->pipeline).Get(); lastPipeline = ToBackend(cmd->pipeline).Get();
lastPipeline->ApplyNow(persistentPipelineState); lastPipeline->ApplyNow(persistentPipelineState);
inputBuffers.OnSetPipeline(lastPipeline); vertexStateBufferBindingTracker.OnSetPipeline(lastPipeline);
bindGroupTracker.OnSetPipeline(lastPipeline); bindGroupTracker.OnSetPipeline(lastPipeline);
} break; } break;
@ -965,12 +967,13 @@ namespace dawn_native { namespace opengl {
case Command::SetIndexBuffer: { case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>(); SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
indexBufferBaseOffset = cmd->offset; indexBufferBaseOffset = cmd->offset;
inputBuffers.OnSetIndexBuffer(cmd->buffer.Get()); vertexStateBufferBindingTracker.OnSetIndexBuffer(cmd->buffer.Get());
} break; } break;
case Command::SetVertexBuffer: { case Command::SetVertexBuffer: {
SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>(); SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();
inputBuffers.OnSetVertexBuffer(cmd->slot, cmd->buffer.Get(), cmd->offset); vertexStateBufferBindingTracker.OnSetVertexBuffer(cmd->slot, cmd->buffer.Get(),
cmd->offset);
} break; } break;
default: default:

View File

@ -202,7 +202,7 @@ namespace dawn_native { namespace opengl {
modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module); modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), modules); PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), modules);
CreateVAOForVertexInput(descriptor->vertexInput); CreateVAOForVertexState(descriptor->vertexState);
} }
RenderPipeline::~RenderPipeline() { RenderPipeline::~RenderPipeline() {
@ -215,25 +215,25 @@ namespace dawn_native { namespace opengl {
return mGlPrimitiveTopology; return mGlPrimitiveTopology;
} }
void RenderPipeline::CreateVAOForVertexInput(const VertexInputDescriptor* vertexInput) { void RenderPipeline::CreateVAOForVertexState(const VertexStateDescriptor* vertexState) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl; const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
gl.GenVertexArrays(1, &mVertexArrayObject); gl.GenVertexArrays(1, &mVertexArrayObject);
gl.BindVertexArray(mVertexArrayObject); gl.BindVertexArray(mVertexArrayObject);
for (uint32_t location : IterateBitSet(GetAttributesSetMask())) { for (uint32_t location : IterateBitSet(GetAttributeLocationsUsed())) {
const auto& attribute = GetAttribute(location); const auto& attribute = GetAttribute(location);
gl.EnableVertexAttribArray(location); gl.EnableVertexAttribArray(location);
attributesUsingInput[attribute.inputSlot][location] = true; attributesUsingVertexBuffer[attribute.vertexBufferSlot][location] = true;
auto input = GetInput(attribute.inputSlot); const VertexBufferInfo& vertexBuffer = GetVertexBuffer(attribute.vertexBufferSlot);
if (input.stride == 0) { if (vertexBuffer.arrayStride == 0) {
// Emulate a stride of zero (constant vertex attribute) by // Emulate a stride of zero (constant vertex attribute) by
// setting the attribute instance divisor to a huge number. // setting the attribute instance divisor to a huge number.
gl.VertexAttribDivisor(location, 0xffffffff); gl.VertexAttribDivisor(location, 0xffffffff);
} else { } else {
switch (input.stepMode) { switch (vertexBuffer.stepMode) {
case wgpu::InputStepMode::Vertex: case wgpu::InputStepMode::Vertex:
break; break;
case wgpu::InputStepMode::Instance: case wgpu::InputStepMode::Instance:

View File

@ -37,7 +37,7 @@ namespace dawn_native { namespace opengl {
void ApplyNow(PersistentPipelineState& persistentPipelineState); void ApplyNow(PersistentPipelineState& persistentPipelineState);
private: private:
void CreateVAOForVertexInput(const VertexInputDescriptor* vertexInput); void CreateVAOForVertexState(const VertexStateDescriptor* vertexState);
// TODO(yunchao.he@intel.com): vao need to be deduplicated between pipelines. // TODO(yunchao.he@intel.com): vao need to be deduplicated between pipelines.
GLuint mVertexArrayObject; GLuint mVertexArrayObject;

View File

@ -867,7 +867,7 @@ namespace dawn_native { namespace vulkan {
// and rebind if needed on pipeline change // and rebind if needed on pipeline change
ASSERT(lastPipeline != nullptr); ASSERT(lastPipeline != nullptr);
VkIndexType indexType = VkIndexType indexType =
VulkanIndexType(lastPipeline->GetVertexInputDescriptor()->indexFormat); VulkanIndexType(lastPipeline->GetVertexStateDescriptor()->indexFormat);
device->fn.CmdBindIndexBuffer( device->fn.CmdBindIndexBuffer(
commands, indexBuffer, static_cast<VkDeviceSize>(cmd->offset), indexType); commands, indexBuffer, static_cast<VkDeviceSize>(cmd->offset), indexType);
} break; } break;

View File

@ -351,11 +351,9 @@ namespace dawn_native { namespace vulkan {
shaderStages[1].pName = descriptor->fragmentStage->entryPoint; shaderStages[1].pName = descriptor->fragmentStage->entryPoint;
} }
std::array<VkVertexInputBindingDescription, kMaxVertexBuffers> mBindings; PipelineVertexInputStateCreateInfoTemporaryAllocations tempAllocations;
std::array<VkVertexInputAttributeDescription, kMaxVertexAttributes> mAttributes;
const VertexInputDescriptor* vertexInput = GetVertexInputDescriptor();
VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo = VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo =
ComputeVertexInputDesc(vertexInput, &mBindings, &mAttributes); ComputeVertexInputDesc(&tempAllocations);
VkPipelineInputAssemblyStateCreateInfo inputAssembly; VkPipelineInputAssemblyStateCreateInfo inputAssembly;
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
@ -507,32 +505,31 @@ namespace dawn_native { namespace vulkan {
} }
VkPipelineVertexInputStateCreateInfo RenderPipeline::ComputeVertexInputDesc( VkPipelineVertexInputStateCreateInfo RenderPipeline::ComputeVertexInputDesc(
const VertexInputDescriptor* vertexInput, PipelineVertexInputStateCreateInfoTemporaryAllocations* tempAllocations) {
std::array<VkVertexInputBindingDescription, kMaxVertexBuffers>* mBindings,
std::array<VkVertexInputAttributeDescription, kMaxVertexAttributes>* mAttributes) {
// Fill in the "binding info" that will be chained in the create info // Fill in the "binding info" that will be chained in the create info
uint32_t bindingCount = 0; uint32_t bindingCount = 0;
for (uint32_t i : IterateBitSet(GetInputsSetMask())) { for (uint32_t i : IterateBitSet(GetVertexBufferSlotsUsed())) {
const auto& bindingInfo = GetInput(i); const VertexBufferInfo& bindingInfo = GetVertexBuffer(i);
auto& bindingDesc = (*mBindings)[bindingCount]; VkVertexInputBindingDescription* bindingDesc = &tempAllocations->bindings[bindingCount];
bindingDesc.binding = i; bindingDesc->binding = i;
bindingDesc.stride = bindingInfo.stride; bindingDesc->stride = bindingInfo.arrayStride;
bindingDesc.inputRate = VulkanInputRate(bindingInfo.stepMode); bindingDesc->inputRate = VulkanInputRate(bindingInfo.stepMode);
bindingCount++; bindingCount++;
} }
// Fill in the "attribute info" that will be chained in the create info // Fill in the "attribute info" that will be chained in the create info
uint32_t attributeCount = 0; uint32_t attributeCount = 0;
for (uint32_t i : IterateBitSet(GetAttributesSetMask())) { for (uint32_t i : IterateBitSet(GetAttributeLocationsUsed())) {
const auto& attributeInfo = GetAttribute(i); const VertexAttributeInfo& attributeInfo = GetAttribute(i);
auto& attributeDesc = (*mAttributes)[attributeCount]; VkVertexInputAttributeDescription* attributeDesc =
attributeDesc.location = i; &tempAllocations->attributes[attributeCount];
attributeDesc.binding = attributeInfo.inputSlot; attributeDesc->location = i;
attributeDesc.format = VulkanVertexFormat(attributeInfo.format); attributeDesc->binding = attributeInfo.vertexBufferSlot;
attributeDesc.offset = attributeInfo.offset; attributeDesc->format = VulkanVertexFormat(attributeInfo.format);
attributeDesc->offset = attributeInfo.offset;
attributeCount++; attributeCount++;
} }
@ -543,9 +540,9 @@ namespace dawn_native { namespace vulkan {
mCreateInfo.pNext = nullptr; mCreateInfo.pNext = nullptr;
mCreateInfo.flags = 0; mCreateInfo.flags = 0;
mCreateInfo.vertexBindingDescriptionCount = bindingCount; mCreateInfo.vertexBindingDescriptionCount = bindingCount;
mCreateInfo.pVertexBindingDescriptions = &(*mBindings)[0]; mCreateInfo.pVertexBindingDescriptions = tempAllocations->bindings.data();
mCreateInfo.vertexAttributeDescriptionCount = attributeCount; mCreateInfo.vertexAttributeDescriptionCount = attributeCount;
mCreateInfo.pVertexAttributeDescriptions = &(*mAttributes)[0]; mCreateInfo.pVertexAttributeDescriptions = tempAllocations->attributes.data();
return mCreateInfo; return mCreateInfo;
} }

View File

@ -36,10 +36,12 @@ namespace dawn_native { namespace vulkan {
using RenderPipelineBase::RenderPipelineBase; using RenderPipelineBase::RenderPipelineBase;
MaybeError Initialize(const RenderPipelineDescriptor* descriptor); MaybeError Initialize(const RenderPipelineDescriptor* descriptor);
struct PipelineVertexInputStateCreateInfoTemporaryAllocations {
std::array<VkVertexInputBindingDescription, kMaxVertexBuffers> bindings;
std::array<VkVertexInputAttributeDescription, kMaxVertexAttributes> attributes;
};
VkPipelineVertexInputStateCreateInfo ComputeVertexInputDesc( VkPipelineVertexInputStateCreateInfo ComputeVertexInputDesc(
const VertexInputDescriptor* vertexInput, PipelineVertexInputStateCreateInfoTemporaryAllocations* temporaryAllocations);
std::array<VkVertexInputBindingDescription, kMaxVertexBuffers>* mBindings,
std::array<VkVertexInputAttributeDescription, kMaxVertexAttributes>* mAttributes);
VkPipeline mHandle = VK_NULL_HANDLE; VkPipeline mHandle = VK_NULL_HANDLE;
}; };

View File

@ -46,10 +46,10 @@ class DestroyTest : public DawnTest {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor); pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -46,10 +46,10 @@ class DrawIndexedIndirectTest : public DawnTest {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor); pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -46,10 +46,10 @@ class DrawIndexedTest : public DawnTest {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor); pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -46,10 +46,10 @@ class DrawIndirectTest : public DawnTest {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor); pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -46,10 +46,10 @@ class DrawTest : public DawnTest {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor); pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -51,11 +51,11 @@ class IndexFormatTest : public DawnTest {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip;
descriptor.cVertexInput.indexFormat = format; descriptor.cVertexState.indexFormat = format;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
return device.CreateRenderPipeline(&descriptor); return device.CreateRenderPipeline(&descriptor);

View File

@ -187,10 +187,10 @@ class PrimitiveTopologyTest : public DawnTest {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = primitiveTopology; descriptor.primitiveTopology = primitiveTopology;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor); wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -77,10 +77,10 @@ class RenderBundleTest : public DawnTest {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; descriptor.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor); pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -362,10 +362,10 @@ class VertexFormatTest : public DawnTest {
utils::ComboRenderPipelineDescriptor descriptor(device); utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.cVertexInput.bufferCount = 1; descriptor.cVertexState.vertexBufferCount = 1;
descriptor.cVertexInput.cBuffers[0].stride = strideBytes; descriptor.cVertexState.cVertexBuffers[0].arrayStride = strideBytes;
descriptor.cVertexInput.cBuffers[0].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor.cVertexInput.cAttributes[0].format = format; descriptor.cVertexState.cAttributes[0].format = format;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
return device.CreateRenderPipeline(&descriptor); return device.CreateRenderPipeline(&descriptor);

View File

@ -21,10 +21,11 @@
using wgpu::InputStepMode; using wgpu::InputStepMode;
using wgpu::VertexFormat; using wgpu::VertexFormat;
// Input state tests all work the same way: the test will render triangles in a grid up to 4x4. Each triangle // Input state tests all work the same way: the test will render triangles in a grid up to 4x4. Each
// is position in the grid such that X will correspond to the "triangle number" and the Y to the instance number. // triangle is position in the grid such that X will correspond to the "triangle number" and the Y
// Each test will set up an input state and buffers, and the vertex shader will check that the vertex attributes // to the instance number. Each test will set up an input state and buffers, and the vertex shader
// corresponds to predetermined values. On success it outputs green, otherwise red. // will check that the vertex attributes corresponds to predetermined values. On success it outputs
// green, otherwise red.
// //
// The predetermined values are "K * gl_VertexID + componentIndex" for vertex-indexed buffers, and // The predetermined values are "K * gl_VertexID + componentIndex" for vertex-indexed buffers, and
// "K * gl_InstanceID + componentIndex" for instance-indexed buffers. // "K * gl_InstanceID + componentIndex" for instance-indexed buffers.
@ -33,7 +34,7 @@ constexpr static unsigned int kRTSize = 400;
constexpr static unsigned int kRTCellOffset = 50; constexpr static unsigned int kRTCellOffset = 50;
constexpr static unsigned int kRTCellSize = 100; constexpr static unsigned int kRTCellSize = 100;
class VertexInputTest : public DawnTest { class VertexStateTest : public DawnTest {
protected: protected:
void TestSetUp() override { void TestSetUp() override {
DawnTest::TestSetUp(); DawnTest::TestSetUp();
@ -64,7 +65,7 @@ class VertexInputTest : public DawnTest {
VertexFormat format; VertexFormat format;
InputStepMode step; InputStepMode step;
}; };
wgpu::RenderPipeline MakeTestPipeline(const wgpu::VertexInputDescriptor& vertexInput, wgpu::RenderPipeline MakeTestPipeline(const wgpu::VertexStateDescriptor& vertexState,
int multiplier, int multiplier,
const std::vector<ShaderTestSpec>& testSpec) { const std::vector<ShaderTestSpec>& testSpec) {
std::ostringstream vs; std::ostringstream vs;
@ -131,7 +132,7 @@ class VertexInputTest : public DawnTest {
utils::ComboRenderPipelineDescriptor descriptor(device); utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.vertexInput = &vertexInput; descriptor.vertexState = &vertexState;
descriptor.cColorStates[0].format = renderPass.colorFormat; descriptor.cColorStates[0].format = renderPass.colorFormat;
return device.CreateRenderPipeline(&descriptor); return device.CreateRenderPipeline(&descriptor);
@ -143,37 +144,37 @@ class VertexInputTest : public DawnTest {
VertexFormat format; VertexFormat format;
}; };
struct VertexBufferSpec { struct VertexBufferSpec {
uint64_t stride; uint64_t arrayStride;
InputStepMode step; InputStepMode step;
std::vector<VertexAttributeSpec> attributes; std::vector<VertexAttributeSpec> attributes;
}; };
utils::ComboVertexInputDescriptor MakeVertexInput( utils::ComboVertexStateDescriptor MakeVertexState(
const std::vector<VertexBufferSpec>& buffers) { const std::vector<VertexBufferSpec>& buffers) {
utils::ComboVertexInputDescriptor vertexInput; utils::ComboVertexStateDescriptor vertexState;
uint32_t bufferCount = 0; uint32_t vertexBufferCount = 0;
uint32_t totalNumAttributes = 0; uint32_t totalNumAttributes = 0;
for (const VertexBufferSpec& buffer : buffers) { for (const VertexBufferSpec& buffer : buffers) {
vertexInput.cBuffers[bufferCount].stride = buffer.stride; vertexState.cVertexBuffers[vertexBufferCount].arrayStride = buffer.arrayStride;
vertexInput.cBuffers[bufferCount].stepMode = buffer.step; vertexState.cVertexBuffers[vertexBufferCount].stepMode = buffer.step;
vertexInput.cBuffers[bufferCount].attributes = vertexState.cVertexBuffers[vertexBufferCount].attributes =
&vertexInput.cAttributes[totalNumAttributes]; &vertexState.cAttributes[totalNumAttributes];
for (const VertexAttributeSpec& attribute : buffer.attributes) { for (const VertexAttributeSpec& attribute : buffer.attributes) {
vertexInput.cAttributes[totalNumAttributes].shaderLocation = attribute.location; vertexState.cAttributes[totalNumAttributes].shaderLocation = attribute.location;
vertexInput.cAttributes[totalNumAttributes].offset = attribute.offset; vertexState.cAttributes[totalNumAttributes].offset = attribute.offset;
vertexInput.cAttributes[totalNumAttributes].format = attribute.format; vertexState.cAttributes[totalNumAttributes].format = attribute.format;
totalNumAttributes++; totalNumAttributes++;
} }
vertexInput.cBuffers[bufferCount].attributeCount = vertexState.cVertexBuffers[vertexBufferCount].attributeCount =
static_cast<uint32_t>(buffer.attributes.size()); static_cast<uint32_t>(buffer.attributes.size());
bufferCount++; vertexBufferCount++;
} }
vertexInput.bufferCount = bufferCount; vertexState.vertexBufferCount = vertexBufferCount;
return vertexInput; return vertexState;
} }
template <typename T> template <typename T>
@ -232,11 +233,11 @@ class VertexInputTest : public DawnTest {
}; };
// Test compilation and usage of the fixture :) // Test compilation and usage of the fixture :)
TEST_P(VertexInputTest, Basic) { TEST_P(VertexStateTest, Basic) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor vertexState = MakeVertexState(
{{4 * sizeof(float), InputStepMode::Vertex, {{0, 0, VertexFormat::Float4}}}}); {{4 * sizeof(float), InputStepMode::Vertex, {{0, 0, VertexFormat::Float4}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}}); MakeTestPipeline(vertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
// clang-format off // clang-format off
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({ wgpu::Buffer buffer0 = MakeVertexBuffer<float>({
@ -249,14 +250,14 @@ TEST_P(VertexInputTest, Basic) {
} }
// Test a stride of 0 works // Test a stride of 0 works
TEST_P(VertexInputTest, ZeroStride) { TEST_P(VertexStateTest, ZeroStride) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet. // This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL()); DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
utils::ComboVertexInputDescriptor vertexInput = utils::ComboVertexStateDescriptor vertexState =
MakeVertexInput({{0, InputStepMode::Vertex, {{0, 0, VertexFormat::Float4}}}}); MakeVertexState({{0, InputStepMode::Vertex, {{0, 0, VertexFormat::Float4}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 0, {{0, VertexFormat::Float4, InputStepMode::Vertex}}); MakeTestPipeline(vertexState, 0, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({ wgpu::Buffer buffer0 = MakeVertexBuffer<float>({
0, 0,
@ -268,36 +269,36 @@ TEST_P(VertexInputTest, ZeroStride) {
} }
// Test attributes defaults to (0, 0, 0, 1) if the input state doesn't have all components // Test attributes defaults to (0, 0, 0, 1) if the input state doesn't have all components
TEST_P(VertexInputTest, AttributeExpanding) { TEST_P(VertexStateTest, AttributeExpanding) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet. // This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL()); DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
// R32F case // R32F case
{ {
utils::ComboVertexInputDescriptor vertexInput = utils::ComboVertexStateDescriptor vertexState =
MakeVertexInput({{0, InputStepMode::Vertex, {{0, 0, VertexFormat::Float}}}}); MakeVertexState({{0, InputStepMode::Vertex, {{0, 0, VertexFormat::Float}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 0, {{0, VertexFormat::Float, InputStepMode::Vertex}}); MakeTestPipeline(vertexState, 0, {{0, VertexFormat::Float, InputStepMode::Vertex}});
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({0, 1, 2, 3}); wgpu::Buffer buffer0 = MakeVertexBuffer<float>({0, 1, 2, 3});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}}); DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
} }
// RG32F case // RG32F case
{ {
utils::ComboVertexInputDescriptor vertexInput = utils::ComboVertexStateDescriptor vertexState =
MakeVertexInput({{0, InputStepMode::Vertex, {{0, 0, VertexFormat::Float2}}}}); MakeVertexState({{0, InputStepMode::Vertex, {{0, 0, VertexFormat::Float2}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 0, {{0, VertexFormat::Float2, InputStepMode::Vertex}}); MakeTestPipeline(vertexState, 0, {{0, VertexFormat::Float2, InputStepMode::Vertex}});
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({0, 1, 2, 3}); wgpu::Buffer buffer0 = MakeVertexBuffer<float>({0, 1, 2, 3});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}}); DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
} }
// RGB32F case // RGB32F case
{ {
utils::ComboVertexInputDescriptor vertexInput = utils::ComboVertexStateDescriptor vertexState =
MakeVertexInput({{0, InputStepMode::Vertex, {{0, 0, VertexFormat::Float3}}}}); MakeVertexState({{0, InputStepMode::Vertex, {{0, 0, VertexFormat::Float3}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 0, {{0, VertexFormat::Float3, InputStepMode::Vertex}}); MakeTestPipeline(vertexState, 0, {{0, VertexFormat::Float3, InputStepMode::Vertex}});
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({0, 1, 2, 3}); wgpu::Buffer buffer0 = MakeVertexBuffer<float>({0, 1, 2, 3});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}}); DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
@ -305,14 +306,14 @@ TEST_P(VertexInputTest, AttributeExpanding) {
} }
// Test a stride larger than the attributes // Test a stride larger than the attributes
TEST_P(VertexInputTest, StrideLargerThanAttributes) { TEST_P(VertexStateTest, StrideLargerThanAttributes) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet. // This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL()); DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor vertexState = MakeVertexState(
{{8 * sizeof(float), InputStepMode::Vertex, {{0, 0, VertexFormat::Float4}}}}); {{8 * sizeof(float), InputStepMode::Vertex, {{0, 0, VertexFormat::Float4}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}}); MakeTestPipeline(vertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
// clang-format off // clang-format off
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({ wgpu::Buffer buffer0 = MakeVertexBuffer<float>({
@ -325,13 +326,13 @@ TEST_P(VertexInputTest, StrideLargerThanAttributes) {
} }
// Test two attributes at an offset, vertex version // Test two attributes at an offset, vertex version
TEST_P(VertexInputTest, TwoAttributesAtAnOffsetVertex) { TEST_P(VertexStateTest, TwoAttributesAtAnOffsetVertex) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor vertexState = MakeVertexState(
{{8 * sizeof(float), {{8 * sizeof(float),
InputStepMode::Vertex, InputStepMode::Vertex,
{{0, 0, VertexFormat::Float4}, {1, 4 * sizeof(float), VertexFormat::Float4}}}}); {{0, 0, VertexFormat::Float4}, {1, 4 * sizeof(float), VertexFormat::Float4}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}}); MakeTestPipeline(vertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
// clang-format off // clang-format off
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({ wgpu::Buffer buffer0 = MakeVertexBuffer<float>({
@ -344,13 +345,13 @@ TEST_P(VertexInputTest, TwoAttributesAtAnOffsetVertex) {
} }
// Test two attributes at an offset, instance version // Test two attributes at an offset, instance version
TEST_P(VertexInputTest, TwoAttributesAtAnOffsetInstance) { TEST_P(VertexStateTest, TwoAttributesAtAnOffsetInstance) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor vertexState = MakeVertexState(
{{8 * sizeof(float), {{8 * sizeof(float),
InputStepMode::Instance, InputStepMode::Instance,
{{0, 0, VertexFormat::Float4}, {1, 4 * sizeof(float), VertexFormat::Float4}}}}); {{0, 0, VertexFormat::Float4}, {1, 4 * sizeof(float), VertexFormat::Float4}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}}); MakeTestPipeline(vertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
// clang-format off // clang-format off
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({ wgpu::Buffer buffer0 = MakeVertexBuffer<float>({
@ -363,11 +364,11 @@ TEST_P(VertexInputTest, TwoAttributesAtAnOffsetInstance) {
} }
// Test a pure-instance input state // Test a pure-instance input state
TEST_P(VertexInputTest, PureInstance) { TEST_P(VertexStateTest, PureInstance) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor vertexState = MakeVertexState(
{{4 * sizeof(float), InputStepMode::Instance, {{0, 0, VertexFormat::Float4}}}}); {{4 * sizeof(float), InputStepMode::Instance, {{0, 0, VertexFormat::Float4}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}}); MakeTestPipeline(vertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
// clang-format off // clang-format off
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({ wgpu::Buffer buffer0 = MakeVertexBuffer<float>({
@ -382,8 +383,8 @@ TEST_P(VertexInputTest, PureInstance) {
// Test with mixed everything, vertex vs. instance, different stride and offsets // Test with mixed everything, vertex vs. instance, different stride and offsets
// different attribute types // different attribute types
TEST_P(VertexInputTest, MixedEverything) { TEST_P(VertexStateTest, MixedEverything) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor vertexState = MakeVertexState(
{{12 * sizeof(float), {{12 * sizeof(float),
InputStepMode::Vertex, InputStepMode::Vertex,
{{0, 0, VertexFormat::Float}, {1, 6 * sizeof(float), VertexFormat::Float2}}}, {{0, 0, VertexFormat::Float}, {1, 6 * sizeof(float), VertexFormat::Float2}}},
@ -391,7 +392,7 @@ TEST_P(VertexInputTest, MixedEverything) {
InputStepMode::Instance, InputStepMode::Instance,
{{2, 0, VertexFormat::Float3}, {3, 5 * sizeof(float), VertexFormat::Float4}}}}); {{2, 0, VertexFormat::Float3}, {3, 5 * sizeof(float), VertexFormat::Float4}}}});
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, MakeTestPipeline(vertexState, 1,
{{0, VertexFormat::Float, InputStepMode::Vertex}, {{0, VertexFormat::Float, InputStepMode::Vertex},
{1, VertexFormat::Float2, InputStepMode::Vertex}, {1, VertexFormat::Float2, InputStepMode::Vertex},
{2, VertexFormat::Float3, InputStepMode::Instance}, {2, VertexFormat::Float3, InputStepMode::Instance},
@ -415,13 +416,13 @@ TEST_P(VertexInputTest, MixedEverything) {
} }
// Test input state is unaffected by unused vertex slot // Test input state is unaffected by unused vertex slot
TEST_P(VertexInputTest, UnusedVertexSlot) { TEST_P(VertexStateTest, UnusedVertexSlot) {
// Instance input state, using slot 1 // Instance input state, using slot 1
utils::ComboVertexInputDescriptor instanceVertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor instanceVertexState = MakeVertexState(
{{0, InputStepMode::Vertex, {}}, {{0, InputStepMode::Vertex, {}},
{4 * sizeof(float), InputStepMode::Instance, {{0, 0, VertexFormat::Float4}}}}); {4 * sizeof(float), InputStepMode::Instance, {{0, 0, VertexFormat::Float4}}}});
wgpu::RenderPipeline instancePipeline = MakeTestPipeline( wgpu::RenderPipeline instancePipeline = MakeTestPipeline(
instanceVertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}}); instanceVertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
// clang-format off // clang-format off
wgpu::Buffer buffer = MakeVertexBuffer<float>({ wgpu::Buffer buffer = MakeVertexBuffer<float>({
@ -454,19 +455,19 @@ TEST_P(VertexInputTest, UnusedVertexSlot) {
// This was a problem with the D3D12 backend where SetVertexBuffer // This was a problem with the D3D12 backend where SetVertexBuffer
// was getting the input from the last set pipeline, not the current. // was getting the input from the last set pipeline, not the current.
// SetVertexBuffer should be reapplied when the input state changes. // SetVertexBuffer should be reapplied when the input state changes.
TEST_P(VertexInputTest, MultiplePipelinesMixedVertexInput) { TEST_P(VertexStateTest, MultiplePipelinesMixedVertexState) {
// Basic input state, using slot 0 // Basic input state, using slot 0
utils::ComboVertexInputDescriptor vertexVertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor vertexVertexState = MakeVertexState(
{{4 * sizeof(float), InputStepMode::Vertex, {{0, 0, VertexFormat::Float4}}}}); {{4 * sizeof(float), InputStepMode::Vertex, {{0, 0, VertexFormat::Float4}}}});
wgpu::RenderPipeline vertexPipeline = wgpu::RenderPipeline vertexPipeline =
MakeTestPipeline(vertexVertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}}); MakeTestPipeline(vertexVertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
// Instance input state, using slot 1 // Instance input state, using slot 1
utils::ComboVertexInputDescriptor instanceVertexInput = MakeVertexInput( utils::ComboVertexStateDescriptor instanceVertexState = MakeVertexState(
{{0, InputStepMode::Instance, {}}, {{0, InputStepMode::Instance, {}},
{4 * sizeof(float), InputStepMode::Instance, {{0, 0, VertexFormat::Float4}}}}); {4 * sizeof(float), InputStepMode::Instance, {{0, 0, VertexFormat::Float4}}}});
wgpu::RenderPipeline instancePipeline = MakeTestPipeline( wgpu::RenderPipeline instancePipeline = MakeTestPipeline(
instanceVertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}}); instanceVertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
// clang-format off // clang-format off
wgpu::Buffer buffer = MakeVertexBuffer<float>({ wgpu::Buffer buffer = MakeVertexBuffer<float>({
@ -499,28 +500,28 @@ TEST_P(VertexInputTest, MultiplePipelinesMixedVertexInput) {
} }
// Checks that using the last vertex buffer doesn't overflow the vertex buffer table in Metal. // Checks that using the last vertex buffer doesn't overflow the vertex buffer table in Metal.
TEST_P(VertexInputTest, LastAllowedVertexBuffer) { TEST_P(VertexStateTest, LastAllowedVertexBuffer) {
constexpr uint32_t kBufferIndex = kMaxVertexBuffers - 1; constexpr uint32_t kBufferIndex = kMaxVertexBuffers - 1;
utils::ComboVertexInputDescriptor vertexInput; utils::ComboVertexStateDescriptor vertexState;
// All the other vertex buffers default to no attributes // All the other vertex buffers default to no attributes
vertexInput.bufferCount = kMaxVertexBuffers; vertexState.vertexBufferCount = kMaxVertexBuffers;
vertexInput.cBuffers[kBufferIndex].stride = 4 * sizeof(float); vertexState.cVertexBuffers[kBufferIndex].arrayStride = 4 * sizeof(float);
vertexInput.cBuffers[kBufferIndex].stepMode = InputStepMode::Vertex; vertexState.cVertexBuffers[kBufferIndex].stepMode = InputStepMode::Vertex;
vertexInput.cBuffers[kBufferIndex].attributeCount = 1; vertexState.cVertexBuffers[kBufferIndex].attributeCount = 1;
vertexInput.cBuffers[kBufferIndex].attributes = &vertexInput.cAttributes[0]; vertexState.cVertexBuffers[kBufferIndex].attributes = &vertexState.cAttributes[0];
vertexInput.cAttributes[0].shaderLocation = 0; vertexState.cAttributes[0].shaderLocation = 0;
vertexInput.cAttributes[0].offset = 0; vertexState.cAttributes[0].offset = 0;
vertexInput.cAttributes[0].format = VertexFormat::Float4; vertexState.cAttributes[0].format = VertexFormat::Float4;
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}}); MakeTestPipeline(vertexState, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
wgpu::Buffer buffer0 = MakeVertexBuffer<float>({0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5}); wgpu::Buffer buffer0 = MakeVertexBuffer<float>({0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{kMaxVertexBuffers - 1, &buffer0}}); DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{kMaxVertexBuffers - 1, &buffer0}});
} }
DAWN_INSTANTIATE_TEST(VertexInputTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend); DAWN_INSTANTIATE_TEST(VertexStateTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);
// TODO for the input state: // TODO for the input state:
// - Add more vertex formats // - Add more vertex formats
@ -530,10 +531,10 @@ DAWN_INSTANTIATE_TEST(VertexInputTest, D3D12Backend, MetalBackend, OpenGLBackend
// - Check for attribute narrowing // - Check for attribute narrowing
// - Check that the input state and the pipeline vertex input types match // - Check that the input state and the pipeline vertex input types match
class OptionalVertexInputTest : public DawnTest {}; class OptionalVertexStateTest : public DawnTest {};
// Test that vertex input is not required in render pipeline descriptor. // Test that vertex input is not required in render pipeline descriptor.
TEST_P(OptionalVertexInputTest, Basic) { TEST_P(OptionalVertexStateTest, Basic) {
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 3, 3); utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 3, 3);
wgpu::ShaderModule vsModule = wgpu::ShaderModule vsModule =
@ -556,7 +557,7 @@ TEST_P(OptionalVertexInputTest, Basic) {
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = wgpu::PrimitiveTopology::PointList; descriptor.primitiveTopology = wgpu::PrimitiveTopology::PointList;
descriptor.vertexInput = nullptr; descriptor.vertexState = nullptr;
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor); wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
@ -574,7 +575,7 @@ TEST_P(OptionalVertexInputTest, Basic) {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 1, 1); EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 1, 1);
} }
DAWN_INSTANTIATE_TEST(OptionalVertexInputTest, DAWN_INSTANTIATE_TEST(OptionalVertexStateTest,
D3D12Backend, D3D12Backend,
MetalBackend, MetalBackend,
OpenGLBackend, OpenGLBackend,

View File

@ -346,10 +346,10 @@ void DrawCallPerf::TestSetUp() {
// Setup the base render pipeline descriptor. // Setup the base render pipeline descriptor.
utils::ComboRenderPipelineDescriptor renderPipelineDesc(device); utils::ComboRenderPipelineDescriptor renderPipelineDesc(device);
renderPipelineDesc.cVertexInput.bufferCount = 1; renderPipelineDesc.cVertexState.vertexBufferCount = 1;
renderPipelineDesc.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); renderPipelineDesc.cVertexState.cVertexBuffers[0].arrayStride = 4 * sizeof(float);
renderPipelineDesc.cVertexInput.cBuffers[0].attributeCount = 1; renderPipelineDesc.cVertexState.cVertexBuffers[0].attributeCount = 1;
renderPipelineDesc.cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float4; renderPipelineDesc.cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float4;
renderPipelineDesc.depthStencilState = &renderPipelineDesc.cDepthStencilState; renderPipelineDesc.depthStencilState = &renderPipelineDesc.cDepthStencilState;
renderPipelineDesc.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8; renderPipelineDesc.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8;
renderPipelineDesc.cColorStates[0].format = wgpu::TextureFormat::RGBA8Unorm; renderPipelineDesc.cColorStates[0].format = wgpu::TextureFormat::RGBA8Unorm;

View File

@ -98,11 +98,11 @@ namespace {
descriptor->layout = pipelineLayout; descriptor->layout = pipelineLayout;
descriptor->vertexStage.module = vsModule; descriptor->vertexStage.module = vsModule;
descriptor->cFragmentStage.module = fsModule; descriptor->cFragmentStage.module = fsModule;
descriptor->cVertexInput.bufferCount = 1; descriptor->cVertexState.vertexBufferCount = 1;
descriptor->cVertexInput.cBuffers[0].stride = 2 * sizeof(float); descriptor->cVertexState.cVertexBuffers[0].arrayStride = 2 * sizeof(float);
descriptor->cVertexInput.cBuffers[0].attributeCount = 1; descriptor->cVertexState.cVertexBuffers[0].attributeCount = 1;
descriptor->cVertexInput.cAttributes[0].format = wgpu::VertexFormat::Float2; descriptor->cVertexState.cAttributes[0].format = wgpu::VertexFormat::Float2;
descriptor->cVertexInput.cAttributes[0].shaderLocation = 0; descriptor->cVertexState.cAttributes[0].shaderLocation = 0;
} }
wgpu::ShaderModule vsModule; wgpu::ShaderModule vsModule;

View File

@ -57,7 +57,7 @@ TEST_F(RenderPipelineValidationTest, CreationSuccess) {
utils::ComboRenderPipelineDescriptor descriptor(device); utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.vertexInput = nullptr; descriptor.vertexState = nullptr;
device.CreateRenderPipeline(&descriptor); device.CreateRenderPipeline(&descriptor);
} }

View File

@ -70,13 +70,13 @@ class VertexBufferValidationTest : public ValidationTest {
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
for (unsigned int i = 0; i < bufferCount; ++i) { for (unsigned int i = 0; i < bufferCount; ++i) {
descriptor.cVertexInput.cBuffers[i].attributeCount = 1; descriptor.cVertexState.cVertexBuffers[i].attributeCount = 1;
descriptor.cVertexInput.cBuffers[i].attributes = descriptor.cVertexState.cVertexBuffers[i].attributes =
&descriptor.cVertexInput.cAttributes[i]; &descriptor.cVertexState.cAttributes[i];
descriptor.cVertexInput.cAttributes[i].shaderLocation = i; descriptor.cVertexState.cAttributes[i].shaderLocation = i;
descriptor.cVertexInput.cAttributes[i].format = wgpu::VertexFormat::Float3; descriptor.cVertexState.cAttributes[i].format = wgpu::VertexFormat::Float3;
} }
descriptor.cVertexInput.bufferCount = bufferCount; descriptor.cVertexState.vertexBufferCount = bufferCount;
return device.CreateRenderPipeline(&descriptor); return device.CreateRenderPipeline(&descriptor);
} }

View File

@ -17,10 +17,10 @@
#include "utils/ComboRenderPipelineDescriptor.h" #include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/WGPUHelpers.h" #include "utils/WGPUHelpers.h"
class VertexInputTest : public ValidationTest { class VertexStateTest : public ValidationTest {
protected: protected:
void CreatePipeline(bool success, void CreatePipeline(bool success,
const utils::ComboVertexInputDescriptor& state, const utils::ComboVertexStateDescriptor& state,
std::string vertexSource) { std::string vertexSource) {
wgpu::ShaderModule vsModule = utils::CreateShaderModule( wgpu::ShaderModule vsModule = utils::CreateShaderModule(
device, utils::SingleShaderStage::Vertex, vertexSource.c_str()); device, utils::SingleShaderStage::Vertex, vertexSource.c_str());
@ -36,7 +36,7 @@ class VertexInputTest : public ValidationTest {
utils::ComboRenderPipelineDescriptor descriptor(device); utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.vertexStage.module = vsModule; descriptor.vertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.vertexInput = &state; descriptor.vertexState = &state;
descriptor.cColorStates[0].format = wgpu::TextureFormat::RGBA8Unorm; descriptor.cColorStates[0].format = wgpu::TextureFormat::RGBA8Unorm;
if (!success) { if (!success) {
@ -48,8 +48,8 @@ class VertexInputTest : public ValidationTest {
}; };
// Check an empty vertex input is valid // Check an empty vertex input is valid
TEST_F(VertexInputTest, EmptyIsOk) { TEST_F(VertexStateTest, EmptyIsOk) {
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -59,13 +59,13 @@ TEST_F(VertexInputTest, EmptyIsOk) {
} }
// Check null buffer is valid // Check null buffer is valid
TEST_F(VertexInputTest, NullBufferIsOk) { TEST_F(VertexStateTest, NullBufferIsOk) {
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
// One null buffer (buffer[0]) is OK // One null buffer (buffer[0]) is OK
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].stride = 0; state.cVertexBuffers[0].arrayStride = 0;
state.cBuffers[0].attributeCount = 0; state.cVertexBuffers[0].attributeCount = 0;
state.cBuffers[0].attributes = nullptr; state.cVertexBuffers[0].attributes = nullptr;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -74,10 +74,10 @@ TEST_F(VertexInputTest, NullBufferIsOk) {
)"); )");
// One null buffer (buffer[0]) followed by a buffer (buffer[1]) is OK // One null buffer (buffer[0]) followed by a buffer (buffer[1]) is OK
state.bufferCount = 2; state.vertexBufferCount = 2;
state.cBuffers[1].stride = 0; state.cVertexBuffers[1].arrayStride = 0;
state.cBuffers[1].attributeCount = 1; state.cVertexBuffers[1].attributeCount = 1;
state.cBuffers[1].attributes = &state.cAttributes[0]; state.cVertexBuffers[1].attributes = &state.cAttributes[0];
state.cAttributes[0].shaderLocation = 0; state.cAttributes[0].shaderLocation = 0;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
@ -87,11 +87,11 @@ TEST_F(VertexInputTest, NullBufferIsOk) {
)"); )");
// Null buffer (buffer[2]) sitting between buffers (buffer[1] and buffer[3]) is OK // Null buffer (buffer[2]) sitting between buffers (buffer[1] and buffer[3]) is OK
state.bufferCount = 4; state.vertexBufferCount = 4;
state.cBuffers[2].attributeCount = 0; state.cVertexBuffers[2].attributeCount = 0;
state.cBuffers[2].attributes = nullptr; state.cVertexBuffers[2].attributes = nullptr;
state.cBuffers[3].attributeCount = 1; state.cVertexBuffers[3].attributeCount = 1;
state.cBuffers[3].attributes = &state.cAttributes[1]; state.cVertexBuffers[3].attributes = &state.cAttributes[1];
state.cAttributes[1].shaderLocation = 1; state.cAttributes[1].shaderLocation = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
@ -103,11 +103,11 @@ TEST_F(VertexInputTest, NullBufferIsOk) {
// Check validation that pipeline vertex buffers are backed by attributes in the vertex input // Check validation that pipeline vertex buffers are backed by attributes in the vertex input
// Check validation that pipeline vertex buffers are backed by attributes in the vertex input // Check validation that pipeline vertex buffers are backed by attributes in the vertex input
TEST_F(VertexInputTest, PipelineCompatibility) { TEST_F(VertexStateTest, PipelineCompatibility) {
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].stride = 2 * sizeof(float); state.cVertexBuffers[0].arrayStride = 2 * sizeof(float);
state.cBuffers[0].attributeCount = 2; state.cVertexBuffers[0].attributeCount = 2;
state.cAttributes[0].shaderLocation = 0; state.cAttributes[0].shaderLocation = 0;
state.cAttributes[1].shaderLocation = 1; state.cAttributes[1].shaderLocation = 1;
state.cAttributes[1].offset = sizeof(float); state.cAttributes[1].offset = sizeof(float);
@ -122,7 +122,7 @@ TEST_F(VertexInputTest, PipelineCompatibility) {
} }
)"); )");
// Check it is valid for the pipeline to use a subset of the VertexInput // Check it is valid for the pipeline to use a subset of the VertexState
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
layout(location = 0) in vec4 a; layout(location = 0) in vec4 a;
@ -141,13 +141,13 @@ TEST_F(VertexInputTest, PipelineCompatibility) {
)"); )");
} }
// Test that a stride of 0 is valid // Test that a arrayStride of 0 is valid
TEST_F(VertexInputTest, StrideZero) { TEST_F(VertexStateTest, StrideZero) {
// Works ok without attributes // Works ok without attributes
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].stride = 0; state.cVertexBuffers[0].arrayStride = 0;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -165,14 +165,14 @@ TEST_F(VertexInputTest, StrideZero) {
)"); )");
} }
// Check validation that vertex attribute offset should be within vertex buffer stride, // Check validation that vertex attribute offset should be within vertex buffer arrayStride,
// if vertex buffer stride is not zero. // if vertex buffer arrayStride is not zero.
TEST_F(VertexInputTest, SetOffsetOutOfBounds) { TEST_F(VertexStateTest, SetOffsetOutOfBounds) {
// Control case, setting correct stride and offset // Control case, setting correct arrayStride and offset
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].stride = 2 * sizeof(float); state.cVertexBuffers[0].arrayStride = 2 * sizeof(float);
state.cBuffers[0].attributeCount = 2; state.cVertexBuffers[0].attributeCount = 2;
state.cAttributes[0].shaderLocation = 0; state.cAttributes[0].shaderLocation = 0;
state.cAttributes[1].shaderLocation = 1; state.cAttributes[1].shaderLocation = 1;
state.cAttributes[1].offset = sizeof(float); state.cAttributes[1].offset = sizeof(float);
@ -183,8 +183,8 @@ TEST_F(VertexInputTest, SetOffsetOutOfBounds) {
} }
)"); )");
// Test vertex attribute offset exceed vertex buffer stride range // Test vertex attribute offset exceed vertex buffer arrayStride range
state.cBuffers[0].stride = sizeof(float); state.cVertexBuffers[0].arrayStride = sizeof(float);
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
void main() { void main() {
@ -192,8 +192,8 @@ TEST_F(VertexInputTest, SetOffsetOutOfBounds) {
} }
)"); )");
// It's OK if stride is zero // It's OK if arrayStride is zero
state.cBuffers[0].stride = 0; state.cVertexBuffers[0].arrayStride = 0;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -203,13 +203,13 @@ TEST_F(VertexInputTest, SetOffsetOutOfBounds) {
} }
// Check out of bounds condition on total number of vertex buffers // Check out of bounds condition on total number of vertex buffers
TEST_F(VertexInputTest, SetVertexBuffersNumLimit) { TEST_F(VertexStateTest, SetVertexBuffersNumLimit) {
// Control case, setting max vertex buffer number // Control case, setting max vertex buffer number
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = kMaxVertexBuffers; state.vertexBufferCount = kMaxVertexBuffers;
for (uint32_t i = 0; i < kMaxVertexBuffers; ++i) { for (uint32_t i = 0; i < kMaxVertexBuffers; ++i) {
state.cBuffers[i].attributeCount = 1; state.cVertexBuffers[i].attributeCount = 1;
state.cBuffers[i].attributes = &state.cAttributes[i]; state.cVertexBuffers[i].attributes = &state.cAttributes[i];
state.cAttributes[i].shaderLocation = i; state.cAttributes[i].shaderLocation = i;
} }
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
@ -220,7 +220,7 @@ TEST_F(VertexInputTest, SetVertexBuffersNumLimit) {
)"); )");
// Test vertex buffer number exceed the limit // Test vertex buffer number exceed the limit
state.bufferCount = kMaxVertexBuffers + 1; state.vertexBufferCount = kMaxVertexBuffers + 1;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
void main() { void main() {
@ -230,11 +230,11 @@ TEST_F(VertexInputTest, SetVertexBuffersNumLimit) {
} }
// Check out of bounds condition on total number of vertex attributes // Check out of bounds condition on total number of vertex attributes
TEST_F(VertexInputTest, SetVertexAttributesNumLimit) { TEST_F(VertexStateTest, SetVertexAttributesNumLimit) {
// Control case, setting max vertex attribute number // Control case, setting max vertex attribute number
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 2; state.vertexBufferCount = 2;
state.cBuffers[0].attributeCount = kMaxVertexAttributes; state.cVertexBuffers[0].attributeCount = kMaxVertexAttributes;
for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) { for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) {
state.cAttributes[i].shaderLocation = i; state.cAttributes[i].shaderLocation = i;
} }
@ -246,8 +246,8 @@ TEST_F(VertexInputTest, SetVertexAttributesNumLimit) {
)"); )");
// Test vertex attribute number exceed the limit // Test vertex attribute number exceed the limit
state.cBuffers[1].attributeCount = 1; state.cVertexBuffers[1].attributeCount = 1;
state.cBuffers[1].attributes = &state.cAttributes[kMaxVertexAttributes - 1]; state.cVertexBuffers[1].attributes = &state.cAttributes[kMaxVertexAttributes - 1];
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
void main() { void main() {
@ -256,13 +256,13 @@ TEST_F(VertexInputTest, SetVertexAttributesNumLimit) {
)"); )");
} }
// Check out of bounds condition on input stride // Check out of bounds condition on input arrayStride
TEST_F(VertexInputTest, SetInputStrideOutOfBounds) { TEST_F(VertexStateTest, SetInputStrideOutOfBounds) {
// Control case, setting max input stride // Control case, setting max input arrayStride
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].stride = kMaxVertexBufferStride; state.cVertexBuffers[0].arrayStride = kMaxVertexBufferStride;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -270,8 +270,8 @@ TEST_F(VertexInputTest, SetInputStrideOutOfBounds) {
} }
)"); )");
// Test input stride OOB // Test input arrayStride OOB
state.cBuffers[0].stride = kMaxVertexBufferStride + 1; state.cVertexBuffers[0].arrayStride = kMaxVertexBufferStride + 1;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
void main() { void main() {
@ -280,13 +280,13 @@ TEST_F(VertexInputTest, SetInputStrideOutOfBounds) {
)"); )");
} }
// Check multiple of 4 bytes constraint on input stride // Check multiple of 4 bytes constraint on input arrayStride
TEST_F(VertexInputTest, SetInputStrideNotAligned) { TEST_F(VertexStateTest, SetInputStrideNotAligned) {
// Control case, setting input stride 4 bytes. // Control case, setting input arrayStride 4 bytes.
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].stride = 4; state.cVertexBuffers[0].arrayStride = 4;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -294,8 +294,8 @@ TEST_F(VertexInputTest, SetInputStrideNotAligned) {
} }
)"); )");
// Test input stride not multiple of 4 bytes // Test input arrayStride not multiple of 4 bytes
state.cBuffers[0].stride = 2; state.cVertexBuffers[0].arrayStride = 2;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
void main() { void main() {
@ -305,11 +305,11 @@ TEST_F(VertexInputTest, SetInputStrideNotAligned) {
} }
// Test that we cannot set an already set attribute // Test that we cannot set an already set attribute
TEST_F(VertexInputTest, AlreadySetAttribute) { TEST_F(VertexStateTest, AlreadySetAttribute) {
// Control case, setting attribute 0 // Control case, setting attribute 0
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
state.cAttributes[0].shaderLocation = 0; state.cAttributes[0].shaderLocation = 0;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
@ -319,7 +319,7 @@ TEST_F(VertexInputTest, AlreadySetAttribute) {
)"); )");
// Oh no, attribute 0 is set twice // Oh no, attribute 0 is set twice
state.cBuffers[0].attributeCount = 2; state.cVertexBuffers[0].attributeCount = 2;
state.cAttributes[0].shaderLocation = 0; state.cAttributes[0].shaderLocation = 0;
state.cAttributes[1].shaderLocation = 0; state.cAttributes[1].shaderLocation = 0;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
@ -330,12 +330,12 @@ TEST_F(VertexInputTest, AlreadySetAttribute) {
)"); )");
} }
// Test that a stride of 0 is valid // Test that a arrayStride of 0 is valid
TEST_F(VertexInputTest, SetSameShaderLocation) { TEST_F(VertexStateTest, SetSameShaderLocation) {
// Control case, setting different shader locations in two attributes // Control case, setting different shader locations in two attributes
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].attributeCount = 2; state.cVertexBuffers[0].attributeCount = 2;
state.cAttributes[0].shaderLocation = 0; state.cAttributes[0].shaderLocation = 0;
state.cAttributes[1].shaderLocation = 1; state.cAttributes[1].shaderLocation = 1;
state.cAttributes[1].offset = sizeof(float); state.cAttributes[1].offset = sizeof(float);
@ -356,11 +356,11 @@ TEST_F(VertexInputTest, SetSameShaderLocation) {
)"); )");
// Test same shader location in two attributes in different buffers // Test same shader location in two attributes in different buffers
state.bufferCount = 2; state.vertexBufferCount = 2;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
state.cAttributes[0].shaderLocation = 0; state.cAttributes[0].shaderLocation = 0;
state.cBuffers[1].attributeCount = 1; state.cVertexBuffers[1].attributeCount = 1;
state.cBuffers[1].attributes = &state.cAttributes[1]; state.cVertexBuffers[1].attributes = &state.cAttributes[1];
state.cAttributes[1].shaderLocation = 0; state.cAttributes[1].shaderLocation = 0;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
@ -371,11 +371,11 @@ TEST_F(VertexInputTest, SetSameShaderLocation) {
} }
// Check out of bounds condition on attribute shader location // Check out of bounds condition on attribute shader location
TEST_F(VertexInputTest, SetAttributeLocationOutOfBounds) { TEST_F(VertexStateTest, SetAttributeLocationOutOfBounds) {
// Control case, setting last attribute shader location // Control case, setting last attribute shader location
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
state.cAttributes[0].shaderLocation = kMaxVertexAttributes - 1; state.cAttributes[0].shaderLocation = kMaxVertexAttributes - 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
@ -395,11 +395,11 @@ TEST_F(VertexInputTest, SetAttributeLocationOutOfBounds) {
} }
// Check attribute offset out of bounds // Check attribute offset out of bounds
TEST_F(VertexInputTest, SetAttributeOffsetOutOfBounds) { TEST_F(VertexStateTest, SetAttributeOffsetOutOfBounds) {
// Control case, setting max attribute offset for FloatR32 vertex format // Control case, setting max attribute offset for FloatR32 vertex format
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
state.cAttributes[0].offset = kMaxVertexAttributeEnd - sizeof(wgpu::VertexFormat::Float); state.cAttributes[0].offset = kMaxVertexAttributeEnd - sizeof(wgpu::VertexFormat::Float);
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
@ -419,11 +419,11 @@ TEST_F(VertexInputTest, SetAttributeOffsetOutOfBounds) {
} }
// Check multiple of 4 bytes constraint on offset // Check multiple of 4 bytes constraint on offset
TEST_F(VertexInputTest, SetOffsetNotAligned) { TEST_F(VertexStateTest, SetOffsetNotAligned) {
// Control case, setting offset 4 bytes. // Control case, setting offset 4 bytes.
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
state.cAttributes[0].offset = 4; state.cAttributes[0].offset = 4;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
@ -443,10 +443,10 @@ TEST_F(VertexInputTest, SetOffsetNotAligned) {
} }
// Check attribute offset overflow // Check attribute offset overflow
TEST_F(VertexInputTest, SetAttributeOffsetOverflow) { TEST_F(VertexStateTest, SetAttributeOffsetOverflow) {
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
state.cAttributes[0].offset = std::numeric_limits<uint32_t>::max(); state.cAttributes[0].offset = std::numeric_limits<uint32_t>::max();
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
@ -457,11 +457,11 @@ TEST_F(VertexInputTest, SetAttributeOffsetOverflow) {
} }
// Check for some potential underflow in the vertex input validation // Check for some potential underflow in the vertex input validation
TEST_F(VertexInputTest, VertexFormatLargerThanNonZeroStride) { TEST_F(VertexStateTest, VertexFormatLargerThanNonZeroStride) {
utils::ComboVertexInputDescriptor state; utils::ComboVertexStateDescriptor state;
state.bufferCount = 1; state.vertexBufferCount = 1;
state.cBuffers[0].stride = 4; state.cVertexBuffers[0].arrayStride = 4;
state.cBuffers[0].attributeCount = 1; state.cVertexBuffers[0].attributeCount = 1;
state.cAttributes[0].format = wgpu::VertexFormat::Float4; state.cAttributes[0].format = wgpu::VertexFormat::Float4;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450

View File

@ -117,11 +117,11 @@ TEST_F(WireArgumentTests, CStringArgument) {
colorStateDescriptor.writeMask = WGPUColorWriteMask_All; colorStateDescriptor.writeMask = WGPUColorWriteMask_All;
// Create the input state // Create the input state
WGPUVertexInputDescriptor vertexInput; WGPUVertexStateDescriptor vertexState;
vertexInput.nextInChain = nullptr; vertexState.nextInChain = nullptr;
vertexInput.indexFormat = WGPUIndexFormat_Uint32; vertexState.indexFormat = WGPUIndexFormat_Uint32;
vertexInput.bufferCount = 0; vertexState.vertexBufferCount = 0;
vertexInput.buffers = nullptr; vertexState.vertexBuffers = nullptr;
// Create the rasterization state // Create the rasterization state
WGPURasterizationStateDescriptor rasterizationState; WGPURasterizationStateDescriptor rasterizationState;
@ -179,7 +179,7 @@ TEST_F(WireArgumentTests, CStringArgument) {
pipelineDescriptor.sampleMask = 0xFFFFFFFF; pipelineDescriptor.sampleMask = 0xFFFFFFFF;
pipelineDescriptor.alphaToCoverageEnabled = false; pipelineDescriptor.alphaToCoverageEnabled = false;
pipelineDescriptor.layout = layout; pipelineDescriptor.layout = layout;
pipelineDescriptor.vertexInput = &vertexInput; pipelineDescriptor.vertexState = &vertexState;
pipelineDescriptor.primitiveTopology = WGPUPrimitiveTopology_TriangleList; pipelineDescriptor.primitiveTopology = WGPUPrimitiveTopology_TriangleList;
pipelineDescriptor.rasterizationState = &rasterizationState; pipelineDescriptor.rasterizationState = &rasterizationState;
pipelineDescriptor.depthStencilState = &depthStencilState; pipelineDescriptor.depthStencilState = &depthStencilState;

View File

@ -90,11 +90,11 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
colorStateDescriptor.writeMask = WGPUColorWriteMask_All; colorStateDescriptor.writeMask = WGPUColorWriteMask_All;
// Create the input state // Create the input state
WGPUVertexInputDescriptor vertexInput; WGPUVertexStateDescriptor vertexState;
vertexInput.nextInChain = nullptr; vertexState.nextInChain = nullptr;
vertexInput.indexFormat = WGPUIndexFormat_Uint32; vertexState.indexFormat = WGPUIndexFormat_Uint32;
vertexInput.bufferCount = 0; vertexState.vertexBufferCount = 0;
vertexInput.buffers = nullptr; vertexState.vertexBuffers = nullptr;
// Create the rasterization state // Create the rasterization state
WGPURasterizationStateDescriptor rasterizationState; WGPURasterizationStateDescriptor rasterizationState;
@ -154,7 +154,7 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
pipelineDescriptor.sampleMask = 0xFFFFFFFF; pipelineDescriptor.sampleMask = 0xFFFFFFFF;
pipelineDescriptor.alphaToCoverageEnabled = false; pipelineDescriptor.alphaToCoverageEnabled = false;
pipelineDescriptor.layout = layout; pipelineDescriptor.layout = layout;
pipelineDescriptor.vertexInput = &vertexInput; pipelineDescriptor.vertexState = &vertexState;
pipelineDescriptor.primitiveTopology = WGPUPrimitiveTopology_TriangleList; pipelineDescriptor.primitiveTopology = WGPUPrimitiveTopology_TriangleList;
pipelineDescriptor.rasterizationState = &rasterizationState; pipelineDescriptor.rasterizationState = &rasterizationState;

View File

@ -18,11 +18,11 @@
namespace utils { namespace utils {
ComboVertexInputDescriptor::ComboVertexInputDescriptor() { ComboVertexStateDescriptor::ComboVertexStateDescriptor() {
wgpu::VertexInputDescriptor* descriptor = this; wgpu::VertexStateDescriptor* descriptor = this;
descriptor->indexFormat = wgpu::IndexFormat::Uint32; descriptor->indexFormat = wgpu::IndexFormat::Uint32;
descriptor->bufferCount = 0; descriptor->vertexBufferCount = 0;
// Fill the default values for vertexBuffers and vertexAttributes in buffers. // Fill the default values for vertexBuffers and vertexAttributes in buffers.
wgpu::VertexAttributeDescriptor vertexAttribute; wgpu::VertexAttributeDescriptor vertexAttribute;
@ -33,17 +33,18 @@ namespace utils {
cAttributes[i] = vertexAttribute; cAttributes[i] = vertexAttribute;
} }
for (uint32_t i = 0; i < kMaxVertexBuffers; ++i) { for (uint32_t i = 0; i < kMaxVertexBuffers; ++i) {
cBuffers[i].stride = 0; cVertexBuffers[i].arrayStride = 0;
cBuffers[i].stepMode = wgpu::InputStepMode::Vertex; cVertexBuffers[i].stepMode = wgpu::InputStepMode::Vertex;
cBuffers[i].attributeCount = 0; cVertexBuffers[i].attributeCount = 0;
cBuffers[i].attributes = nullptr; cVertexBuffers[i].attributes = nullptr;
} }
// cBuffers[i].attributes points to somewhere in cAttributes. cBuffers[0].attributes // cVertexBuffers[i].attributes points to somewhere in cAttributes.
// points to &cAttributes[0] by default. Assuming cBuffers[0] has two attributes, then // cVertexBuffers[0].attributes points to &cAttributes[0] by default. Assuming
// cBuffers[1].attributes should point to &cAttributes[2]. Likewise, if cBuffers[1] // cVertexBuffers[0] has two attributes, then cVertexBuffers[1].attributes should point to
// has 3 attributes, then cBuffers[2].attributes should point to &cAttributes[5]. // &cAttributes[2]. Likewise, if cVertexBuffers[1] has 3 attributes, then
cBuffers[0].attributes = &cAttributes[0]; // cVertexBuffers[2].attributes should point to &cAttributes[5].
descriptor->buffers = &cBuffers[0]; cVertexBuffers[0].attributes = &cAttributes[0];
descriptor->vertexBuffers = &cVertexBuffers[0];
} }
ComboRenderPipelineDescriptor::ComboRenderPipelineDescriptor(const wgpu::Device& device) { ComboRenderPipelineDescriptor::ComboRenderPipelineDescriptor(const wgpu::Device& device) {
@ -62,7 +63,7 @@ namespace utils {
} }
// Set defaults for the input state descriptors. // Set defaults for the input state descriptors.
descriptor->vertexInput = &cVertexInput; descriptor->vertexState = &cVertexState;
// Set defaults for the rasterization state descriptor. // Set defaults for the rasterization state descriptor.
{ {

View File

@ -23,11 +23,11 @@
namespace utils { namespace utils {
class ComboVertexInputDescriptor : public wgpu::VertexInputDescriptor { class ComboVertexStateDescriptor : public wgpu::VertexStateDescriptor {
public: public:
ComboVertexInputDescriptor(); ComboVertexStateDescriptor();
std::array<wgpu::VertexBufferDescriptor, kMaxVertexBuffers> cBuffers; std::array<wgpu::VertexBufferLayoutDescriptor, kMaxVertexBuffers> cVertexBuffers;
std::array<wgpu::VertexAttributeDescriptor, kMaxVertexAttributes> cAttributes; std::array<wgpu::VertexAttributeDescriptor, kMaxVertexAttributes> cAttributes;
}; };
@ -42,7 +42,7 @@ namespace utils {
wgpu::ProgrammableStageDescriptor cFragmentStage; wgpu::ProgrammableStageDescriptor cFragmentStage;
ComboVertexInputDescriptor cVertexInput; ComboVertexStateDescriptor cVertexState;
wgpu::RasterizationStateDescriptor cRasterizationState; wgpu::RasterizationStateDescriptor cRasterizationState;
std::array<wgpu::ColorStateDescriptor, kMaxColorAttachments> cColorStates; std::array<wgpu::ColorStateDescriptor, kMaxColorAttachments> cColorStates;
wgpu::DepthStencilStateDescriptor cDepthStencilState; wgpu::DepthStencilStateDescriptor cDepthStencilState;