Update VertexInput (InputState) to match spec - Part 1

This is only a renaming: change VertexInput to VertexBuffer, and
change InputState to VertexInput.

The next two patches will do as follows:
1) change the structure of vertex input descriptor related stuff.
2) change num to count.

BUG=dawn:80, dawn:107

Change-Id: Ie76aa653a527759a9c3b4a4792e3254689f053b8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/7420
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Yunchao He <yunchao.he@intel.com>
This commit is contained in:
Yunchao He 2019-05-22 22:46:32 +00:00 committed by Commit Bot service account
parent 820a04b9ce
commit eea2091068
35 changed files with 758 additions and 757 deletions

View File

@ -573,7 +573,6 @@ test("dawn_unittests") {
"src/tests/unittests/validation/DebugMarkerValidationTests.cpp", "src/tests/unittests/validation/DebugMarkerValidationTests.cpp",
"src/tests/unittests/validation/DynamicStateCommandValidationTests.cpp", "src/tests/unittests/validation/DynamicStateCommandValidationTests.cpp",
"src/tests/unittests/validation/FenceValidationTests.cpp", "src/tests/unittests/validation/FenceValidationTests.cpp",
"src/tests/unittests/validation/InputStateValidationTests.cpp",
"src/tests/unittests/validation/PushConstantsValidationTests.cpp", "src/tests/unittests/validation/PushConstantsValidationTests.cpp",
"src/tests/unittests/validation/QueueSubmitValidationTests.cpp", "src/tests/unittests/validation/QueueSubmitValidationTests.cpp",
"src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp", "src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp",
@ -587,6 +586,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/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",
@ -642,7 +642,6 @@ test("dawn_end2end_tests") {
"src/tests/end2end/DrawTests.cpp", "src/tests/end2end/DrawTests.cpp",
"src/tests/end2end/FenceTests.cpp", "src/tests/end2end/FenceTests.cpp",
"src/tests/end2end/IndexFormatTests.cpp", "src/tests/end2end/IndexFormatTests.cpp",
"src/tests/end2end/InputStateTests.cpp",
"src/tests/end2end/MultisampledRenderingTests.cpp", "src/tests/end2end/MultisampledRenderingTests.cpp",
"src/tests/end2end/NonzeroTextureCreationTests.cpp", "src/tests/end2end/NonzeroTextureCreationTests.cpp",
"src/tests/end2end/ObjectCachingTests.cpp", "src/tests/end2end/ObjectCachingTests.cpp",
@ -654,6 +653,7 @@ test("dawn_end2end_tests") {
"src/tests/end2end/ScissorTests.cpp", "src/tests/end2end/ScissorTests.cpp",
"src/tests/end2end/TextureViewTests.cpp", "src/tests/end2end/TextureViewTests.cpp",
"src/tests/end2end/VertexFormatTests.cpp", "src/tests/end2end/VertexFormatTests.cpp",
"src/tests/end2end/VertexInputTests.cpp",
"src/tests/end2end/ViewportOrientationTests.cpp", "src/tests/end2end/ViewportOrientationTests.cpp",
] ]

View File

@ -597,7 +597,7 @@
{"name": "format", "type": "vertex format"} {"name": "format", "type": "vertex format"}
] ]
}, },
"vertex input descriptor": { "vertex buffer descriptor": {
"category": "structure", "category": "structure",
"extensible": false, "extensible": false,
"members": [ "members": [
@ -606,15 +606,15 @@
{"name": "step mode", "type": "input step mode"} {"name": "step mode", "type": "input step mode"}
] ]
}, },
"input state descriptor": { "vertex input descriptor": {
"category": "structure", "category": "structure",
"extensible": true, "extensible": true,
"members": [ "members": [
{"name": "index format", "type": "index format"}, {"name": "index format", "type": "index format"},
{"name": "num attributes", "type": "uint32_t"}, {"name": "num attributes", "type": "uint32_t"},
{"name": "attributes", "type": "vertex attribute descriptor", "annotation": "const*", "length": "num attributes"}, {"name": "attributes", "type": "vertex attribute descriptor", "annotation": "const*", "length": "num attributes"},
{"name": "num inputs", "type": "uint32_t"}, {"name": "num buffers", "type": "uint32_t"},
{"name": "inputs", "type": "vertex input descriptor", "annotation": "const*", "length": "num inputs"} {"name": "buffers", "type": "vertex buffer descriptor", "annotation": "const*", "length": "num buffers"}
] ]
}, },
"input step mode": { "input step mode": {
@ -864,7 +864,7 @@
{"name": "layout", "type": "pipeline layout"}, {"name": "layout", "type": "pipeline layout"},
{"name": "vertex stage", "type": "pipeline stage descriptor", "annotation": "const*"}, {"name": "vertex stage", "type": "pipeline stage descriptor", "annotation": "const*"},
{"name": "fragment stage", "type": "pipeline stage descriptor", "annotation": "const*"}, {"name": "fragment stage", "type": "pipeline stage descriptor", "annotation": "const*"},
{"name": "input state", "type": "input state descriptor", "annotation": "const*"}, {"name": "vertex input", "type": "vertex input descriptor", "annotation": "const*"},
{"name": "primitive topology", "type": "primitive topology"}, {"name": "primitive topology", "type": "primitive topology"},
{"name": "rasterization state", "type": "rasterization state descriptor", "annotation": "const*"}, {"name": "rasterization state", "type": "rasterization state descriptor", "annotation": "const*"},
{"name": "sample count", "type": "uint32_t"}, {"name": "sample count", "type": "uint32_t"},

View File

@ -93,14 +93,14 @@ void init() {
pl.bindGroupLayouts = nullptr; pl.bindGroupLayouts = nullptr;
descriptor.layout = dawnDeviceCreatePipelineLayout(device, &pl); descriptor.layout = dawnDeviceCreatePipelineLayout(device, &pl);
DawnInputStateDescriptor inputState; DawnVertexInputDescriptor vertexInput;
inputState.nextInChain = nullptr; vertexInput.nextInChain = nullptr;
inputState.indexFormat = DAWN_INDEX_FORMAT_UINT32; vertexInput.indexFormat = DAWN_INDEX_FORMAT_UINT32;
inputState.numInputs = 0; vertexInput.numBuffers = 0;
inputState.inputs = nullptr; vertexInput.buffers = nullptr;
inputState.numAttributes = 0; vertexInput.numAttributes = 0;
inputState.attributes = nullptr; vertexInput.attributes = nullptr;
descriptor.inputState = &inputState; descriptor.vertexInput = &vertexInput;
DawnRasterizationStateDescriptor rasterizationState; DawnRasterizationStateDescriptor rasterizationState;
rasterizationState.nextInChain = nullptr; rasterizationState.nextInChain = nullptr;

View File

@ -120,20 +120,20 @@ void initRender() {
descriptor.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.cInputState.numAttributes = 3; descriptor.cVertexInput.numAttributes = 3;
descriptor.cInputState.cAttributes[0].offset = offsetof(Particle, pos); descriptor.cVertexInput.cAttributes[0].offset = offsetof(Particle, pos);
descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float2; descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float2;
descriptor.cInputState.cAttributes[1].shaderLocation = 1; descriptor.cVertexInput.cAttributes[1].shaderLocation = 1;
descriptor.cInputState.cAttributes[1].offset = offsetof(Particle, vel); descriptor.cVertexInput.cAttributes[1].offset = offsetof(Particle, vel);
descriptor.cInputState.cAttributes[1].format = dawn::VertexFormat::Float2; descriptor.cVertexInput.cAttributes[1].format = dawn::VertexFormat::Float2;
descriptor.cInputState.cAttributes[2].shaderLocation = 2; descriptor.cVertexInput.cAttributes[2].shaderLocation = 2;
descriptor.cInputState.cAttributes[2].inputSlot = 1; descriptor.cVertexInput.cAttributes[2].inputSlot = 1;
descriptor.cInputState.cAttributes[2].format = dawn::VertexFormat::Float2; descriptor.cVertexInput.cAttributes[2].format = dawn::VertexFormat::Float2;
descriptor.cInputState.numInputs = 2; descriptor.cVertexInput.numBuffers = 2;
descriptor.cInputState.cInputs[0].stride = sizeof(Particle); descriptor.cVertexInput.cBuffers[0].stride = sizeof(Particle);
descriptor.cInputState.cInputs[0].stepMode = dawn::InputStepMode::Instance; descriptor.cVertexInput.cBuffers[0].stepMode = dawn::InputStepMode::Instance;
descriptor.cInputState.cInputs[1].inputSlot = 1; descriptor.cVertexInput.cBuffers[1].inputSlot = 1;
descriptor.cInputState.cInputs[1].stride = sizeof(glm::vec2); descriptor.cVertexInput.cBuffers[1].stride = sizeof(glm::vec2);
descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.depthStencilState = &descriptor.cDepthStencilState;
descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat();

View File

@ -125,10 +125,10 @@ void init() {
descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl); descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl);
descriptor.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.cInputState.numAttributes = 1; descriptor.cVertexInput.numAttributes = 1;
descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4;
descriptor.cInputState.numInputs = 1; descriptor.cVertexInput.numBuffers = 1;
descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float);
descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.depthStencilState = &descriptor.cDepthStencilState;
descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat();

View File

@ -156,15 +156,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::ComboInputStateDescriptor inputState; utils::ComboVertexInputDescriptor vertexInput;
inputState.numAttributes = 2; vertexInput.numAttributes = 2;
inputState.cAttributes[0].format = dawn::VertexFormat::Float3; vertexInput.cAttributes[0].format = dawn::VertexFormat::Float3;
inputState.cAttributes[1].shaderLocation = 1; vertexInput.cAttributes[1].shaderLocation = 1;
inputState.cAttributes[1].offset = 3 * sizeof(float); vertexInput.cAttributes[1].offset = 3 * sizeof(float);
inputState.cAttributes[1].format = dawn::VertexFormat::Float3; vertexInput.cAttributes[1].format = dawn::VertexFormat::Float3;
inputState.numInputs = 1; vertexInput.numBuffers = 1;
inputState.cInputs[0].stride = 6 * sizeof(float); vertexInput.cBuffers[0].stride = 6 * sizeof(float);
auto bgl = utils::MakeBindGroupLayout( auto bgl = utils::MakeBindGroupLayout(
device, { device, {
@ -201,7 +201,7 @@ void init() {
descriptor.layout = pl; descriptor.layout = pl;
descriptor.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.inputState = &inputState; descriptor.vertexInput = &vertexInput;
descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.depthStencilState = &descriptor.cDepthStencilState;
descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat();
@ -214,7 +214,7 @@ void init() {
pDescriptor.layout = pl; pDescriptor.layout = pl;
pDescriptor.cVertexStage.module = vsModule; pDescriptor.cVertexStage.module = vsModule;
pDescriptor.cFragmentStage.module = fsModule; pDescriptor.cFragmentStage.module = fsModule;
pDescriptor.inputState = &inputState; pDescriptor.vertexInput = &vertexInput;
pDescriptor.depthStencilState = &pDescriptor.cDepthStencilState; pDescriptor.depthStencilState = &pDescriptor.cDepthStencilState;
pDescriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; pDescriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint;
pDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); pDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat();
@ -228,7 +228,7 @@ void init() {
rfDescriptor.layout = pl; rfDescriptor.layout = pl;
rfDescriptor.cVertexStage.module = vsModule; rfDescriptor.cVertexStage.module = vsModule;
rfDescriptor.cFragmentStage.module = fsReflectionModule; rfDescriptor.cFragmentStage.module = fsReflectionModule;
rfDescriptor.inputState = &inputState; rfDescriptor.vertexInput = &vertexInput;
rfDescriptor.depthStencilState = &rfDescriptor.cDepthStencilState; rfDescriptor.depthStencilState = &rfDescriptor.cDepthStencilState;
rfDescriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; rfDescriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint;
rfDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); rfDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat();

View File

@ -24,12 +24,13 @@ static constexpr uint32_t kMaxBindingsPerGroup = 16u;
static constexpr uint32_t kMaxVertexAttributes = 16u; static constexpr uint32_t kMaxVertexAttributes = 16u;
// Vulkan has a standalone limit named maxVertexInputAttributeOffset (2047u at least) for vertex // Vulkan has a standalone limit named maxVertexInputAttributeOffset (2047u at least) for vertex
// attribute offset. The limit might be meaningless because Vulkan has another limit named // attribute offset. The limit might be meaningless because Vulkan has another limit named
// maxVertexInputBindingStride (2048u at least). We use maxVertexAttributeEnd (2048u) here to verify // maxVertexInputBindingStride (2048u at least). We use maxVertexAttributeEnd (2048u) here to
// vertex attribute offset, which equals to maxOffset + smallest size of vertex format (char). We // verify vertex attribute offset, which equals to maxOffset + smallest size of vertex format
// may use maxVertexInputStride instead in future. // (char). We may use maxVertexInputBindingStride (maxVertexBufferStride below) instead to replace
// maxVertexAttributeEnd in future.
static constexpr uint32_t kMaxVertexAttributeEnd = 2048u; static constexpr uint32_t kMaxVertexAttributeEnd = 2048u;
static constexpr uint32_t kMaxVertexInputs = 16u; static constexpr uint32_t kMaxVertexBuffers = 16u;
static constexpr uint32_t kMaxVertexInputStride = 2048u; static constexpr uint32_t kMaxVertexBufferStride = 2048u;
static constexpr uint32_t kNumStages = 3; static constexpr uint32_t kNumStages = 3;
static constexpr uint32_t kMaxColorAttachments = 4u; static constexpr uint32_t kMaxColorAttachments = 4u;
static constexpr uint32_t kTextureRowPitchAlignment = 256u; static constexpr uint32_t kTextureRowPitchAlignment = 256u;

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<kMaxVertexInputs> mInputsSet; std::bitset<kMaxVertexBuffers> mInputsSet;
PipelineLayoutBase* mLastPipelineLayout = nullptr; PipelineLayoutBase* mLastPipelineLayout = nullptr;
RenderPipelineBase* mLastRenderPipeline = nullptr; RenderPipelineBase* mLastRenderPipeline = nullptr;

View File

@ -25,33 +25,33 @@ namespace dawn_native {
// Helper functions // Helper functions
namespace { namespace {
MaybeError ValidateVertexInputDescriptor(const VertexInputDescriptor* input, MaybeError ValidateVertexBufferDescriptor(const VertexBufferDescriptor* buffer,
std::bitset<kMaxVertexInputs>* inputsSetMask) { std::bitset<kMaxVertexBuffers>* inputsSetMask) {
DAWN_TRY(ValidateInputStepMode(input->stepMode)); DAWN_TRY(ValidateInputStepMode(buffer->stepMode));
if (input->inputSlot >= kMaxVertexInputs) { if (buffer->inputSlot >= kMaxVertexBuffers) {
return DAWN_VALIDATION_ERROR("Setting input out of bounds"); return DAWN_VALIDATION_ERROR("Setting vertex buffer out of bounds");
} }
if (input->stride > kMaxVertexInputStride) { if (buffer->stride > kMaxVertexBufferStride) {
return DAWN_VALIDATION_ERROR("Setting input stride out of bounds"); return DAWN_VALIDATION_ERROR("Setting input stride out of bounds");
} }
if ((*inputsSetMask)[input->inputSlot]) { if ((*inputsSetMask)[buffer->inputSlot]) {
return DAWN_VALIDATION_ERROR("Setting already set input"); return DAWN_VALIDATION_ERROR("Setting already set vertex buffer");
} }
inputsSetMask->set(input->inputSlot); inputsSetMask->set(buffer->inputSlot);
return {}; return {};
} }
MaybeError ValidateVertexAttributeDescriptor( MaybeError ValidateVertexAttributeDescriptor(
const VertexAttributeDescriptor* attribute, const VertexAttributeDescriptor* attribute,
const std::bitset<kMaxVertexInputs>* inputsSetMask, const std::bitset<kMaxVertexBuffers>* inputsSetMask,
std::bitset<kMaxVertexAttributes>* attributesSetMask) { std::bitset<kMaxVertexAttributes>* attributesSetMask) {
DAWN_TRY(ValidateVertexFormat(attribute->format)); DAWN_TRY(ValidateVertexFormat(attribute->format));
if (attribute->shaderLocation >= kMaxVertexAttributes) { if (attribute->shaderLocation >= kMaxVertexAttributes) {
return DAWN_VALIDATION_ERROR("Setting attribute out of bounds"); return DAWN_VALIDATION_ERROR("Setting attribute out of bounds");
} }
if (attribute->inputSlot >= kMaxVertexInputs) { if (attribute->inputSlot >= kMaxVertexBuffers) {
return DAWN_VALIDATION_ERROR("Binding slot out of bounds"); return DAWN_VALIDATION_ERROR("Binding slot out of bounds");
} }
ASSERT(kMaxVertexAttributeEnd >= VertexFormatSize(attribute->format)); ASSERT(kMaxVertexAttributeEnd >= VertexFormatSize(attribute->format));
@ -70,24 +70,24 @@ namespace dawn_native {
return {}; return {};
} }
MaybeError ValidateInputStateDescriptor( MaybeError ValidateVertexInputDescriptor(
const InputStateDescriptor* descriptor, const VertexInputDescriptor* descriptor,
std::bitset<kMaxVertexInputs>* inputsSetMask, std::bitset<kMaxVertexBuffers>* inputsSetMask,
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->numInputs > kMaxVertexInputs) { if (descriptor->numBuffers > kMaxVertexBuffers) {
return DAWN_VALIDATION_ERROR("Vertex Inputs number exceeds maximum"); return DAWN_VALIDATION_ERROR("Vertex Inputs number exceeds maximum");
} }
if (descriptor->numAttributes > kMaxVertexAttributes) { if (descriptor->numAttributes > kMaxVertexAttributes) {
return DAWN_VALIDATION_ERROR("Vertex Attributes number exceeds maximum"); return DAWN_VALIDATION_ERROR("Vertex Attributes number exceeds maximum");
} }
for (uint32_t i = 0; i < descriptor->numInputs; ++i) { for (uint32_t i = 0; i < descriptor->numBuffers; ++i) {
DAWN_TRY(ValidateVertexInputDescriptor(&descriptor->inputs[i], inputsSetMask)); DAWN_TRY(ValidateVertexBufferDescriptor(&descriptor->buffers[i], inputsSetMask));
} }
for (uint32_t i = 0; i < descriptor->numAttributes; ++i) { for (uint32_t i = 0; i < descriptor->numAttributes; ++i) {
@ -262,14 +262,14 @@ namespace dawn_native {
DAWN_TRY(device->ValidateObject(descriptor->layout)); DAWN_TRY(device->ValidateObject(descriptor->layout));
if (descriptor->inputState == nullptr) { if (descriptor->vertexInput == nullptr) {
return DAWN_VALIDATION_ERROR("Input state must not be null"); return DAWN_VALIDATION_ERROR("Input state must not be null");
} }
std::bitset<kMaxVertexInputs> inputsSetMask; std::bitset<kMaxVertexBuffers> inputsSetMask;
std::bitset<kMaxVertexAttributes> attributesSetMask; std::bitset<kMaxVertexAttributes> attributesSetMask;
DAWN_TRY(ValidateInputStateDescriptor(descriptor->inputState, &inputsSetMask, DAWN_TRY(ValidateVertexInputDescriptor(descriptor->vertexInput, &inputsSetMask,
&attributesSetMask)); &attributesSetMask));
DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology)); DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology));
DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->vertexStage, DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->vertexStage,
descriptor->layout, dawn::ShaderStage::Vertex)); descriptor->layout, dawn::ShaderStage::Vertex));
@ -334,7 +334,7 @@ namespace dawn_native {
: PipelineBase(device, : PipelineBase(device,
descriptor->layout, descriptor->layout,
dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment), dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment),
mInputState(*descriptor->inputState), mVertexInput(*descriptor->vertexInput),
mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr), mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr),
mPrimitiveTopology(descriptor->primitiveTopology), mPrimitiveTopology(descriptor->primitiveTopology),
mRasterizationState(*descriptor->rasterizationState), mRasterizationState(*descriptor->rasterizationState),
@ -345,16 +345,16 @@ namespace dawn_native {
mFragmentEntryPoint(descriptor->fragmentStage->entryPoint), mFragmentEntryPoint(descriptor->fragmentStage->entryPoint),
mIsBlueprint(blueprint) { mIsBlueprint(blueprint) {
uint32_t location = 0; uint32_t location = 0;
for (uint32_t i = 0; i < mInputState.numAttributes; ++i) { for (uint32_t i = 0; i < mVertexInput.numAttributes; ++i) {
location = mInputState.attributes[i].shaderLocation; location = mVertexInput.attributes[i].shaderLocation;
mAttributesSetMask.set(location); mAttributesSetMask.set(location);
mAttributeInfos[location] = mInputState.attributes[i]; mAttributeInfos[location] = mVertexInput.attributes[i];
} }
uint32_t slot = 0; uint32_t slot = 0;
for (uint32_t i = 0; i < mInputState.numInputs; ++i) { for (uint32_t i = 0; i < mVertexInput.numBuffers; ++i) {
slot = mInputState.inputs[i].inputSlot; slot = mVertexInput.buffers[i].inputSlot;
mInputsSetMask.set(slot); mInputsSetMask.set(slot);
mInputInfos[slot] = mInputState.inputs[i]; mInputInfos[slot] = mVertexInput.buffers[i];
} }
if (mHasDepthStencilAttachment) { if (mHasDepthStencilAttachment) {
@ -405,9 +405,9 @@ namespace dawn_native {
} }
} }
const InputStateDescriptor* RenderPipelineBase::GetInputStateDescriptor() const { const VertexInputDescriptor* RenderPipelineBase::GetVertexInputDescriptor() const {
ASSERT(!IsError()); ASSERT(!IsError());
return &mInputState; return &mVertexInput;
} }
const std::bitset<kMaxVertexAttributes>& RenderPipelineBase::GetAttributesSetMask() const { const std::bitset<kMaxVertexAttributes>& RenderPipelineBase::GetAttributesSetMask() const {
@ -421,12 +421,12 @@ namespace dawn_native {
return mAttributeInfos[location]; return mAttributeInfos[location];
} }
const std::bitset<kMaxVertexInputs>& RenderPipelineBase::GetInputsSetMask() const { const std::bitset<kMaxVertexBuffers>& RenderPipelineBase::GetInputsSetMask() const {
ASSERT(!IsError()); ASSERT(!IsError());
return mInputsSetMask; return mInputsSetMask;
} }
const VertexInputDescriptor& RenderPipelineBase::GetInput(uint32_t slot) const { const VertexBufferDescriptor& RenderPipelineBase::GetInput(uint32_t slot) const {
ASSERT(!IsError()); ASSERT(!IsError());
ASSERT(mInputsSetMask[slot]); ASSERT(mInputsSetMask[slot]);
return mInputInfos[slot]; return mInputInfos[slot];
@ -561,11 +561,11 @@ namespace dawn_native {
HashCombine(&hash, pipeline->mInputsSetMask); HashCombine(&hash, pipeline->mInputsSetMask);
for (uint32_t i : IterateBitSet(pipeline->mInputsSetMask)) { for (uint32_t i : IterateBitSet(pipeline->mInputsSetMask)) {
const VertexInputDescriptor& desc = pipeline->GetInput(i); const VertexBufferDescriptor& desc = pipeline->GetInput(i);
HashCombine(&hash, desc.inputSlot, desc.stride, desc.stepMode); HashCombine(&hash, desc.inputSlot, desc.stride, desc.stepMode);
} }
HashCombine(&hash, pipeline->mInputState.indexFormat); HashCombine(&hash, pipeline->mVertexInput.indexFormat);
// Hash rasterization state // Hash rasterization state
{ {
@ -660,15 +660,15 @@ namespace dawn_native {
} }
for (uint32_t i : IterateBitSet(a->mInputsSetMask)) { for (uint32_t i : IterateBitSet(a->mInputsSetMask)) {
const VertexInputDescriptor& descA = a->GetInput(i); const VertexBufferDescriptor& descA = a->GetInput(i);
const VertexInputDescriptor& descB = b->GetInput(i); const VertexBufferDescriptor& descB = b->GetInput(i);
if (descA.inputSlot != descB.inputSlot || descA.stride != descB.stride || if (descA.inputSlot != descB.inputSlot || descA.stride != descB.stride ||
descA.stepMode != descB.stepMode) { descA.stepMode != descB.stepMode) {
return false; return false;
} }
} }
if (a->mInputState.indexFormat != b->mInputState.indexFormat) { if (a->mVertexInput.indexFormat != b->mVertexInput.indexFormat) {
return false; return false;
} }

View File

@ -47,11 +47,11 @@ namespace dawn_native {
static RenderPipelineBase* MakeError(DeviceBase* device); static RenderPipelineBase* MakeError(DeviceBase* device);
const InputStateDescriptor* GetInputStateDescriptor() const; const VertexInputDescriptor* GetVertexInputDescriptor() const;
const std::bitset<kMaxVertexAttributes>& GetAttributesSetMask() const; const std::bitset<kMaxVertexAttributes>& GetAttributesSetMask() const;
const VertexAttributeDescriptor& GetAttribute(uint32_t location) const; const VertexAttributeDescriptor& GetAttribute(uint32_t location) const;
const std::bitset<kMaxVertexInputs>& GetInputsSetMask() const; const std::bitset<kMaxVertexBuffers>& GetInputsSetMask() const;
const VertexInputDescriptor& GetInput(uint32_t slot) const; const VertexBufferDescriptor& GetInput(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;
@ -69,7 +69,7 @@ namespace dawn_native {
// attachments in the render pass. This returns whether it is the case. // attachments in the render pass. This returns whether it is the case.
bool IsCompatibleWith(const BeginRenderPassCmd* renderPassCmd) const; bool IsCompatibleWith(const BeginRenderPassCmd* renderPassCmd) const;
std::bitset<kMaxVertexAttributes> GetAttributesUsingInput(uint32_t slot) const; std::bitset<kMaxVertexAttributes> GetAttributesUsingInput(uint32_t slot) const;
std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexInputs> attributesUsingInput; std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexBuffers> attributesUsingInput;
// Functors necessary for the unordered_set<RenderPipelineBase*>-based cache. // Functors necessary for the unordered_set<RenderPipelineBase*>-based cache.
struct HashFunc { struct HashFunc {
@ -83,11 +83,11 @@ namespace dawn_native {
RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag); RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
// Vertex input // Vertex input
InputStateDescriptor mInputState; VertexInputDescriptor mVertexInput;
std::bitset<kMaxVertexAttributes> mAttributesSetMask; std::bitset<kMaxVertexAttributes> mAttributesSetMask;
std::array<VertexAttributeDescriptor, kMaxVertexAttributes> mAttributeInfos; std::array<VertexAttributeDescriptor, kMaxVertexAttributes> mAttributeInfos;
std::bitset<kMaxVertexInputs> mInputsSetMask; std::bitset<kMaxVertexBuffers> mInputsSetMask;
std::array<VertexInputDescriptor, kMaxVertexInputs> mInputInfos; std::array<VertexBufferDescriptor, kMaxVertexBuffers> mInputInfos;
// Attachments // Attachments
bool mHasDepthStencilAttachment = false; bool mHasDepthStencilAttachment = false;

View File

@ -653,7 +653,7 @@ namespace dawn_native { namespace d3d12 {
commandList->IASetVertexBuffers(startSlot, count, commandList->IASetVertexBuffers(startSlot, count,
&vertexBuffersInfo->d3d12BufferViews[startSlot]); &vertexBuffersInfo->d3d12BufferViews[startSlot]);
vertexBuffersInfo->startSlot = kMaxVertexInputs; vertexBuffersInfo->startSlot = kMaxVertexBuffers;
vertexBuffersInfo->endSlot = 0; vertexBuffersInfo->endSlot = 0;
} }
@ -893,7 +893,7 @@ namespace dawn_native { namespace d3d12 {
// this will break if the pipeline is changed for one with a different index // this will break if the pipeline is changed for one with a different index
// format after SetIndexBuffer // format after SetIndexBuffer
bufferView.Format = bufferView.Format =
DXGIIndexFormat(lastPipeline->GetInputStateDescriptor()->indexFormat); DXGIIndexFormat(lastPipeline->GetVertexInputDescriptor()->indexFormat);
commandList->IASetIndexBuffer(&bufferView); commandList->IASetIndexBuffer(&bufferView);
} break; } break;

View File

@ -41,9 +41,9 @@ namespace dawn_native { namespace d3d12 {
// represent the union of the dirty ranges (the union may have non-dirty // represent the union of the dirty ranges (the union may have non-dirty
// data in the middle of the range). // data in the middle of the range).
const RenderPipeline* lastRenderPipeline = nullptr; const RenderPipeline* lastRenderPipeline = nullptr;
uint32_t startSlot = kMaxVertexInputs; uint32_t startSlot = kMaxVertexBuffers;
uint32_t endSlot = 0; uint32_t endSlot = 0;
std::array<D3D12_VERTEX_BUFFER_VIEW, kMaxVertexInputs> d3d12BufferViews = {}; std::array<D3D12_VERTEX_BUFFER_VIEW, kMaxVertexBuffers> d3d12BufferViews = {};
}; };
class CommandBuffer : public CommandBufferBase { class CommandBuffer : public CommandBufferBase {

View File

@ -409,7 +409,7 @@ namespace dawn_native { namespace d3d12 {
inputElementDescriptor.Format = VertexFormatType(attribute.format); inputElementDescriptor.Format = VertexFormatType(attribute.format);
inputElementDescriptor.InputSlot = attribute.inputSlot; inputElementDescriptor.InputSlot = attribute.inputSlot;
const VertexInputDescriptor& input = GetInput(attribute.inputSlot); const VertexBufferDescriptor& input = GetInput(attribute.inputSlot);
inputElementDescriptor.AlignedByteOffset = attribute.offset; inputElementDescriptor.AlignedByteOffset = attribute.offset;
inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode); inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode);

View File

@ -804,7 +804,7 @@ namespace dawn_native { namespace metal {
case Command::DrawIndexed: { case Command::DrawIndexed: {
DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>(); DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
size_t formatSize = size_t formatSize =
IndexFormatSize(lastPipeline->GetInputStateDescriptor()->indexFormat); IndexFormatSize(lastPipeline->GetVertexInputDescriptor()->indexFormat);
// The index and instance count must be non-zero, otherwise no-op // The index and instance count must be non-zero, otherwise no-op
if (draw->indexCount != 0 && draw->instanceCount != 0) { if (draw->indexCount != 0 && draw->instanceCount != 0) {
@ -926,8 +926,8 @@ namespace dawn_native { namespace metal {
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count); auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
auto offsets = mCommands.NextData<uint64_t>(cmd->count); auto offsets = mCommands.NextData<uint64_t>(cmd->count);
std::array<id<MTLBuffer>, kMaxVertexInputs> mtlBuffers; std::array<id<MTLBuffer>, kMaxVertexBuffers> mtlBuffers;
std::array<NSUInteger, kMaxVertexInputs> mtlOffsets; std::array<NSUInteger, kMaxVertexBuffers> mtlOffsets;
// Perhaps an "array of vertex buffers(+offsets?)" should be // Perhaps an "array of vertex buffers(+offsets?)" should be
// a Dawn API primitive to avoid reconstructing this array? // a Dawn API primitive to avoid reconstructing this array?

View File

@ -307,7 +307,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(GetInputStateDescriptor()->indexFormat)), mMtlIndexType(MTLIndexFormat(GetVertexInputDescriptor()->indexFormat)),
mMtlPrimitiveTopology(MTLPrimitiveTopology(GetPrimitiveTopology())), mMtlPrimitiveTopology(MTLPrimitiveTopology(GetPrimitiveTopology())),
mMtlFrontFace(MTLFrontFace(GetFrontFace())), mMtlFrontFace(MTLFrontFace(GetFrontFace())),
mMtlCullMode(ToMTLCullMode(GetCullMode())) { mMtlCullMode(ToMTLCullMode(GetCullMode())) {
@ -416,7 +416,7 @@ namespace dawn_native { namespace metal {
} }
for (uint32_t i : IterateBitSet(GetInputsSetMask())) { for (uint32_t i : IterateBitSet(GetInputsSetMask())) {
const VertexInputDescriptor& info = GetInput(i); const VertexBufferDescriptor& info = GetInput(i);
auto layoutDesc = [MTLVertexBufferLayoutDescriptor new]; auto layoutDesc = [MTLVertexBufferLayoutDescriptor new];
if (info.stride == 0) { if (info.stride == 0) {

View File

@ -210,8 +210,8 @@ 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 InputState. On the contrary in Dawn they are part of the global state. // corresponds to an VertexInput. On the contrary in Dawn they are part of the global state.
// This means that we have to re-apply these buffers on an InputState change. // This means that we have to re-apply these buffers on an VertexInput change.
class InputBufferTracker { class InputBufferTracker {
public: public:
void OnSetIndexBuffer(BufferBase* buffer) { void OnSetIndexBuffer(BufferBase* buffer) {
@ -230,7 +230,7 @@ namespace dawn_native { namespace opengl {
} }
// Use 64 bit masks and make sure there are no shift UB // Use 64 bit masks and make sure there are no shift UB
static_assert(kMaxVertexInputs <= 8 * sizeof(unsigned long long) - 1, ""); static_assert(kMaxVertexBuffers <= 8 * sizeof(unsigned long long) - 1, "");
mDirtyVertexBuffers |= ((1ull << count) - 1ull) << startSlot; mDirtyVertexBuffers |= ((1ull << count) - 1ull) << startSlot;
} }
@ -286,9 +286,9 @@ namespace dawn_native { namespace opengl {
bool mIndexBufferDirty = false; bool mIndexBufferDirty = false;
Buffer* mIndexBuffer = nullptr; Buffer* mIndexBuffer = nullptr;
std::bitset<kMaxVertexInputs> mDirtyVertexBuffers; std::bitset<kMaxVertexBuffers> mDirtyVertexBuffers;
std::array<Buffer*, kMaxVertexInputs> mVertexBuffers; std::array<Buffer*, kMaxVertexBuffers> mVertexBuffers;
std::array<uint64_t, kMaxVertexInputs> mVertexBufferOffsets; std::array<uint64_t, kMaxVertexBuffers> mVertexBufferOffsets;
RenderPipelineBase* mLastPipeline = nullptr; RenderPipelineBase* mLastPipeline = nullptr;
}; };
@ -772,7 +772,7 @@ namespace dawn_native { namespace opengl {
inputBuffers.Apply(); inputBuffers.Apply();
dawn::IndexFormat indexFormat = dawn::IndexFormat indexFormat =
lastPipeline->GetInputStateDescriptor()->indexFormat; lastPipeline->GetVertexInputDescriptor()->indexFormat;
size_t formatSize = IndexFormatSize(indexFormat); size_t formatSize = IndexFormatSize(indexFormat);
GLenum formatType = IndexFormatType(indexFormat); GLenum formatType = IndexFormatType(indexFormat);

View File

@ -182,7 +182,7 @@ namespace dawn_native { namespace opengl {
modules[dawn::ShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module); modules[dawn::ShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
PipelineGL::Initialize(ToBackend(GetLayout()), modules); PipelineGL::Initialize(ToBackend(GetLayout()), modules);
CreateVAOForInputState(descriptor->inputState); CreateVAOForVertexInput(descriptor->vertexInput);
} }
RenderPipeline::~RenderPipeline() { RenderPipeline::~RenderPipeline() {
@ -194,7 +194,7 @@ namespace dawn_native { namespace opengl {
return mGlPrimitiveTopology; return mGlPrimitiveTopology;
} }
void RenderPipeline::CreateVAOForInputState(const InputStateDescriptor* inputState) { void RenderPipeline::CreateVAOForVertexInput(const VertexInputDescriptor* vertexInput) {
glGenVertexArrays(1, &mVertexArrayObject); glGenVertexArrays(1, &mVertexArrayObject);
glBindVertexArray(mVertexArrayObject); glBindVertexArray(mVertexArrayObject);
for (uint32_t location : IterateBitSet(GetAttributesSetMask())) { for (uint32_t location : IterateBitSet(GetAttributesSetMask())) {

View File

@ -38,7 +38,7 @@ namespace dawn_native { namespace opengl {
void ApplyNow(PersistentPipelineState& persistentPipelineState); void ApplyNow(PersistentPipelineState& persistentPipelineState);
private: private:
void CreateVAOForInputState(const InputStateDescriptor* inputState); void CreateVAOForVertexInput(const VertexInputDescriptor* vertexInput);
// 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

@ -575,7 +575,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->GetInputStateDescriptor()->indexFormat); VulkanIndexType(lastPipeline->GetVertexInputDescriptor()->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;
@ -613,8 +613,8 @@ namespace dawn_native { namespace vulkan {
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count); auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
auto offsets = mCommands.NextData<uint64_t>(cmd->count); auto offsets = mCommands.NextData<uint64_t>(cmd->count);
std::array<VkBuffer, kMaxVertexInputs> vkBuffers; std::array<VkBuffer, kMaxVertexBuffers> vkBuffers;
std::array<VkDeviceSize, kMaxVertexInputs> vkOffsets; std::array<VkDeviceSize, kMaxVertexBuffers> vkOffsets;
for (uint32_t i = 0; i < cmd->count; ++i) { for (uint32_t i = 0; i < cmd->count; ++i) {
Buffer* buffer = ToBackend(buffers[i].Get()); Buffer* buffer = ToBackend(buffers[i].Get());

View File

@ -296,11 +296,11 @@ namespace dawn_native { namespace vulkan {
shaderStages[1].pName = descriptor->fragmentStage->entryPoint; shaderStages[1].pName = descriptor->fragmentStage->entryPoint;
} }
std::array<VkVertexInputBindingDescription, kMaxVertexInputs> mBindings; std::array<VkVertexInputBindingDescription, kMaxVertexBuffers> mBindings;
std::array<VkVertexInputAttributeDescription, kMaxVertexAttributes> mAttributes; std::array<VkVertexInputAttributeDescription, kMaxVertexAttributes> mAttributes;
const InputStateDescriptor* inputState = GetInputStateDescriptor(); const VertexInputDescriptor* vertexInput = GetVertexInputDescriptor();
VkPipelineVertexInputStateCreateInfo inputStateCreateInfo = VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo =
ComputeInputStateDesc(inputState, &mBindings, &mAttributes); ComputeVertexInputDesc(vertexInput, &mBindings, &mAttributes);
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;
@ -427,7 +427,7 @@ namespace dawn_native { namespace vulkan {
createInfo.flags = 0; createInfo.flags = 0;
createInfo.stageCount = 2; createInfo.stageCount = 2;
createInfo.pStages = shaderStages; createInfo.pStages = shaderStages;
createInfo.pVertexInputState = &inputStateCreateInfo; createInfo.pVertexInputState = &vertexInputCreateInfo;
createInfo.pInputAssemblyState = &inputAssembly; createInfo.pInputAssemblyState = &inputAssembly;
createInfo.pTessellationState = nullptr; createInfo.pTessellationState = nullptr;
createInfo.pViewportState = &viewport; createInfo.pViewportState = &viewport;
@ -448,9 +448,9 @@ namespace dawn_native { namespace vulkan {
} }
} }
VkPipelineVertexInputStateCreateInfo RenderPipeline::ComputeInputStateDesc( VkPipelineVertexInputStateCreateInfo RenderPipeline::ComputeVertexInputDesc(
const InputStateDescriptor* inputState, const VertexInputDescriptor* vertexInput,
std::array<VkVertexInputBindingDescription, kMaxVertexInputs>* mBindings, std::array<VkVertexInputBindingDescription, kMaxVertexBuffers>* mBindings,
std::array<VkVertexInputAttributeDescription, kMaxVertexAttributes>* mAttributes) { 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;

View File

@ -31,9 +31,9 @@ namespace dawn_native { namespace vulkan {
VkPipeline GetHandle() const; VkPipeline GetHandle() const;
private: private:
VkPipelineVertexInputStateCreateInfo ComputeInputStateDesc( VkPipelineVertexInputStateCreateInfo ComputeVertexInputDesc(
const InputStateDescriptor* inputState, const VertexInputDescriptor* vertexInput,
std::array<VkVertexInputBindingDescription, kMaxVertexInputs>* mBindings, std::array<VkVertexInputBindingDescription, kMaxVertexBuffers>* mBindings,
std::array<VkVertexInputAttributeDescription, kMaxVertexAttributes>* mAttributes); 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.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
descriptor.cInputState.numInputs = 1; descriptor.cVertexInput.numBuffers = 1;
descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float);
descriptor.cInputState.numAttributes = 1; descriptor.cVertexInput.numAttributes = 1;
descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cVertexInput.cAttributes[0].format = dawn::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.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
descriptor.cInputState.numInputs = 1; descriptor.cVertexInput.numBuffers = 1;
descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float);
descriptor.cInputState.numAttributes = 1; descriptor.cVertexInput.numAttributes = 1;
descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cVertexInput.cAttributes[0].format = dawn::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.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
descriptor.cInputState.numInputs = 1; descriptor.cVertexInput.numBuffers = 1;
descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float);
descriptor.cInputState.numAttributes = 1; descriptor.cVertexInput.numAttributes = 1;
descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4;
descriptor.cColorStates[0]->format = renderPass.colorFormat; descriptor.cColorStates[0]->format = renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor); pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -52,11 +52,11 @@ class IndexFormatTest : public DawnTest {
descriptor.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip; descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
descriptor.cInputState.indexFormat = format; descriptor.cVertexInput.indexFormat = format;
descriptor.cInputState.numInputs = 1; descriptor.cVertexInput.numBuffers = 1;
descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float);
descriptor.cInputState.numAttributes = 1; descriptor.cVertexInput.numAttributes = 1;
descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4;
descriptor.cColorStates[0]->format = renderPass.colorFormat; descriptor.cColorStates[0]->format = renderPass.colorFormat;
return device.CreateRenderPipeline(&descriptor); return device.CreateRenderPipeline(&descriptor);

View File

@ -1,494 +0,0 @@
// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tests/DawnTest.h"
#include "common/Assert.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
using dawn::InputStepMode;
using dawn::VertexFormat;
// Input state tests all work the same way: the test will render triangles in a grid up to 4x4. Each triangle
// is position in the grid such that X will correspond to the "triangle number" and the Y to the instance number.
// Each test will set up an input state and buffers, and the vertex shader 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
// "K * gl_InstanceID + componentIndex" for instance-indexed buffers.
constexpr static unsigned int kRTSize = 400;
constexpr static unsigned int kRTCellOffset = 50;
constexpr static unsigned int kRTCellSize = 100;
class InputStateTest : public DawnTest {
protected:
void SetUp() override {
DawnTest::SetUp();
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
}
bool ShouldComponentBeDefault(VertexFormat format, int component) {
EXPECT_TRUE(component >= 0 && component < 4);
switch (format) {
case VertexFormat::Float4:
case VertexFormat::UChar4Norm:
return component >= 4;
case VertexFormat::Float3:
return component >= 3;
case VertexFormat::Float2:
case VertexFormat::UChar2Norm:
return component >= 2;
case VertexFormat::Float:
return component >= 1;
default:
DAWN_UNREACHABLE();
}
}
struct ShaderTestSpec {
uint32_t location;
VertexFormat format;
InputStepMode step;
};
dawn::RenderPipeline MakeTestPipeline(const dawn::InputStateDescriptor& inputState,
int multiplier,
const std::vector<ShaderTestSpec>& testSpec) {
std::ostringstream vs;
vs << "#version 450\n";
// TODO(cwallez@chromium.org): this only handles float attributes, we should extend it to other types
// Adds line of the form
// layout(location=1) in vec4 input1;
for (const auto& input : testSpec) {
vs << "layout(location=" << input.location << ") in vec4 input" << input.location << ";\n";
}
vs << "layout(location = 0) out vec4 color;\n";
vs << "void main() {\n";
// Hard code the triangle in the shader so that we don't have to add a vertex input for it.
// Also this places the triangle in the grid based on its VertexID and InstanceID
vs << " const vec2 pos[3] = vec2[3](vec2(0.5f, 1.0f), vec2(0.0f, 0.0f), vec2(1.0f, 0.0f));\n";
vs << " vec2 offset = vec2(float(gl_VertexIndex / 3), float(gl_InstanceIndex));\n";
vs << " vec2 worldPos = pos[gl_VertexIndex % 3] + offset;\n";
vs << " gl_Position = vec4(worldPos / 2 - vec2(1.0f), 0.0f, 1.0f);\n";
// Perform the checks by successively ANDing a boolean
vs << " bool success = true;\n";
for (const auto& input : testSpec) {
for (int component = 0; component < 4; ++component) {
vs << " success = success && (input" << input.location << "[" << component << "] == ";
if (ShouldComponentBeDefault(input.format, component)) {
vs << (component == 3 ? "1.0f" : "0.0f");
} else {
if (input.step == InputStepMode::Vertex) {
vs << multiplier << " * gl_VertexIndex + " << component << ".0f";
} else {
vs << multiplier << " * gl_InstanceIndex + " << component << ".0f";
}
}
vs << ");\n";
}
}
// Choose the color
vs << " if (success) {\n";
vs << " color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n";
vs << " } else {\n";
vs << " color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
vs << " }\n;";
vs << "}\n";
dawn::ShaderModule vsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vs.str().c_str());
dawn::ShaderModule fsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"(
#version 450
layout(location = 0) in vec4 color;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = color;
})"
);
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.inputState = &inputState;
descriptor.cColorStates[0]->format = renderPass.colorFormat;
return device.CreateRenderPipeline(&descriptor);
}
struct InputSpec {
uint32_t slot;
uint64_t stride;
InputStepMode step;
};
struct AttributeSpec {
uint32_t location;
uint32_t slot;
uint64_t offset;
VertexFormat format;
};
utils::ComboInputStateDescriptor MakeInputState(
const std::vector<InputSpec>& inputs,
const std::vector<AttributeSpec>& attributes) {
utils::ComboInputStateDescriptor inputState;
uint32_t numInputs = 0;
for (const auto& input : inputs) {
inputState.cInputs[numInputs].inputSlot = input.slot;
inputState.cInputs[numInputs].stride = input.stride;
inputState.cInputs[numInputs].stepMode = input.step;
numInputs++;
}
uint32_t numAttributes = 0;
for (const auto& attribute : attributes) {
inputState.cAttributes[numAttributes].shaderLocation = attribute.location;
inputState.cAttributes[numAttributes].inputSlot = attribute.slot;
inputState.cAttributes[numAttributes].offset = attribute.offset;
inputState.cAttributes[numAttributes].format = attribute.format;
numAttributes++;
}
inputState.numInputs = numInputs;
inputState.numAttributes = numAttributes;
return inputState;
}
template<typename T>
dawn::Buffer MakeVertexBuffer(std::vector<T> data) {
return utils::CreateBufferFromData(device, data.data(), static_cast<uint32_t>(data.size() * sizeof(T)), dawn::BufferUsageBit::Vertex);
}
struct DrawVertexBuffer {
uint32_t location;
dawn::Buffer* buffer;
};
void DoTestDraw(const dawn::RenderPipeline& pipeline, unsigned int triangles, unsigned int instances, std::vector<DrawVertexBuffer> vertexBuffers) {
EXPECT_LE(triangles, 4u);
EXPECT_LE(instances, 4u);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
pass.SetPipeline(pipeline);
uint64_t zeroOffset = 0;
for (const auto& buffer : vertexBuffers) {
pass.SetVertexBuffers(buffer.location, 1, buffer.buffer, &zeroOffset);
}
pass.Draw(triangles * 3, instances, 0, 0);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
CheckResult(triangles, instances);
}
void CheckResult(unsigned int triangles, unsigned int instances) {
// Check that the center of each triangle is pure green, so that if a single vertex shader
// instance fails, linear interpolation makes the pixel check fail.
for (unsigned int triangle = 0; triangle < 4; triangle++) {
for (unsigned int instance = 0; instance < 4; instance++) {
unsigned int x = kRTCellOffset + kRTCellSize * triangle;
unsigned int y = kRTCellOffset + kRTCellSize * instance;
if (triangle < triangles && instance < instances) {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, x, y);
} else {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, x, y);
}
}
}
}
utils::BasicRenderPass renderPass;
};
// Test compilation and usage of the fixture :)
TEST_P(InputStateTest, Basic) {
utils::ComboInputStateDescriptor inputState = MakeInputState(
{{0, 4 * sizeof(float), InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 1, {
{0, VertexFormat::Float4, InputStepMode::Vertex}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3,
1, 2, 3, 4,
2, 3, 4, 5
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test a stride of 0 works
TEST_P(InputStateTest, ZeroStride) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
utils::ComboInputStateDescriptor inputState =
MakeInputState({{0, 0, InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 0, {
{0, VertexFormat::Float4, InputStepMode::Vertex}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3,
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test attributes defaults to (0, 0, 0, 1) if the input state doesn't have all components
TEST_P(InputStateTest, AttributeExpanding) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
// R32F case
{
utils::ComboInputStateDescriptor inputState =
MakeInputState({{0, 0, InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 0, {
{0, VertexFormat::Float, InputStepMode::Vertex}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// RG32F case
{
utils::ComboInputStateDescriptor inputState =
MakeInputState({{0, 0, InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float2}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 0, {
{0, VertexFormat::Float2, InputStepMode::Vertex}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// RGB32F case
{
utils::ComboInputStateDescriptor inputState =
MakeInputState({{0, 0, InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float3}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 0, {
{0, VertexFormat::Float3, InputStepMode::Vertex}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
}
// Test a stride larger than the attributes
TEST_P(InputStateTest, StrideLargerThanAttributes) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
utils::ComboInputStateDescriptor inputState = MakeInputState(
{{0, 8 * sizeof(float), InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 1, {
{0, VertexFormat::Float4, InputStepMode::Vertex}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 0, 0, 0,
1, 2, 3, 4, 0, 0, 0, 0,
2, 3, 4, 5, 0, 0, 0, 0,
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test two attributes at an offset, vertex version
TEST_P(InputStateTest, TwoAttributesAtAnOffsetVertex) {
utils::ComboInputStateDescriptor inputState = MakeInputState(
{{0, 8 * sizeof(float), InputStepMode::Vertex}},
{{0, 0, 0, VertexFormat::Float4}, {1, 0, 4 * sizeof(float), VertexFormat::Float4}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 1, {
{0, VertexFormat::Float4, InputStepMode::Vertex}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 1, 2, 3,
1, 2, 3, 4, 1, 2, 3, 4,
2, 3, 4, 5, 2, 3, 4, 5,
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test two attributes at an offset, instance version
TEST_P(InputStateTest, TwoAttributesAtAnOffsetInstance) {
utils::ComboInputStateDescriptor inputState = MakeInputState(
{{0, 8 * sizeof(float), InputStepMode::Instance}},
{{0, 0, 0, VertexFormat::Float4}, {1, 0, 4 * sizeof(float), VertexFormat::Float4}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 1, {
{0, VertexFormat::Float4, InputStepMode::Instance}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 1, 2, 3,
1, 2, 3, 4, 1, 2, 3, 4,
2, 3, 4, 5, 2, 3, 4, 5,
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test a pure-instance input state
TEST_P(InputStateTest, PureInstance) {
utils::ComboInputStateDescriptor inputState = MakeInputState(
{{0, 4 * sizeof(float), InputStepMode::Instance}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 1, {
{0, VertexFormat::Float4, InputStepMode::Instance}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3,
1, 2, 3, 4,
2, 3, 4, 5,
3, 4, 5, 6,
});
DoTestDraw(pipeline, 1, 4, {DrawVertexBuffer{0, &buffer0}});
}
// Test with mixed everything, vertex vs. instance, different stride and offsets
// different attribute types
TEST_P(InputStateTest, MixedEverything) {
utils::ComboInputStateDescriptor inputState = MakeInputState(
{
{0, 12 * sizeof(float), InputStepMode::Vertex},
{1, 10 * sizeof(float), InputStepMode::Instance},
},
{{0, 0, 0, VertexFormat::Float},
{1, 0, 6 * sizeof(float), VertexFormat::Float2},
{2, 1, 0, VertexFormat::Float3},
{3, 1, 5 * sizeof(float), VertexFormat::Float4}});
dawn::RenderPipeline pipeline = MakeTestPipeline(inputState, 1, {
{0, VertexFormat::Float, InputStepMode::Vertex},
{1, VertexFormat::Float2, InputStepMode::Vertex},
{2, VertexFormat::Float3, InputStepMode::Instance},
{3, VertexFormat::Float4, InputStepMode::Instance}
});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 0, 0, 1, 2, 3, 0, 0,
1, 2, 3, 4, 0, 0, 1, 2, 3, 4, 0, 0,
2, 3, 4, 5, 0, 0, 2, 3, 4, 5, 0, 0,
3, 4, 5, 6, 0, 0, 3, 4, 5, 6, 0, 0,
});
dawn::Buffer buffer1 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 0, 1, 2, 3, 0,
1, 2, 3, 4, 0, 1, 2, 3, 4, 0,
2, 3, 4, 5, 0, 2, 3, 4, 5, 0,
3, 4, 5, 6, 0, 3, 4, 5, 6, 0,
});
DoTestDraw(pipeline, 1, 1, {{0, &buffer0}, {1, &buffer1}});
}
// Test input state is unaffected by unused vertex slot
TEST_P(InputStateTest, UnusedVertexSlot) {
// Instance input state, using slot 1
utils::ComboInputStateDescriptor instanceInputState = MakeInputState(
{{1, 4 * sizeof(float), InputStepMode::Instance}}, {{0, 1, 0, VertexFormat::Float4}});
dawn::RenderPipeline instancePipeline = MakeTestPipeline(
instanceInputState, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
dawn::Buffer buffer = MakeVertexBuffer<float>({
0, 1, 2, 3,
1, 2, 3, 4,
2, 3, 4, 5,
3, 4, 5, 6,
});
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
uint64_t zeroOffset = 0;
pass.SetVertexBuffers(0, 1, &buffer, &zeroOffset);
pass.SetVertexBuffers(1, 1, &buffer, &zeroOffset);
pass.SetPipeline(instancePipeline);
pass.Draw(1 * 3, 4, 0, 0);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
CheckResult(1, 4);
}
// Test setting a different pipeline with a different input state.
// This was a problem with the D3D12 backend where SetVertexBuffers
// was getting the input from the last set pipeline, not the current.
// SetVertexBuffers should be reapplied when the input state changes.
TEST_P(InputStateTest, MultiplePipelinesMixedInputState) {
// Basic input state, using slot 0
utils::ComboInputStateDescriptor vertexInputState = MakeInputState(
{{0, 4 * sizeof(float), InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline vertexPipeline = MakeTestPipeline(
vertexInputState, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
// Instance input state, using slot 1
utils::ComboInputStateDescriptor instanceInputState = MakeInputState(
{{1, 4 * sizeof(float), InputStepMode::Instance}}, {{0, 1, 0, VertexFormat::Float4}});
dawn::RenderPipeline instancePipeline = MakeTestPipeline(
instanceInputState, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
dawn::Buffer buffer = MakeVertexBuffer<float>({
0, 1, 2, 3,
1, 2, 3, 4,
2, 3, 4, 5,
3, 4, 5, 6,
});
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
uint64_t zeroOffset = 0;
pass.SetVertexBuffers(0, 1, &buffer, &zeroOffset);
pass.SetVertexBuffers(1, 1, &buffer, &zeroOffset);
pass.SetPipeline(vertexPipeline);
pass.Draw(1 * 3, 1, 0, 0);
pass.SetPipeline(instancePipeline);
pass.Draw(1 * 3, 4, 0, 0);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
CheckResult(1, 4);
}
DAWN_INSTANTIATE_TEST(InputStateTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);
// TODO for the input state:
// - Add more vertex formats
// - Add checks that the stride is enough to contain all attributes
// - Add checks stride less than some limit
// - Add checks for alignement of vertex buffers and attributes if needed
// - Check for attribute narrowing
// - Check that the input state and the pipeline vertex input types match

View File

@ -185,10 +185,10 @@ class PrimitiveTopologyTest : public DawnTest {
descriptor.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = primitiveTopology; descriptor.primitiveTopology = primitiveTopology;
descriptor.cInputState.numInputs = 1; descriptor.cVertexInput.numBuffers = 1;
descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float);
descriptor.cInputState.numAttributes = 1; descriptor.cVertexInput.numAttributes = 1;
descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4;
descriptor.cColorStates[0]->format = renderPass.colorFormat; descriptor.cColorStates[0]->format = renderPass.colorFormat;
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor); dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

View File

@ -362,10 +362,10 @@ class VertexFormatTest : public DawnTest {
utils::ComboRenderPipelineDescriptor descriptor(device); utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.cInputState.numInputs = 1; descriptor.cVertexInput.numBuffers = 1;
descriptor.cInputState.cInputs[0].stride = strideBytes; descriptor.cVertexInput.cBuffers[0].stride = strideBytes;
descriptor.cInputState.numAttributes = 1; descriptor.cVertexInput.numAttributes = 1;
descriptor.cInputState.cAttributes[0].format = format; descriptor.cVertexInput.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

@ -0,0 +1,494 @@
// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tests/DawnTest.h"
#include "common/Assert.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
using dawn::InputStepMode;
using dawn::VertexFormat;
// Input state tests all work the same way: the test will render triangles in a grid up to 4x4. Each triangle
// is position in the grid such that X will correspond to the "triangle number" and the Y to the instance number.
// Each test will set up an input state and buffers, and the vertex shader 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
// "K * gl_InstanceID + componentIndex" for instance-indexed buffers.
constexpr static unsigned int kRTSize = 400;
constexpr static unsigned int kRTCellOffset = 50;
constexpr static unsigned int kRTCellSize = 100;
class VertexInputTest : public DawnTest {
protected:
void SetUp() override {
DawnTest::SetUp();
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
}
bool ShouldComponentBeDefault(VertexFormat format, int component) {
EXPECT_TRUE(component >= 0 && component < 4);
switch (format) {
case VertexFormat::Float4:
case VertexFormat::UChar4Norm:
return component >= 4;
case VertexFormat::Float3:
return component >= 3;
case VertexFormat::Float2:
case VertexFormat::UChar2Norm:
return component >= 2;
case VertexFormat::Float:
return component >= 1;
default:
DAWN_UNREACHABLE();
}
}
struct ShaderTestSpec {
uint32_t location;
VertexFormat format;
InputStepMode step;
};
dawn::RenderPipeline MakeTestPipeline(const dawn::VertexInputDescriptor& vertexInput,
int multiplier,
const std::vector<ShaderTestSpec>& testSpec) {
std::ostringstream vs;
vs << "#version 450\n";
// TODO(cwallez@chromium.org): this only handles float attributes, we should extend it to
// other types Adds line of the form
// layout(location=1) in vec4 input1;
for (const auto& input : testSpec) {
vs << "layout(location=" << input.location << ") in vec4 input" << input.location
<< ";\n";
}
vs << "layout(location = 0) out vec4 color;\n";
vs << "void main() {\n";
// Hard code the triangle in the shader so that we don't have to add a vertex input for it.
// Also this places the triangle in the grid based on its VertexID and InstanceID
vs << " const vec2 pos[3] = vec2[3](vec2(0.5f, 1.0f), vec2(0.0f, 0.0f), vec2(1.0f, "
"0.0f));\n";
vs << " vec2 offset = vec2(float(gl_VertexIndex / 3), float(gl_InstanceIndex));\n";
vs << " vec2 worldPos = pos[gl_VertexIndex % 3] + offset;\n";
vs << " gl_Position = vec4(worldPos / 2 - vec2(1.0f), 0.0f, 1.0f);\n";
// Perform the checks by successively ANDing a boolean
vs << " bool success = true;\n";
for (const auto& input : testSpec) {
for (int component = 0; component < 4; ++component) {
vs << " success = success && (input" << input.location << "[" << component
<< "] == ";
if (ShouldComponentBeDefault(input.format, component)) {
vs << (component == 3 ? "1.0f" : "0.0f");
} else {
if (input.step == InputStepMode::Vertex) {
vs << multiplier << " * gl_VertexIndex + " << component << ".0f";
} else {
vs << multiplier << " * gl_InstanceIndex + " << component << ".0f";
}
}
vs << ");\n";
}
}
// Choose the color
vs << " if (success) {\n";
vs << " color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n";
vs << " } else {\n";
vs << " color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
vs << " }\n;";
vs << "}\n";
dawn::ShaderModule vsModule =
utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vs.str().c_str());
dawn::ShaderModule fsModule =
utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"(
#version 450
layout(location = 0) in vec4 color;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = color;
})");
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.vertexInput = &vertexInput;
descriptor.cColorStates[0]->format = renderPass.colorFormat;
return device.CreateRenderPipeline(&descriptor);
}
struct VertexBufferSpec {
uint32_t slot;
uint64_t stride;
InputStepMode step;
};
struct AttributeSpec {
uint32_t location;
uint32_t slot;
uint64_t offset;
VertexFormat format;
};
utils::ComboVertexInputDescriptor MakeVertexInput(
const std::vector<VertexBufferSpec>& buffers,
const std::vector<AttributeSpec>& attributes) {
utils::ComboVertexInputDescriptor vertexInput;
uint32_t numBuffers = 0;
for (const auto& buffer : buffers) {
vertexInput.cBuffers[numBuffers].inputSlot = buffer.slot;
vertexInput.cBuffers[numBuffers].stride = buffer.stride;
vertexInput.cBuffers[numBuffers].stepMode = buffer.step;
numBuffers++;
}
uint32_t numAttributes = 0;
for (const auto& attribute : attributes) {
vertexInput.cAttributes[numAttributes].shaderLocation = attribute.location;
vertexInput.cAttributes[numAttributes].inputSlot = attribute.slot;
vertexInput.cAttributes[numAttributes].offset = attribute.offset;
vertexInput.cAttributes[numAttributes].format = attribute.format;
numAttributes++;
}
vertexInput.numBuffers = numBuffers;
vertexInput.numAttributes = numAttributes;
return vertexInput;
}
template <typename T>
dawn::Buffer MakeVertexBuffer(std::vector<T> data) {
return utils::CreateBufferFromData(device, data.data(),
static_cast<uint32_t>(data.size() * sizeof(T)),
dawn::BufferUsageBit::Vertex);
}
struct DrawVertexBuffer {
uint32_t location;
dawn::Buffer* buffer;
};
void DoTestDraw(const dawn::RenderPipeline& pipeline,
unsigned int triangles,
unsigned int instances,
std::vector<DrawVertexBuffer> vertexBuffers) {
EXPECT_LE(triangles, 4u);
EXPECT_LE(instances, 4u);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
pass.SetPipeline(pipeline);
uint64_t zeroOffset = 0;
for (const auto& buffer : vertexBuffers) {
pass.SetVertexBuffers(buffer.location, 1, buffer.buffer, &zeroOffset);
}
pass.Draw(triangles * 3, instances, 0, 0);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
CheckResult(triangles, instances);
}
void CheckResult(unsigned int triangles, unsigned int instances) {
// Check that the center of each triangle is pure green, so that if a single vertex shader
// instance fails, linear interpolation makes the pixel check fail.
for (unsigned int triangle = 0; triangle < 4; triangle++) {
for (unsigned int instance = 0; instance < 4; instance++) {
unsigned int x = kRTCellOffset + kRTCellSize * triangle;
unsigned int y = kRTCellOffset + kRTCellSize * instance;
if (triangle < triangles && instance < instances) {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, x, y);
} else {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, x, y);
}
}
}
}
utils::BasicRenderPass renderPass;
};
// Test compilation and usage of the fixture :)
TEST_P(VertexInputTest, Basic) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput(
{{0, 4 * sizeof(float), InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3,
1, 2, 3, 4,
2, 3, 4, 5
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test a stride of 0 works
TEST_P(VertexInputTest, ZeroStride) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
utils::ComboVertexInputDescriptor vertexInput =
MakeVertexInput({{0, 0, InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 0, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3,
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test attributes defaults to (0, 0, 0, 1) if the input state doesn't have all components
TEST_P(VertexInputTest, AttributeExpanding) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
// R32F case
{
utils::ComboVertexInputDescriptor vertexInput =
MakeVertexInput({{0, 0, InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 0, {{0, VertexFormat::Float, InputStepMode::Vertex}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// RG32F case
{
utils::ComboVertexInputDescriptor vertexInput =
MakeVertexInput({{0, 0, InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float2}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 0, {{0, VertexFormat::Float2, InputStepMode::Vertex}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// RGB32F case
{
utils::ComboVertexInputDescriptor vertexInput =
MakeVertexInput({{0, 0, InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float3}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 0, {{0, VertexFormat::Float3, InputStepMode::Vertex}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
}
// Test a stride larger than the attributes
TEST_P(VertexInputTest, StrideLargerThanAttributes) {
// This test was failing only on AMD but the OpenGL backend doesn't gather PCI info yet.
DAWN_SKIP_TEST_IF(IsLinux() && IsOpenGL());
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput(
{{0, 8 * sizeof(float), InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 0, 0, 0,
1, 2, 3, 4, 0, 0, 0, 0,
2, 3, 4, 5, 0, 0, 0, 0,
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test two attributes at an offset, vertex version
TEST_P(VertexInputTest, TwoAttributesAtAnOffsetVertex) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput(
{{0, 8 * sizeof(float), InputStepMode::Vertex}},
{{0, 0, 0, VertexFormat::Float4}, {1, 0, 4 * sizeof(float), VertexFormat::Float4}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 1, 2, 3,
1, 2, 3, 4, 1, 2, 3, 4,
2, 3, 4, 5, 2, 3, 4, 5,
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test two attributes at an offset, instance version
TEST_P(VertexInputTest, TwoAttributesAtAnOffsetInstance) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput(
{{0, 8 * sizeof(float), InputStepMode::Instance}},
{{0, 0, 0, VertexFormat::Float4}, {1, 0, 4 * sizeof(float), VertexFormat::Float4}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 1, 2, 3,
1, 2, 3, 4, 1, 2, 3, 4,
2, 3, 4, 5, 2, 3, 4, 5,
});
DoTestDraw(pipeline, 1, 1, {DrawVertexBuffer{0, &buffer0}});
}
// Test a pure-instance input state
TEST_P(VertexInputTest, PureInstance) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput(
{{0, 4 * sizeof(float), InputStepMode::Instance}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3,
1, 2, 3, 4,
2, 3, 4, 5,
3, 4, 5, 6,
});
DoTestDraw(pipeline, 1, 4, {DrawVertexBuffer{0, &buffer0}});
}
// Test with mixed everything, vertex vs. instance, different stride and offsets
// different attribute types
TEST_P(VertexInputTest, MixedEverything) {
utils::ComboVertexInputDescriptor vertexInput = MakeVertexInput(
{
{0, 12 * sizeof(float), InputStepMode::Vertex},
{1, 10 * sizeof(float), InputStepMode::Instance},
},
{{0, 0, 0, VertexFormat::Float},
{1, 0, 6 * sizeof(float), VertexFormat::Float2},
{2, 1, 0, VertexFormat::Float3},
{3, 1, 5 * sizeof(float), VertexFormat::Float4}});
dawn::RenderPipeline pipeline =
MakeTestPipeline(vertexInput, 1,
{{0, VertexFormat::Float, InputStepMode::Vertex},
{1, VertexFormat::Float2, InputStepMode::Vertex},
{2, VertexFormat::Float3, InputStepMode::Instance},
{3, VertexFormat::Float4, InputStepMode::Instance}});
dawn::Buffer buffer0 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 0, 0, 1, 2, 3, 0, 0,
1, 2, 3, 4, 0, 0, 1, 2, 3, 4, 0, 0,
2, 3, 4, 5, 0, 0, 2, 3, 4, 5, 0, 0,
3, 4, 5, 6, 0, 0, 3, 4, 5, 6, 0, 0,
});
dawn::Buffer buffer1 = MakeVertexBuffer<float>({
0, 1, 2, 3, 0, 0, 1, 2, 3, 0,
1, 2, 3, 4, 0, 1, 2, 3, 4, 0,
2, 3, 4, 5, 0, 2, 3, 4, 5, 0,
3, 4, 5, 6, 0, 3, 4, 5, 6, 0,
});
DoTestDraw(pipeline, 1, 1, {{0, &buffer0}, {1, &buffer1}});
}
// Test input state is unaffected by unused vertex slot
TEST_P(VertexInputTest, UnusedVertexSlot) {
// Instance input state, using slot 1
utils::ComboVertexInputDescriptor instanceVertexInput = MakeVertexInput(
{{1, 4 * sizeof(float), InputStepMode::Instance}}, {{0, 1, 0, VertexFormat::Float4}});
dawn::RenderPipeline instancePipeline = MakeTestPipeline(
instanceVertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
dawn::Buffer buffer = MakeVertexBuffer<float>({
0, 1, 2, 3,
1, 2, 3, 4,
2, 3, 4, 5,
3, 4, 5, 6,
});
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
uint64_t zeroOffset = 0;
pass.SetVertexBuffers(0, 1, &buffer, &zeroOffset);
pass.SetVertexBuffers(1, 1, &buffer, &zeroOffset);
pass.SetPipeline(instancePipeline);
pass.Draw(1 * 3, 4, 0, 0);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
CheckResult(1, 4);
}
// Test setting a different pipeline with a different input state.
// This was a problem with the D3D12 backend where SetVertexBuffers
// was getting the input from the last set pipeline, not the current.
// SetVertexBuffers should be reapplied when the input state changes.
TEST_P(VertexInputTest, MultiplePipelinesMixedVertexInput) {
// Basic input state, using slot 0
utils::ComboVertexInputDescriptor vertexVertexInput = MakeVertexInput(
{{0, 4 * sizeof(float), InputStepMode::Vertex}}, {{0, 0, 0, VertexFormat::Float4}});
dawn::RenderPipeline vertexPipeline =
MakeTestPipeline(vertexVertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Vertex}});
// Instance input state, using slot 1
utils::ComboVertexInputDescriptor instanceVertexInput = MakeVertexInput(
{{1, 4 * sizeof(float), InputStepMode::Instance}}, {{0, 1, 0, VertexFormat::Float4}});
dawn::RenderPipeline instancePipeline = MakeTestPipeline(
instanceVertexInput, 1, {{0, VertexFormat::Float4, InputStepMode::Instance}});
dawn::Buffer buffer = MakeVertexBuffer<float>({
0, 1, 2, 3,
1, 2, 3, 4,
2, 3, 4, 5,
3, 4, 5, 6,
});
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
uint64_t zeroOffset = 0;
pass.SetVertexBuffers(0, 1, &buffer, &zeroOffset);
pass.SetVertexBuffers(1, 1, &buffer, &zeroOffset);
pass.SetPipeline(vertexPipeline);
pass.Draw(1 * 3, 1, 0, 0);
pass.SetPipeline(instancePipeline);
pass.Draw(1 * 3, 4, 0, 0);
pass.EndPass();
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
CheckResult(1, 4);
}
DAWN_INSTANTIATE_TEST(VertexInputTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);
// TODO for the input state:
// - Add more vertex formats
// - Add checks that the stride is enough to contain all attributes
// - Add checks stride less than some limit
// - Add checks for alignement of vertex buffers and attributes if needed
// - Check for attribute narrowing
// - Check that the input state and the pipeline vertex input types match

View File

@ -45,18 +45,18 @@ class VertexBufferValidationTest : public ValidationTest {
return buffers; return buffers;
} }
dawn::ShaderModule MakeVertexShader(unsigned int numInputs) { dawn::ShaderModule MakeVertexShader(unsigned int numBuffers) {
std::ostringstream vs; std::ostringstream vs;
vs << "#version 450\n"; vs << "#version 450\n";
for (unsigned int i = 0; i < numInputs; ++i) { for (unsigned int i = 0; i < numBuffers; ++i) {
vs << "layout(location = " << i << ") in vec3 a_position" << i << ";\n"; vs << "layout(location = " << i << ") in vec3 a_position" << i << ";\n";
} }
vs << "void main() {\n"; vs << "void main() {\n";
vs << "gl_Position = vec4("; vs << "gl_Position = vec4(";
for (unsigned int i = 0; i < numInputs; ++i) { for (unsigned int i = 0; i < numBuffers; ++i) {
vs << "a_position" << i; vs << "a_position" << i;
if (i != numInputs - 1) { if (i != numBuffers - 1) {
vs << " + "; vs << " + ";
} }
} }
@ -68,19 +68,19 @@ class VertexBufferValidationTest : public ValidationTest {
} }
dawn::RenderPipeline MakeRenderPipeline(const dawn::ShaderModule& vsModule, dawn::RenderPipeline MakeRenderPipeline(const dawn::ShaderModule& vsModule,
unsigned int numInputs) { unsigned int numBuffers) {
utils::ComboRenderPipelineDescriptor descriptor(device); utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
for (unsigned int i = 0; i < numInputs; ++i) { for (unsigned int i = 0; i < numBuffers; ++i) {
descriptor.cInputState.cAttributes[i].shaderLocation = i; descriptor.cVertexInput.cAttributes[i].shaderLocation = i;
descriptor.cInputState.cAttributes[i].inputSlot = i; descriptor.cVertexInput.cAttributes[i].inputSlot = i;
descriptor.cInputState.cAttributes[i].format = dawn::VertexFormat::Float3; descriptor.cVertexInput.cAttributes[i].format = dawn::VertexFormat::Float3;
descriptor.cInputState.cInputs[i].inputSlot = i; descriptor.cVertexInput.cBuffers[i].inputSlot = i;
} }
descriptor.cInputState.numInputs = numInputs; descriptor.cVertexInput.numBuffers = numBuffers;
descriptor.cInputState.numAttributes = numInputs; descriptor.cVertexInput.numAttributes = numBuffers;
return device.CreateRenderPipeline(&descriptor); return device.CreateRenderPipeline(&descriptor);
} }
@ -88,7 +88,7 @@ class VertexBufferValidationTest : public ValidationTest {
dawn::ShaderModule fsModule; dawn::ShaderModule fsModule;
}; };
TEST_F(VertexBufferValidationTest, VertexInputsInheritedBetweenPipelines) { TEST_F(VertexBufferValidationTest, VertexBuffersInheritedBetweenPipelines) {
DummyRenderPass renderPass(device); DummyRenderPass renderPass(device);
auto vsModule2 = MakeVertexShader(2); auto vsModule2 = MakeVertexShader(2);
auto vsModule1 = MakeVertexShader(1); auto vsModule1 = MakeVertexShader(1);
@ -123,7 +123,7 @@ TEST_F(VertexBufferValidationTest, VertexInputsInheritedBetweenPipelines) {
encoder.Finish(); encoder.Finish();
} }
TEST_F(VertexBufferValidationTest, VertexInputsNotInheritedBetweenRendePasses) { TEST_F(VertexBufferValidationTest, VertexBuffersNotInheritedBetweenRendePasses) {
DummyRenderPass renderPass(device); DummyRenderPass renderPass(device);
auto vsModule2 = MakeVertexShader(2); auto vsModule2 = MakeVertexShader(2);
auto vsModule1 = MakeVertexShader(1); auto vsModule1 = MakeVertexShader(1);

View File

@ -17,15 +17,15 @@
#include "utils/ComboRenderPipelineDescriptor.h" #include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h" #include "utils/DawnHelpers.h"
class InputStateTest : public ValidationTest { class VertexInputTest : public ValidationTest {
protected: protected:
void CreatePipeline(bool success, void CreatePipeline(bool success,
const utils::ComboInputStateDescriptor& state, const utils::ComboVertexInputDescriptor& state,
std::string vertexSource) { std::string vertexSource) {
dawn::ShaderModule vsModule = dawn::ShaderModule vsModule =
utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vertexSource.c_str()); utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vertexSource.c_str());
dawn::ShaderModule fsModule = dawn::ShaderModule fsModule =
utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"( utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"(
#version 450 #version 450
layout(location = 0) out vec4 fragColor; layout(location = 0) out vec4 fragColor;
void main() { void main() {
@ -33,23 +33,23 @@ class InputStateTest : public ValidationTest {
} }
)"); )");
utils::ComboRenderPipelineDescriptor descriptor(device); utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule; descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.inputState = &state; descriptor.vertexInput = &state;
descriptor.cColorStates[0]->format = dawn::TextureFormat::R8G8B8A8Unorm; descriptor.cColorStates[0]->format = dawn::TextureFormat::R8G8B8A8Unorm;
if (!success) { if (!success) {
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor)); ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
} else { } else {
device.CreateRenderPipeline(&descriptor); device.CreateRenderPipeline(&descriptor);
} }
} }
}; };
// Check an empty input state is valid // Check an empty input state is valid
TEST_F(InputStateTest, EmptyIsOk) { TEST_F(VertexInputTest, EmptyIsOk) {
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -58,11 +58,11 @@ TEST_F(InputStateTest, EmptyIsOk) {
)"); )");
} }
// Check validation that pipeline vertex inputs are backed by attributes in the input state // Check validation that pipeline vertex buffers are backed by attributes in the vertex input
TEST_F(InputStateTest, PipelineCompatibility) { TEST_F(VertexInputTest, PipelineCompatibility) {
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.cInputs[0].stride = 2 * sizeof(float); state.cBuffers[0].stride = 2 * sizeof(float);
state.numAttributes = 2; state.numAttributes = 2;
state.cAttributes[1].shaderLocation = 1; state.cAttributes[1].shaderLocation = 1;
state.cAttributes[1].offset = sizeof(float); state.cAttributes[1].offset = sizeof(float);
@ -77,7 +77,7 @@ TEST_F(InputStateTest, PipelineCompatibility) {
} }
)"); )");
// Check it is valid for the pipeline to use a subset of the InputState // Check it is valid for the pipeline to use a subset of the VertexInput
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
layout(location = 0) in vec4 a; layout(location = 0) in vec4 a;
@ -97,10 +97,10 @@ TEST_F(InputStateTest, PipelineCompatibility) {
} }
// Test that a stride of 0 is valid // Test that a stride of 0 is valid
TEST_F(InputStateTest, StrideZero) { TEST_F(VertexInputTest, StrideZero) {
// Works ok without attributes // Works ok without attributes
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -120,10 +120,10 @@ TEST_F(InputStateTest, StrideZero) {
} }
// Test that we cannot set an already set input // Test that we cannot set an already set input
TEST_F(InputStateTest, AlreadySetInput) { TEST_F(VertexInputTest, AlreadySetInput) {
// Control case // Control case
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -132,7 +132,7 @@ TEST_F(InputStateTest, AlreadySetInput) {
)"); )");
// Oh no, input 0 is set twice // Oh no, input 0 is set twice
state.numInputs = 2; state.numBuffers = 2;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
void main() { void main() {
@ -142,11 +142,11 @@ TEST_F(InputStateTest, AlreadySetInput) {
} }
// Check out of bounds condition on input slot // Check out of bounds condition on input slot
TEST_F(InputStateTest, SetInputSlotOutOfBounds) { TEST_F(VertexInputTest, SetInputSlotOutOfBounds) {
// Control case, setting last input slot // Control case, setting last input slot
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.cInputs[0].inputSlot = kMaxVertexInputs - 1; state.cBuffers[0].inputSlot = kMaxVertexBuffers - 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -155,7 +155,7 @@ TEST_F(InputStateTest, SetInputSlotOutOfBounds) {
)"); )");
// Test input slot OOB // Test input slot OOB
state.cInputs[0].inputSlot = kMaxVertexInputs; state.cBuffers[0].inputSlot = kMaxVertexBuffers;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
void main() { void main() {
@ -165,11 +165,11 @@ TEST_F(InputStateTest, SetInputSlotOutOfBounds) {
} }
// Check out of bounds condition on input stride // Check out of bounds condition on input stride
TEST_F(InputStateTest, SetInputStrideOutOfBounds) { TEST_F(VertexInputTest, SetInputStrideOutOfBounds) {
// Control case, setting max input stride // Control case, setting max input stride
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.cInputs[0].stride = kMaxVertexInputStride; state.cBuffers[0].stride = kMaxVertexBufferStride;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
void main() { void main() {
@ -178,7 +178,7 @@ TEST_F(InputStateTest, SetInputStrideOutOfBounds) {
)"); )");
// Test input stride OOB // Test input stride OOB
state.cInputs[0].stride = kMaxVertexInputStride + 1; state.cBuffers[0].stride = kMaxVertexBufferStride + 1;
CreatePipeline(false, state, R"( CreatePipeline(false, state, R"(
#version 450 #version 450
void main() { void main() {
@ -188,10 +188,10 @@ TEST_F(InputStateTest, SetInputStrideOutOfBounds) {
} }
// Test that we cannot set an already set attribute // Test that we cannot set an already set attribute
TEST_F(InputStateTest, AlreadySetAttribute) { TEST_F(VertexInputTest, AlreadySetAttribute) {
// Control case, setting last attribute // Control case, setting last attribute
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.numAttributes = 1; state.numAttributes = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
@ -211,10 +211,10 @@ TEST_F(InputStateTest, AlreadySetAttribute) {
} }
// Check out of bounds condition on attribute shader location // Check out of bounds condition on attribute shader location
TEST_F(InputStateTest, SetAttributeLocationOutOfBounds) { TEST_F(VertexInputTest, SetAttributeLocationOutOfBounds) {
// Control case, setting last attribute shader location // Control case, setting last attribute shader location
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.numAttributes = 1; state.numAttributes = 1;
state.cAttributes[0].shaderLocation = kMaxVertexAttributes - 1; state.cAttributes[0].shaderLocation = kMaxVertexAttributes - 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
@ -235,10 +235,10 @@ TEST_F(InputStateTest, SetAttributeLocationOutOfBounds) {
} }
// Check attribute offset out of bounds // Check attribute offset out of bounds
TEST_F(InputStateTest, SetAttributeOffsetOutOfBounds) { TEST_F(VertexInputTest, SetAttributeOffsetOutOfBounds) {
// Control case, setting max attribute offset for FloatR32 vertex format // Control case, setting max attribute offset for FloatR32 vertex format
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.numAttributes = 1; state.numAttributes = 1;
state.cAttributes[0].offset = kMaxVertexAttributeEnd - sizeof(dawn::VertexFormat::Float); state.cAttributes[0].offset = kMaxVertexAttributeEnd - sizeof(dawn::VertexFormat::Float);
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
@ -259,9 +259,9 @@ TEST_F(InputStateTest, SetAttributeOffsetOutOfBounds) {
} }
// Check attribute offset overflow // Check attribute offset overflow
TEST_F(InputStateTest, SetAttributeOffsetOverflow) { TEST_F(VertexInputTest, SetAttributeOffsetOverflow) {
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.numAttributes = 1; state.numAttributes = 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"(
@ -273,10 +273,10 @@ TEST_F(InputStateTest, SetAttributeOffsetOverflow) {
} }
// Check that all attributes must be backed by an input // Check that all attributes must be backed by an input
TEST_F(InputStateTest, RequireInputForAttribute) { TEST_F(VertexInputTest, RequireInputForAttribute) {
// Control case // Control case
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.numAttributes = 1; state.numAttributes = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450
@ -296,10 +296,10 @@ TEST_F(InputStateTest, RequireInputForAttribute) {
} }
// Check OOB checks for an attribute's input // Check OOB checks for an attribute's input
TEST_F(InputStateTest, SetAttributeOOBCheckForInputs) { TEST_F(VertexInputTest, SetAttributeOOBCheckForInputs) {
// Control case // Control case
utils::ComboInputStateDescriptor state; utils::ComboVertexInputDescriptor state;
state.numInputs = 1; state.numBuffers = 1;
state.numAttributes = 1; state.numAttributes = 1;
CreatePipeline(true, state, R"( CreatePipeline(true, state, R"(
#version 450 #version 450

View File

@ -97,13 +97,13 @@ TEST_F(WireArgumentTests, CStringArgument) {
colorStateDescriptor.writeMask = DAWN_COLOR_WRITE_MASK_ALL; colorStateDescriptor.writeMask = DAWN_COLOR_WRITE_MASK_ALL;
// Create the input state // Create the input state
DawnInputStateDescriptor inputState; DawnVertexInputDescriptor vertexInput;
inputState.nextInChain = nullptr; vertexInput.nextInChain = nullptr;
inputState.indexFormat = DAWN_INDEX_FORMAT_UINT32; vertexInput.indexFormat = DAWN_INDEX_FORMAT_UINT32;
inputState.numInputs = 0; vertexInput.numBuffers = 0;
inputState.inputs = nullptr; vertexInput.buffers = nullptr;
inputState.numAttributes = 0; vertexInput.numAttributes = 0;
inputState.attributes = nullptr; vertexInput.attributes = nullptr;
// Create the rasterization state // Create the rasterization state
DawnRasterizationStateDescriptor rasterizationState; DawnRasterizationStateDescriptor rasterizationState;
@ -162,7 +162,7 @@ TEST_F(WireArgumentTests, CStringArgument) {
pipelineDescriptor.sampleCount = 1; pipelineDescriptor.sampleCount = 1;
pipelineDescriptor.layout = layout; pipelineDescriptor.layout = layout;
pipelineDescriptor.inputState = &inputState; pipelineDescriptor.vertexInput = &vertexInput;
pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
pipelineDescriptor.rasterizationState = &rasterizationState; pipelineDescriptor.rasterizationState = &rasterizationState;
pipelineDescriptor.depthStencilState = &depthStencilState; pipelineDescriptor.depthStencilState = &depthStencilState;

View File

@ -87,13 +87,13 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
colorStateDescriptor.writeMask = DAWN_COLOR_WRITE_MASK_ALL; colorStateDescriptor.writeMask = DAWN_COLOR_WRITE_MASK_ALL;
// Create the input state // Create the input state
DawnInputStateDescriptor inputState; DawnVertexInputDescriptor vertexInput;
inputState.nextInChain = nullptr; vertexInput.nextInChain = nullptr;
inputState.indexFormat = DAWN_INDEX_FORMAT_UINT32; vertexInput.indexFormat = DAWN_INDEX_FORMAT_UINT32;
inputState.numInputs = 0; vertexInput.numBuffers = 0;
inputState.inputs = nullptr; vertexInput.buffers = nullptr;
inputState.numAttributes = 0; vertexInput.numAttributes = 0;
inputState.attributes = nullptr; vertexInput.attributes = nullptr;
// Create the rasterization state // Create the rasterization state
DawnRasterizationStateDescriptor rasterizationState; DawnRasterizationStateDescriptor rasterizationState;
@ -152,7 +152,7 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
pipelineDescriptor.sampleCount = 1; pipelineDescriptor.sampleCount = 1;
pipelineDescriptor.layout = layout; pipelineDescriptor.layout = layout;
pipelineDescriptor.inputState = &inputState; pipelineDescriptor.vertexInput = &vertexInput;
pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
pipelineDescriptor.rasterizationState = &rasterizationState; pipelineDescriptor.rasterizationState = &rasterizationState;

View File

@ -18,21 +18,21 @@
namespace utils { namespace utils {
ComboInputStateDescriptor::ComboInputStateDescriptor() { ComboVertexInputDescriptor::ComboVertexInputDescriptor() {
dawn::InputStateDescriptor* descriptor = this; dawn::VertexInputDescriptor* descriptor = this;
descriptor->indexFormat = dawn::IndexFormat::Uint32; descriptor->indexFormat = dawn::IndexFormat::Uint32;
// Fill the default values for vertexInput. // Fill the default values for vertexBuffer.
descriptor->numInputs = 0; descriptor->numBuffers = 0;
dawn::VertexInputDescriptor vertexInput; dawn::VertexBufferDescriptor vertexBuffer;
vertexInput.inputSlot = 0; vertexBuffer.inputSlot = 0;
vertexInput.stride = 0; vertexBuffer.stride = 0;
vertexInput.stepMode = dawn::InputStepMode::Vertex; vertexBuffer.stepMode = dawn::InputStepMode::Vertex;
for (uint32_t i = 0; i < kMaxVertexInputs; ++i) { for (uint32_t i = 0; i < kMaxVertexBuffers; ++i) {
cInputs[i] = vertexInput; cBuffers[i] = vertexBuffer;
} }
descriptor->inputs = &cInputs[0]; descriptor->buffers = &cBuffers[0];
// Fill the default values for vertexAttribute. // Fill the default values for vertexAttribute.
descriptor->numAttributes = 0; descriptor->numAttributes = 0;
@ -66,7 +66,7 @@ namespace utils {
} }
// Set defaults for the input state descriptors. // Set defaults for the input state descriptors.
descriptor->inputState = &cInputState; descriptor->vertexInput = &cVertexInput;
// 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 ComboInputStateDescriptor : public dawn::InputStateDescriptor { class ComboVertexInputDescriptor : public dawn::VertexInputDescriptor {
public: public:
ComboInputStateDescriptor(); ComboVertexInputDescriptor();
std::array<dawn::VertexInputDescriptor, kMaxVertexInputs> cInputs; std::array<dawn::VertexBufferDescriptor, kMaxVertexBuffers> cBuffers;
std::array<dawn::VertexAttributeDescriptor, kMaxVertexAttributes> cAttributes; std::array<dawn::VertexAttributeDescriptor, kMaxVertexAttributes> cAttributes;
}; };
@ -38,7 +38,7 @@ namespace utils {
dawn::PipelineStageDescriptor cVertexStage; dawn::PipelineStageDescriptor cVertexStage;
dawn::PipelineStageDescriptor cFragmentStage; dawn::PipelineStageDescriptor cFragmentStage;
ComboInputStateDescriptor cInputState; ComboVertexInputDescriptor cVertexInput;
dawn::RasterizationStateDescriptor cRasterizationState; dawn::RasterizationStateDescriptor cRasterizationState;
std::array<dawn::ColorStateDescriptor*, kMaxColorAttachments> cColorStates; std::array<dawn::ColorStateDescriptor*, kMaxColorAttachments> cColorStates;
dawn::DepthStencilStateDescriptor cDepthStencilState; dawn::DepthStencilStateDescriptor cDepthStencilState;