diff --git a/BUILD.gn b/BUILD.gn index 0110ac5fb6..2ae8d92b21 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -573,7 +573,6 @@ test("dawn_unittests") { "src/tests/unittests/validation/DebugMarkerValidationTests.cpp", "src/tests/unittests/validation/DynamicStateCommandValidationTests.cpp", "src/tests/unittests/validation/FenceValidationTests.cpp", - "src/tests/unittests/validation/InputStateValidationTests.cpp", "src/tests/unittests/validation/PushConstantsValidationTests.cpp", "src/tests/unittests/validation/QueueSubmitValidationTests.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.h", "src/tests/unittests/validation/VertexBufferValidationTests.cpp", + "src/tests/unittests/validation/VertexInputValidationTests.cpp", "src/tests/unittests/wire/WireArgumentTests.cpp", "src/tests/unittests/wire/WireBasicTests.cpp", "src/tests/unittests/wire/WireBufferMappingTests.cpp", @@ -642,7 +642,6 @@ test("dawn_end2end_tests") { "src/tests/end2end/DrawTests.cpp", "src/tests/end2end/FenceTests.cpp", "src/tests/end2end/IndexFormatTests.cpp", - "src/tests/end2end/InputStateTests.cpp", "src/tests/end2end/MultisampledRenderingTests.cpp", "src/tests/end2end/NonzeroTextureCreationTests.cpp", "src/tests/end2end/ObjectCachingTests.cpp", @@ -654,6 +653,7 @@ test("dawn_end2end_tests") { "src/tests/end2end/ScissorTests.cpp", "src/tests/end2end/TextureViewTests.cpp", "src/tests/end2end/VertexFormatTests.cpp", + "src/tests/end2end/VertexInputTests.cpp", "src/tests/end2end/ViewportOrientationTests.cpp", ] diff --git a/dawn.json b/dawn.json index b7a18ce19c..45bed41acf 100644 --- a/dawn.json +++ b/dawn.json @@ -597,7 +597,7 @@ {"name": "format", "type": "vertex format"} ] }, - "vertex input descriptor": { + "vertex buffer descriptor": { "category": "structure", "extensible": false, "members": [ @@ -606,15 +606,15 @@ {"name": "step mode", "type": "input step mode"} ] }, - "input state descriptor": { + "vertex input descriptor": { "category": "structure", "extensible": true, "members": [ {"name": "index format", "type": "index format"}, {"name": "num attributes", "type": "uint32_t"}, {"name": "attributes", "type": "vertex attribute descriptor", "annotation": "const*", "length": "num attributes"}, - {"name": "num inputs", "type": "uint32_t"}, - {"name": "inputs", "type": "vertex input descriptor", "annotation": "const*", "length": "num inputs"} + {"name": "num buffers", "type": "uint32_t"}, + {"name": "buffers", "type": "vertex buffer descriptor", "annotation": "const*", "length": "num buffers"} ] }, "input step mode": { @@ -864,7 +864,7 @@ {"name": "layout", "type": "pipeline layout"}, {"name": "vertex 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": "rasterization state", "type": "rasterization state descriptor", "annotation": "const*"}, {"name": "sample count", "type": "uint32_t"}, diff --git a/examples/CHelloTriangle.cpp b/examples/CHelloTriangle.cpp index 5a5d8bba69..d48725335e 100644 --- a/examples/CHelloTriangle.cpp +++ b/examples/CHelloTriangle.cpp @@ -93,14 +93,14 @@ void init() { pl.bindGroupLayouts = nullptr; descriptor.layout = dawnDeviceCreatePipelineLayout(device, &pl); - DawnInputStateDescriptor inputState; - inputState.nextInChain = nullptr; - inputState.indexFormat = DAWN_INDEX_FORMAT_UINT32; - inputState.numInputs = 0; - inputState.inputs = nullptr; - inputState.numAttributes = 0; - inputState.attributes = nullptr; - descriptor.inputState = &inputState; + DawnVertexInputDescriptor vertexInput; + vertexInput.nextInChain = nullptr; + vertexInput.indexFormat = DAWN_INDEX_FORMAT_UINT32; + vertexInput.numBuffers = 0; + vertexInput.buffers = nullptr; + vertexInput.numAttributes = 0; + vertexInput.attributes = nullptr; + descriptor.vertexInput = &vertexInput; DawnRasterizationStateDescriptor rasterizationState; rasterizationState.nextInChain = nullptr; diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp index ae4234ce7a..beeffa4b2f 100644 --- a/examples/ComputeBoids.cpp +++ b/examples/ComputeBoids.cpp @@ -120,20 +120,20 @@ void initRender() { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; - descriptor.cInputState.numAttributes = 3; - descriptor.cInputState.cAttributes[0].offset = offsetof(Particle, pos); - descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float2; - descriptor.cInputState.cAttributes[1].shaderLocation = 1; - descriptor.cInputState.cAttributes[1].offset = offsetof(Particle, vel); - descriptor.cInputState.cAttributes[1].format = dawn::VertexFormat::Float2; - descriptor.cInputState.cAttributes[2].shaderLocation = 2; - descriptor.cInputState.cAttributes[2].inputSlot = 1; - descriptor.cInputState.cAttributes[2].format = dawn::VertexFormat::Float2; - descriptor.cInputState.numInputs = 2; - descriptor.cInputState.cInputs[0].stride = sizeof(Particle); - descriptor.cInputState.cInputs[0].stepMode = dawn::InputStepMode::Instance; - descriptor.cInputState.cInputs[1].inputSlot = 1; - descriptor.cInputState.cInputs[1].stride = sizeof(glm::vec2); + descriptor.cVertexInput.numAttributes = 3; + descriptor.cVertexInput.cAttributes[0].offset = offsetof(Particle, pos); + descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float2; + descriptor.cVertexInput.cAttributes[1].shaderLocation = 1; + descriptor.cVertexInput.cAttributes[1].offset = offsetof(Particle, vel); + descriptor.cVertexInput.cAttributes[1].format = dawn::VertexFormat::Float2; + descriptor.cVertexInput.cAttributes[2].shaderLocation = 2; + descriptor.cVertexInput.cAttributes[2].inputSlot = 1; + descriptor.cVertexInput.cAttributes[2].format = dawn::VertexFormat::Float2; + descriptor.cVertexInput.numBuffers = 2; + descriptor.cVertexInput.cBuffers[0].stride = sizeof(Particle); + descriptor.cVertexInput.cBuffers[0].stepMode = dawn::InputStepMode::Instance; + descriptor.cVertexInput.cBuffers[1].inputSlot = 1; + descriptor.cVertexInput.cBuffers[1].stride = sizeof(glm::vec2); descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); diff --git a/examples/CppHelloTriangle.cpp b/examples/CppHelloTriangle.cpp index b560d7959e..a23b3e4edb 100644 --- a/examples/CppHelloTriangle.cpp +++ b/examples/CppHelloTriangle.cpp @@ -125,10 +125,10 @@ void init() { descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl); descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; - descriptor.cInputState.numAttributes = 1; - descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; - descriptor.cInputState.numInputs = 1; - descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); + descriptor.cVertexInput.numAttributes = 1; + descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4; + descriptor.cVertexInput.numBuffers = 1; + descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); diff --git a/examples/CubeReflection.cpp b/examples/CubeReflection.cpp index 56263d444a..a848938caf 100644 --- a/examples/CubeReflection.cpp +++ b/examples/CubeReflection.cpp @@ -156,15 +156,15 @@ void init() { fragColor = vec4(mix(f_col, vec3(0.5, 0.5, 0.5), 0.5), 1.0); })"); - utils::ComboInputStateDescriptor inputState; - inputState.numAttributes = 2; - inputState.cAttributes[0].format = dawn::VertexFormat::Float3; - inputState.cAttributes[1].shaderLocation = 1; - inputState.cAttributes[1].offset = 3 * sizeof(float); - inputState.cAttributes[1].format = dawn::VertexFormat::Float3; + utils::ComboVertexInputDescriptor vertexInput; + vertexInput.numAttributes = 2; + vertexInput.cAttributes[0].format = dawn::VertexFormat::Float3; + vertexInput.cAttributes[1].shaderLocation = 1; + vertexInput.cAttributes[1].offset = 3 * sizeof(float); + vertexInput.cAttributes[1].format = dawn::VertexFormat::Float3; - inputState.numInputs = 1; - inputState.cInputs[0].stride = 6 * sizeof(float); + vertexInput.numBuffers = 1; + vertexInput.cBuffers[0].stride = 6 * sizeof(float); auto bgl = utils::MakeBindGroupLayout( device, { @@ -201,7 +201,7 @@ void init() { descriptor.layout = pl; descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; - descriptor.inputState = &inputState; + descriptor.vertexInput = &vertexInput; descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); @@ -214,7 +214,7 @@ void init() { pDescriptor.layout = pl; pDescriptor.cVertexStage.module = vsModule; pDescriptor.cFragmentStage.module = fsModule; - pDescriptor.inputState = &inputState; + pDescriptor.vertexInput = &vertexInput; pDescriptor.depthStencilState = &pDescriptor.cDepthStencilState; pDescriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; pDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); @@ -228,7 +228,7 @@ void init() { rfDescriptor.layout = pl; rfDescriptor.cVertexStage.module = vsModule; rfDescriptor.cFragmentStage.module = fsReflectionModule; - rfDescriptor.inputState = &inputState; + rfDescriptor.vertexInput = &vertexInput; rfDescriptor.depthStencilState = &rfDescriptor.cDepthStencilState; rfDescriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; rfDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); diff --git a/src/common/Constants.h b/src/common/Constants.h index 0a41dfffd1..aa04501abf 100644 --- a/src/common/Constants.h +++ b/src/common/Constants.h @@ -24,12 +24,13 @@ static constexpr uint32_t kMaxBindingsPerGroup = 16u; static constexpr uint32_t kMaxVertexAttributes = 16u; // 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 -// maxVertexInputBindingStride (2048u at least). We use maxVertexAttributeEnd (2048u) here to verify -// vertex attribute offset, which equals to maxOffset + smallest size of vertex format (char). We -// may use maxVertexInputStride instead in future. +// maxVertexInputBindingStride (2048u at least). We use maxVertexAttributeEnd (2048u) here to +// verify vertex attribute offset, which equals to maxOffset + smallest size of vertex format +// (char). We may use maxVertexInputBindingStride (maxVertexBufferStride below) instead to replace +// maxVertexAttributeEnd in future. static constexpr uint32_t kMaxVertexAttributeEnd = 2048u; -static constexpr uint32_t kMaxVertexInputs = 16u; -static constexpr uint32_t kMaxVertexInputStride = 2048u; +static constexpr uint32_t kMaxVertexBuffers = 16u; +static constexpr uint32_t kMaxVertexBufferStride = 2048u; static constexpr uint32_t kNumStages = 3; static constexpr uint32_t kMaxColorAttachments = 4u; static constexpr uint32_t kTextureRowPitchAlignment = 256u; diff --git a/src/dawn_native/CommandBufferStateTracker.h b/src/dawn_native/CommandBufferStateTracker.h index f2580e423c..2009dd7340 100644 --- a/src/dawn_native/CommandBufferStateTracker.h +++ b/src/dawn_native/CommandBufferStateTracker.h @@ -53,7 +53,7 @@ namespace dawn_native { ValidationAspects mAspects; std::array mBindgroups = {}; - std::bitset mInputsSet; + std::bitset mInputsSet; PipelineLayoutBase* mLastPipelineLayout = nullptr; RenderPipelineBase* mLastRenderPipeline = nullptr; diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp index e44d2879ee..699c992eec 100644 --- a/src/dawn_native/RenderPipeline.cpp +++ b/src/dawn_native/RenderPipeline.cpp @@ -25,33 +25,33 @@ namespace dawn_native { // Helper functions namespace { - MaybeError ValidateVertexInputDescriptor(const VertexInputDescriptor* input, - std::bitset* inputsSetMask) { - DAWN_TRY(ValidateInputStepMode(input->stepMode)); - if (input->inputSlot >= kMaxVertexInputs) { - return DAWN_VALIDATION_ERROR("Setting input out of bounds"); + MaybeError ValidateVertexBufferDescriptor(const VertexBufferDescriptor* buffer, + std::bitset* inputsSetMask) { + DAWN_TRY(ValidateInputStepMode(buffer->stepMode)); + if (buffer->inputSlot >= kMaxVertexBuffers) { + 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"); } - if ((*inputsSetMask)[input->inputSlot]) { - return DAWN_VALIDATION_ERROR("Setting already set input"); + if ((*inputsSetMask)[buffer->inputSlot]) { + return DAWN_VALIDATION_ERROR("Setting already set vertex buffer"); } - inputsSetMask->set(input->inputSlot); + inputsSetMask->set(buffer->inputSlot); return {}; } MaybeError ValidateVertexAttributeDescriptor( const VertexAttributeDescriptor* attribute, - const std::bitset* inputsSetMask, + const std::bitset* inputsSetMask, std::bitset* attributesSetMask) { DAWN_TRY(ValidateVertexFormat(attribute->format)); if (attribute->shaderLocation >= kMaxVertexAttributes) { 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"); } ASSERT(kMaxVertexAttributeEnd >= VertexFormatSize(attribute->format)); @@ -70,24 +70,24 @@ namespace dawn_native { return {}; } - MaybeError ValidateInputStateDescriptor( - const InputStateDescriptor* descriptor, - std::bitset* inputsSetMask, + MaybeError ValidateVertexInputDescriptor( + const VertexInputDescriptor* descriptor, + std::bitset* inputsSetMask, std::bitset* attributesSetMask) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } DAWN_TRY(ValidateIndexFormat(descriptor->indexFormat)); - if (descriptor->numInputs > kMaxVertexInputs) { + if (descriptor->numBuffers > kMaxVertexBuffers) { return DAWN_VALIDATION_ERROR("Vertex Inputs number exceeds maximum"); } if (descriptor->numAttributes > kMaxVertexAttributes) { return DAWN_VALIDATION_ERROR("Vertex Attributes number exceeds maximum"); } - for (uint32_t i = 0; i < descriptor->numInputs; ++i) { - DAWN_TRY(ValidateVertexInputDescriptor(&descriptor->inputs[i], inputsSetMask)); + for (uint32_t i = 0; i < descriptor->numBuffers; ++i) { + DAWN_TRY(ValidateVertexBufferDescriptor(&descriptor->buffers[i], inputsSetMask)); } for (uint32_t i = 0; i < descriptor->numAttributes; ++i) { @@ -262,14 +262,14 @@ namespace dawn_native { DAWN_TRY(device->ValidateObject(descriptor->layout)); - if (descriptor->inputState == nullptr) { + if (descriptor->vertexInput == nullptr) { return DAWN_VALIDATION_ERROR("Input state must not be null"); } - std::bitset inputsSetMask; + std::bitset inputsSetMask; std::bitset attributesSetMask; - DAWN_TRY(ValidateInputStateDescriptor(descriptor->inputState, &inputsSetMask, - &attributesSetMask)); + DAWN_TRY(ValidateVertexInputDescriptor(descriptor->vertexInput, &inputsSetMask, + &attributesSetMask)); DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology)); DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->vertexStage, descriptor->layout, dawn::ShaderStage::Vertex)); @@ -334,7 +334,7 @@ namespace dawn_native { : PipelineBase(device, descriptor->layout, dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment), - mInputState(*descriptor->inputState), + mVertexInput(*descriptor->vertexInput), mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr), mPrimitiveTopology(descriptor->primitiveTopology), mRasterizationState(*descriptor->rasterizationState), @@ -345,16 +345,16 @@ namespace dawn_native { mFragmentEntryPoint(descriptor->fragmentStage->entryPoint), mIsBlueprint(blueprint) { uint32_t location = 0; - for (uint32_t i = 0; i < mInputState.numAttributes; ++i) { - location = mInputState.attributes[i].shaderLocation; + for (uint32_t i = 0; i < mVertexInput.numAttributes; ++i) { + location = mVertexInput.attributes[i].shaderLocation; mAttributesSetMask.set(location); - mAttributeInfos[location] = mInputState.attributes[i]; + mAttributeInfos[location] = mVertexInput.attributes[i]; } uint32_t slot = 0; - for (uint32_t i = 0; i < mInputState.numInputs; ++i) { - slot = mInputState.inputs[i].inputSlot; + for (uint32_t i = 0; i < mVertexInput.numBuffers; ++i) { + slot = mVertexInput.buffers[i].inputSlot; mInputsSetMask.set(slot); - mInputInfos[slot] = mInputState.inputs[i]; + mInputInfos[slot] = mVertexInput.buffers[i]; } if (mHasDepthStencilAttachment) { @@ -405,9 +405,9 @@ namespace dawn_native { } } - const InputStateDescriptor* RenderPipelineBase::GetInputStateDescriptor() const { + const VertexInputDescriptor* RenderPipelineBase::GetVertexInputDescriptor() const { ASSERT(!IsError()); - return &mInputState; + return &mVertexInput; } const std::bitset& RenderPipelineBase::GetAttributesSetMask() const { @@ -421,12 +421,12 @@ namespace dawn_native { return mAttributeInfos[location]; } - const std::bitset& RenderPipelineBase::GetInputsSetMask() const { + const std::bitset& RenderPipelineBase::GetInputsSetMask() const { ASSERT(!IsError()); return mInputsSetMask; } - const VertexInputDescriptor& RenderPipelineBase::GetInput(uint32_t slot) const { + const VertexBufferDescriptor& RenderPipelineBase::GetInput(uint32_t slot) const { ASSERT(!IsError()); ASSERT(mInputsSetMask[slot]); return mInputInfos[slot]; @@ -561,11 +561,11 @@ namespace dawn_native { HashCombine(&hash, 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, pipeline->mInputState.indexFormat); + HashCombine(&hash, pipeline->mVertexInput.indexFormat); // Hash rasterization state { @@ -660,15 +660,15 @@ namespace dawn_native { } for (uint32_t i : IterateBitSet(a->mInputsSetMask)) { - const VertexInputDescriptor& descA = a->GetInput(i); - const VertexInputDescriptor& descB = b->GetInput(i); + const VertexBufferDescriptor& descA = a->GetInput(i); + const VertexBufferDescriptor& descB = b->GetInput(i); if (descA.inputSlot != descB.inputSlot || descA.stride != descB.stride || descA.stepMode != descB.stepMode) { return false; } } - if (a->mInputState.indexFormat != b->mInputState.indexFormat) { + if (a->mVertexInput.indexFormat != b->mVertexInput.indexFormat) { return false; } diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h index 98fc1adfb1..df4bf58064 100644 --- a/src/dawn_native/RenderPipeline.h +++ b/src/dawn_native/RenderPipeline.h @@ -47,11 +47,11 @@ namespace dawn_native { static RenderPipelineBase* MakeError(DeviceBase* device); - const InputStateDescriptor* GetInputStateDescriptor() const; + const VertexInputDescriptor* GetVertexInputDescriptor() const; const std::bitset& GetAttributesSetMask() const; const VertexAttributeDescriptor& GetAttribute(uint32_t location) const; - const std::bitset& GetInputsSetMask() const; - const VertexInputDescriptor& GetInput(uint32_t slot) const; + const std::bitset& GetInputsSetMask() const; + const VertexBufferDescriptor& GetInput(uint32_t slot) const; const ColorStateDescriptor* GetColorStateDescriptor(uint32_t attachmentSlot) const; const DepthStencilStateDescriptor* GetDepthStencilStateDescriptor() const; @@ -69,7 +69,7 @@ namespace dawn_native { // attachments in the render pass. This returns whether it is the case. bool IsCompatibleWith(const BeginRenderPassCmd* renderPassCmd) const; std::bitset GetAttributesUsingInput(uint32_t slot) const; - std::array, kMaxVertexInputs> attributesUsingInput; + std::array, kMaxVertexBuffers> attributesUsingInput; // Functors necessary for the unordered_set-based cache. struct HashFunc { @@ -83,11 +83,11 @@ namespace dawn_native { RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag); // Vertex input - InputStateDescriptor mInputState; + VertexInputDescriptor mVertexInput; std::bitset mAttributesSetMask; std::array mAttributeInfos; - std::bitset mInputsSetMask; - std::array mInputInfos; + std::bitset mInputsSetMask; + std::array mInputInfos; // Attachments bool mHasDepthStencilAttachment = false; diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 18e6d1cc48..d9c7d52fb8 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -653,7 +653,7 @@ namespace dawn_native { namespace d3d12 { commandList->IASetVertexBuffers(startSlot, count, &vertexBuffersInfo->d3d12BufferViews[startSlot]); - vertexBuffersInfo->startSlot = kMaxVertexInputs; + vertexBuffersInfo->startSlot = kMaxVertexBuffers; 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 // format after SetIndexBuffer bufferView.Format = - DXGIIndexFormat(lastPipeline->GetInputStateDescriptor()->indexFormat); + DXGIIndexFormat(lastPipeline->GetVertexInputDescriptor()->indexFormat); commandList->IASetIndexBuffer(&bufferView); } break; diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.h b/src/dawn_native/d3d12/CommandBufferD3D12.h index 694f98c9f0..ed508858b4 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.h +++ b/src/dawn_native/d3d12/CommandBufferD3D12.h @@ -41,9 +41,9 @@ namespace dawn_native { namespace d3d12 { // represent the union of the dirty ranges (the union may have non-dirty // data in the middle of the range). const RenderPipeline* lastRenderPipeline = nullptr; - uint32_t startSlot = kMaxVertexInputs; + uint32_t startSlot = kMaxVertexBuffers; uint32_t endSlot = 0; - std::array d3d12BufferViews = {}; + std::array d3d12BufferViews = {}; }; class CommandBuffer : public CommandBufferBase { diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp index 5df00b1a5e..c8b11eaf83 100644 --- a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp +++ b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp @@ -409,7 +409,7 @@ namespace dawn_native { namespace d3d12 { inputElementDescriptor.Format = VertexFormatType(attribute.format); inputElementDescriptor.InputSlot = attribute.inputSlot; - const VertexInputDescriptor& input = GetInput(attribute.inputSlot); + const VertexBufferDescriptor& input = GetInput(attribute.inputSlot); inputElementDescriptor.AlignedByteOffset = attribute.offset; inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode); diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm index d44740e1d3..1c30164fff 100644 --- a/src/dawn_native/metal/CommandBufferMTL.mm +++ b/src/dawn_native/metal/CommandBufferMTL.mm @@ -804,7 +804,7 @@ namespace dawn_native { namespace metal { case Command::DrawIndexed: { DrawIndexedCmd* draw = mCommands.NextCommand(); size_t formatSize = - IndexFormatSize(lastPipeline->GetInputStateDescriptor()->indexFormat); + IndexFormatSize(lastPipeline->GetVertexInputDescriptor()->indexFormat); // The index and instance count must be non-zero, otherwise no-op if (draw->indexCount != 0 && draw->instanceCount != 0) { @@ -926,8 +926,8 @@ namespace dawn_native { namespace metal { auto buffers = mCommands.NextData>(cmd->count); auto offsets = mCommands.NextData(cmd->count); - std::array, kMaxVertexInputs> mtlBuffers; - std::array mtlOffsets; + std::array, kMaxVertexBuffers> mtlBuffers; + std::array mtlOffsets; // Perhaps an "array of vertex buffers(+offsets?)" should be // a Dawn API primitive to avoid reconstructing this array? diff --git a/src/dawn_native/metal/RenderPipelineMTL.mm b/src/dawn_native/metal/RenderPipelineMTL.mm index 0a92c93df7..078a081c75 100644 --- a/src/dawn_native/metal/RenderPipelineMTL.mm +++ b/src/dawn_native/metal/RenderPipelineMTL.mm @@ -307,7 +307,7 @@ namespace dawn_native { namespace metal { RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor) : RenderPipelineBase(device, descriptor), - mMtlIndexType(MTLIndexFormat(GetInputStateDescriptor()->indexFormat)), + mMtlIndexType(MTLIndexFormat(GetVertexInputDescriptor()->indexFormat)), mMtlPrimitiveTopology(MTLPrimitiveTopology(GetPrimitiveTopology())), mMtlFrontFace(MTLFrontFace(GetFrontFace())), mMtlCullMode(ToMTLCullMode(GetCullMode())) { @@ -416,7 +416,7 @@ namespace dawn_native { namespace metal { } for (uint32_t i : IterateBitSet(GetInputsSetMask())) { - const VertexInputDescriptor& info = GetInput(i); + const VertexBufferDescriptor& info = GetInput(i); auto layoutDesc = [MTLVertexBufferLayoutDescriptor new]; if (info.stride == 0) { diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp index 686f9dbad3..7973d44201 100644 --- a/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/src/dawn_native/opengl/CommandBufferGL.cpp @@ -210,8 +210,8 @@ namespace dawn_native { namespace opengl { }; // 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. - // This means that we have to re-apply these buffers on an InputState change. + // 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 VertexInput change. class InputBufferTracker { public: 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 - static_assert(kMaxVertexInputs <= 8 * sizeof(unsigned long long) - 1, ""); + static_assert(kMaxVertexBuffers <= 8 * sizeof(unsigned long long) - 1, ""); mDirtyVertexBuffers |= ((1ull << count) - 1ull) << startSlot; } @@ -286,9 +286,9 @@ namespace dawn_native { namespace opengl { bool mIndexBufferDirty = false; Buffer* mIndexBuffer = nullptr; - std::bitset mDirtyVertexBuffers; - std::array mVertexBuffers; - std::array mVertexBufferOffsets; + std::bitset mDirtyVertexBuffers; + std::array mVertexBuffers; + std::array mVertexBufferOffsets; RenderPipelineBase* mLastPipeline = nullptr; }; @@ -772,7 +772,7 @@ namespace dawn_native { namespace opengl { inputBuffers.Apply(); dawn::IndexFormat indexFormat = - lastPipeline->GetInputStateDescriptor()->indexFormat; + lastPipeline->GetVertexInputDescriptor()->indexFormat; size_t formatSize = IndexFormatSize(indexFormat); GLenum formatType = IndexFormatType(indexFormat); diff --git a/src/dawn_native/opengl/RenderPipelineGL.cpp b/src/dawn_native/opengl/RenderPipelineGL.cpp index ada39b21bc..5e3f2d6c19 100644 --- a/src/dawn_native/opengl/RenderPipelineGL.cpp +++ b/src/dawn_native/opengl/RenderPipelineGL.cpp @@ -182,7 +182,7 @@ namespace dawn_native { namespace opengl { modules[dawn::ShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module); PipelineGL::Initialize(ToBackend(GetLayout()), modules); - CreateVAOForInputState(descriptor->inputState); + CreateVAOForVertexInput(descriptor->vertexInput); } RenderPipeline::~RenderPipeline() { @@ -194,7 +194,7 @@ namespace dawn_native { namespace opengl { return mGlPrimitiveTopology; } - void RenderPipeline::CreateVAOForInputState(const InputStateDescriptor* inputState) { + void RenderPipeline::CreateVAOForVertexInput(const VertexInputDescriptor* vertexInput) { glGenVertexArrays(1, &mVertexArrayObject); glBindVertexArray(mVertexArrayObject); for (uint32_t location : IterateBitSet(GetAttributesSetMask())) { diff --git a/src/dawn_native/opengl/RenderPipelineGL.h b/src/dawn_native/opengl/RenderPipelineGL.h index dc51f6f9e8..6dc3c1495d 100644 --- a/src/dawn_native/opengl/RenderPipelineGL.h +++ b/src/dawn_native/opengl/RenderPipelineGL.h @@ -38,7 +38,7 @@ namespace dawn_native { namespace opengl { void ApplyNow(PersistentPipelineState& persistentPipelineState); private: - void CreateVAOForInputState(const InputStateDescriptor* inputState); + void CreateVAOForVertexInput(const VertexInputDescriptor* vertexInput); // TODO(yunchao.he@intel.com): vao need to be deduplicated between pipelines. GLuint mVertexArrayObject; diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp index e65f537799..3c81af40ce 100644 --- a/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/src/dawn_native/vulkan/CommandBufferVk.cpp @@ -575,7 +575,7 @@ namespace dawn_native { namespace vulkan { // and rebind if needed on pipeline change ASSERT(lastPipeline != nullptr); VkIndexType indexType = - VulkanIndexType(lastPipeline->GetInputStateDescriptor()->indexFormat); + VulkanIndexType(lastPipeline->GetVertexInputDescriptor()->indexFormat); device->fn.CmdBindIndexBuffer( commands, indexBuffer, static_cast(cmd->offset), indexType); } break; @@ -613,8 +613,8 @@ namespace dawn_native { namespace vulkan { auto buffers = mCommands.NextData>(cmd->count); auto offsets = mCommands.NextData(cmd->count); - std::array vkBuffers; - std::array vkOffsets; + std::array vkBuffers; + std::array vkOffsets; for (uint32_t i = 0; i < cmd->count; ++i) { Buffer* buffer = ToBackend(buffers[i].Get()); diff --git a/src/dawn_native/vulkan/RenderPipelineVk.cpp b/src/dawn_native/vulkan/RenderPipelineVk.cpp index e2cbca93d1..581e303d35 100644 --- a/src/dawn_native/vulkan/RenderPipelineVk.cpp +++ b/src/dawn_native/vulkan/RenderPipelineVk.cpp @@ -296,11 +296,11 @@ namespace dawn_native { namespace vulkan { shaderStages[1].pName = descriptor->fragmentStage->entryPoint; } - std::array mBindings; + std::array mBindings; std::array mAttributes; - const InputStateDescriptor* inputState = GetInputStateDescriptor(); - VkPipelineVertexInputStateCreateInfo inputStateCreateInfo = - ComputeInputStateDesc(inputState, &mBindings, &mAttributes); + const VertexInputDescriptor* vertexInput = GetVertexInputDescriptor(); + VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo = + ComputeVertexInputDesc(vertexInput, &mBindings, &mAttributes); VkPipelineInputAssemblyStateCreateInfo inputAssembly; inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; @@ -427,7 +427,7 @@ namespace dawn_native { namespace vulkan { createInfo.flags = 0; createInfo.stageCount = 2; createInfo.pStages = shaderStages; - createInfo.pVertexInputState = &inputStateCreateInfo; + createInfo.pVertexInputState = &vertexInputCreateInfo; createInfo.pInputAssemblyState = &inputAssembly; createInfo.pTessellationState = nullptr; createInfo.pViewportState = &viewport; @@ -448,9 +448,9 @@ namespace dawn_native { namespace vulkan { } } - VkPipelineVertexInputStateCreateInfo RenderPipeline::ComputeInputStateDesc( - const InputStateDescriptor* inputState, - std::array* mBindings, + VkPipelineVertexInputStateCreateInfo RenderPipeline::ComputeVertexInputDesc( + const VertexInputDescriptor* vertexInput, + std::array* mBindings, std::array* mAttributes) { // Fill in the "binding info" that will be chained in the create info uint32_t bindingCount = 0; diff --git a/src/dawn_native/vulkan/RenderPipelineVk.h b/src/dawn_native/vulkan/RenderPipelineVk.h index 5d58fa7397..083c3abb99 100644 --- a/src/dawn_native/vulkan/RenderPipelineVk.h +++ b/src/dawn_native/vulkan/RenderPipelineVk.h @@ -31,9 +31,9 @@ namespace dawn_native { namespace vulkan { VkPipeline GetHandle() const; private: - VkPipelineVertexInputStateCreateInfo ComputeInputStateDesc( - const InputStateDescriptor* inputState, - std::array* mBindings, + VkPipelineVertexInputStateCreateInfo ComputeVertexInputDesc( + const VertexInputDescriptor* vertexInput, + std::array* mBindings, std::array* mAttributes); VkPipeline mHandle = VK_NULL_HANDLE; diff --git a/src/tests/end2end/DestroyTests.cpp b/src/tests/end2end/DestroyTests.cpp index 8bd4cda90d..3deaeaa082 100644 --- a/src/tests/end2end/DestroyTests.cpp +++ b/src/tests/end2end/DestroyTests.cpp @@ -46,10 +46,10 @@ class DestroyTest : public DawnTest { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip; - descriptor.cInputState.numInputs = 1; - descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); - descriptor.cInputState.numAttributes = 1; - descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; + descriptor.cVertexInput.numBuffers = 1; + descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); + descriptor.cVertexInput.numAttributes = 1; + descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cColorStates[0]->format = renderPass.colorFormat; pipeline = device.CreateRenderPipeline(&descriptor); diff --git a/src/tests/end2end/DrawIndexedTests.cpp b/src/tests/end2end/DrawIndexedTests.cpp index 02421c7a6b..44baa2bbd2 100644 --- a/src/tests/end2end/DrawIndexedTests.cpp +++ b/src/tests/end2end/DrawIndexedTests.cpp @@ -46,10 +46,10 @@ class DrawIndexedTest : public DawnTest { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip; - descriptor.cInputState.numInputs = 1; - descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); - descriptor.cInputState.numAttributes = 1; - descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; + descriptor.cVertexInput.numBuffers = 1; + descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); + descriptor.cVertexInput.numAttributes = 1; + descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cColorStates[0]->format = renderPass.colorFormat; pipeline = device.CreateRenderPipeline(&descriptor); diff --git a/src/tests/end2end/DrawTests.cpp b/src/tests/end2end/DrawTests.cpp index b2c36f7dcb..c09e337e18 100644 --- a/src/tests/end2end/DrawTests.cpp +++ b/src/tests/end2end/DrawTests.cpp @@ -46,10 +46,10 @@ class DrawTest : public DawnTest { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip; - descriptor.cInputState.numInputs = 1; - descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); - descriptor.cInputState.numAttributes = 1; - descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; + descriptor.cVertexInput.numBuffers = 1; + descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); + descriptor.cVertexInput.numAttributes = 1; + descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cColorStates[0]->format = renderPass.colorFormat; pipeline = device.CreateRenderPipeline(&descriptor); diff --git a/src/tests/end2end/IndexFormatTests.cpp b/src/tests/end2end/IndexFormatTests.cpp index d4b2acb137..f7122c79dc 100644 --- a/src/tests/end2end/IndexFormatTests.cpp +++ b/src/tests/end2end/IndexFormatTests.cpp @@ -52,11 +52,11 @@ class IndexFormatTest : public DawnTest { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip; - descriptor.cInputState.indexFormat = format; - descriptor.cInputState.numInputs = 1; - descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); - descriptor.cInputState.numAttributes = 1; - descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; + descriptor.cVertexInput.indexFormat = format; + descriptor.cVertexInput.numBuffers = 1; + descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); + descriptor.cVertexInput.numAttributes = 1; + descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cColorStates[0]->format = renderPass.colorFormat; return device.CreateRenderPipeline(&descriptor); diff --git a/src/tests/end2end/InputStateTests.cpp b/src/tests/end2end/InputStateTests.cpp deleted file mode 100644 index c463dc12f6..0000000000 --- a/src/tests/end2end/InputStateTests.cpp +++ /dev/null @@ -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& 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& inputs, - const std::vector& 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 - dawn::Buffer MakeVertexBuffer(std::vector data) { - return utils::CreateBufferFromData(device, data.data(), static_cast(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 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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 diff --git a/src/tests/end2end/PrimitiveTopologyTests.cpp b/src/tests/end2end/PrimitiveTopologyTests.cpp index 552715b7e1..d0bd8510c8 100644 --- a/src/tests/end2end/PrimitiveTopologyTests.cpp +++ b/src/tests/end2end/PrimitiveTopologyTests.cpp @@ -185,10 +185,10 @@ class PrimitiveTopologyTest : public DawnTest { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; descriptor.primitiveTopology = primitiveTopology; - descriptor.cInputState.numInputs = 1; - descriptor.cInputState.cInputs[0].stride = 4 * sizeof(float); - descriptor.cInputState.numAttributes = 1; - descriptor.cInputState.cAttributes[0].format = dawn::VertexFormat::Float4; + descriptor.cVertexInput.numBuffers = 1; + descriptor.cVertexInput.cBuffers[0].stride = 4 * sizeof(float); + descriptor.cVertexInput.numAttributes = 1; + descriptor.cVertexInput.cAttributes[0].format = dawn::VertexFormat::Float4; descriptor.cColorStates[0]->format = renderPass.colorFormat; dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor); diff --git a/src/tests/end2end/VertexFormatTests.cpp b/src/tests/end2end/VertexFormatTests.cpp index 6d20bb8d5c..f65e126bb6 100644 --- a/src/tests/end2end/VertexFormatTests.cpp +++ b/src/tests/end2end/VertexFormatTests.cpp @@ -362,10 +362,10 @@ class VertexFormatTest : public DawnTest { utils::ComboRenderPipelineDescriptor descriptor(device); descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; - descriptor.cInputState.numInputs = 1; - descriptor.cInputState.cInputs[0].stride = strideBytes; - descriptor.cInputState.numAttributes = 1; - descriptor.cInputState.cAttributes[0].format = format; + descriptor.cVertexInput.numBuffers = 1; + descriptor.cVertexInput.cBuffers[0].stride = strideBytes; + descriptor.cVertexInput.numAttributes = 1; + descriptor.cVertexInput.cAttributes[0].format = format; descriptor.cColorStates[0]->format = renderPass.colorFormat; return device.CreateRenderPipeline(&descriptor); @@ -797,4 +797,4 @@ TEST_P(VertexFormatTest, Int4) { DoVertexFormatTest(dawn::VertexFormat::Int4, vertexData, vertexData); } -DAWN_INSTANTIATE_TEST(VertexFormatTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend); \ No newline at end of file +DAWN_INSTANTIATE_TEST(VertexFormatTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend); diff --git a/src/tests/end2end/VertexInputTests.cpp b/src/tests/end2end/VertexInputTests.cpp new file mode 100644 index 0000000000..f23df7327e --- /dev/null +++ b/src/tests/end2end/VertexInputTests.cpp @@ -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& 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& buffers, + const std::vector& 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 + dawn::Buffer MakeVertexBuffer(std::vector data) { + return utils::CreateBufferFromData(device, data.data(), + static_cast(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 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({ + 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({ + 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({ + 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({ + 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({ + 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({ + 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({ + 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({ + 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({ + 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({ + 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({ + 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({ + 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({ + 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 diff --git a/src/tests/unittests/validation/VertexBufferValidationTests.cpp b/src/tests/unittests/validation/VertexBufferValidationTests.cpp index 36cbd4d6d5..60561ae1ef 100644 --- a/src/tests/unittests/validation/VertexBufferValidationTests.cpp +++ b/src/tests/unittests/validation/VertexBufferValidationTests.cpp @@ -45,18 +45,18 @@ class VertexBufferValidationTest : public ValidationTest { return buffers; } - dawn::ShaderModule MakeVertexShader(unsigned int numInputs) { + dawn::ShaderModule MakeVertexShader(unsigned int numBuffers) { std::ostringstream vs; 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 << "void main() {\n"; vs << "gl_Position = vec4("; - for (unsigned int i = 0; i < numInputs; ++i) { + for (unsigned int i = 0; i < numBuffers; ++i) { vs << "a_position" << i; - if (i != numInputs - 1) { + if (i != numBuffers - 1) { vs << " + "; } } @@ -68,19 +68,19 @@ class VertexBufferValidationTest : public ValidationTest { } dawn::RenderPipeline MakeRenderPipeline(const dawn::ShaderModule& vsModule, - unsigned int numInputs) { + unsigned int numBuffers) { utils::ComboRenderPipelineDescriptor descriptor(device); descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; - for (unsigned int i = 0; i < numInputs; ++i) { - descriptor.cInputState.cAttributes[i].shaderLocation = i; - descriptor.cInputState.cAttributes[i].inputSlot = i; - descriptor.cInputState.cAttributes[i].format = dawn::VertexFormat::Float3; - descriptor.cInputState.cInputs[i].inputSlot = i; + for (unsigned int i = 0; i < numBuffers; ++i) { + descriptor.cVertexInput.cAttributes[i].shaderLocation = i; + descriptor.cVertexInput.cAttributes[i].inputSlot = i; + descriptor.cVertexInput.cAttributes[i].format = dawn::VertexFormat::Float3; + descriptor.cVertexInput.cBuffers[i].inputSlot = i; } - descriptor.cInputState.numInputs = numInputs; - descriptor.cInputState.numAttributes = numInputs; + descriptor.cVertexInput.numBuffers = numBuffers; + descriptor.cVertexInput.numAttributes = numBuffers; return device.CreateRenderPipeline(&descriptor); } @@ -88,7 +88,7 @@ class VertexBufferValidationTest : public ValidationTest { dawn::ShaderModule fsModule; }; -TEST_F(VertexBufferValidationTest, VertexInputsInheritedBetweenPipelines) { +TEST_F(VertexBufferValidationTest, VertexBuffersInheritedBetweenPipelines) { DummyRenderPass renderPass(device); auto vsModule2 = MakeVertexShader(2); auto vsModule1 = MakeVertexShader(1); @@ -123,7 +123,7 @@ TEST_F(VertexBufferValidationTest, VertexInputsInheritedBetweenPipelines) { encoder.Finish(); } -TEST_F(VertexBufferValidationTest, VertexInputsNotInheritedBetweenRendePasses) { +TEST_F(VertexBufferValidationTest, VertexBuffersNotInheritedBetweenRendePasses) { DummyRenderPass renderPass(device); auto vsModule2 = MakeVertexShader(2); auto vsModule1 = MakeVertexShader(1); diff --git a/src/tests/unittests/validation/InputStateValidationTests.cpp b/src/tests/unittests/validation/VertexInputValidationTests.cpp similarity index 70% rename from src/tests/unittests/validation/InputStateValidationTests.cpp rename to src/tests/unittests/validation/VertexInputValidationTests.cpp index 4799817217..d208fc3e06 100644 --- a/src/tests/unittests/validation/InputStateValidationTests.cpp +++ b/src/tests/unittests/validation/VertexInputValidationTests.cpp @@ -17,15 +17,15 @@ #include "utils/ComboRenderPipelineDescriptor.h" #include "utils/DawnHelpers.h" -class InputStateTest : public ValidationTest { - protected: - void CreatePipeline(bool success, - const utils::ComboInputStateDescriptor& state, - std::string vertexSource) { - dawn::ShaderModule vsModule = - utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vertexSource.c_str()); - dawn::ShaderModule fsModule = - utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"( +class VertexInputTest : public ValidationTest { + protected: + void CreatePipeline(bool success, + const utils::ComboVertexInputDescriptor& state, + std::string vertexSource) { + dawn::ShaderModule vsModule = + utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vertexSource.c_str()); + dawn::ShaderModule fsModule = + utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"( #version 450 layout(location = 0) out vec4 fragColor; void main() { @@ -33,23 +33,23 @@ class InputStateTest : public ValidationTest { } )"); - utils::ComboRenderPipelineDescriptor descriptor(device); - descriptor.cVertexStage.module = vsModule; - descriptor.cFragmentStage.module = fsModule; - descriptor.inputState = &state; - descriptor.cColorStates[0]->format = dawn::TextureFormat::R8G8B8A8Unorm; + utils::ComboRenderPipelineDescriptor descriptor(device); + descriptor.cVertexStage.module = vsModule; + descriptor.cFragmentStage.module = fsModule; + descriptor.vertexInput = &state; + descriptor.cColorStates[0]->format = dawn::TextureFormat::R8G8B8A8Unorm; - if (!success) { - ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor)); - } else { - device.CreateRenderPipeline(&descriptor); - } - } + if (!success) { + ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor)); + } else { + device.CreateRenderPipeline(&descriptor); + } + } }; // Check an empty input state is valid -TEST_F(InputStateTest, EmptyIsOk) { - utils::ComboInputStateDescriptor state; +TEST_F(VertexInputTest, EmptyIsOk) { + utils::ComboVertexInputDescriptor state; CreatePipeline(true, state, R"( #version 450 void main() { @@ -58,11 +58,11 @@ TEST_F(InputStateTest, EmptyIsOk) { )"); } -// Check validation that pipeline vertex inputs are backed by attributes in the input state -TEST_F(InputStateTest, PipelineCompatibility) { - utils::ComboInputStateDescriptor state; - state.numInputs = 1; - state.cInputs[0].stride = 2 * sizeof(float); +// Check validation that pipeline vertex buffers are backed by attributes in the vertex input +TEST_F(VertexInputTest, PipelineCompatibility) { + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; + state.cBuffers[0].stride = 2 * sizeof(float); state.numAttributes = 2; state.cAttributes[1].shaderLocation = 1; 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"( #version 450 layout(location = 0) in vec4 a; @@ -97,10 +97,10 @@ TEST_F(InputStateTest, PipelineCompatibility) { } // Test that a stride of 0 is valid -TEST_F(InputStateTest, StrideZero) { +TEST_F(VertexInputTest, StrideZero) { // Works ok without attributes - utils::ComboInputStateDescriptor state; - state.numInputs = 1; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; CreatePipeline(true, state, R"( #version 450 void main() { @@ -120,10 +120,10 @@ TEST_F(InputStateTest, StrideZero) { } // Test that we cannot set an already set input -TEST_F(InputStateTest, AlreadySetInput) { +TEST_F(VertexInputTest, AlreadySetInput) { // Control case - utils::ComboInputStateDescriptor state; - state.numInputs = 1; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; CreatePipeline(true, state, R"( #version 450 void main() { @@ -132,7 +132,7 @@ TEST_F(InputStateTest, AlreadySetInput) { )"); // Oh no, input 0 is set twice - state.numInputs = 2; + state.numBuffers = 2; CreatePipeline(false, state, R"( #version 450 void main() { @@ -142,11 +142,11 @@ TEST_F(InputStateTest, AlreadySetInput) { } // Check out of bounds condition on input slot -TEST_F(InputStateTest, SetInputSlotOutOfBounds) { +TEST_F(VertexInputTest, SetInputSlotOutOfBounds) { // Control case, setting last input slot - utils::ComboInputStateDescriptor state; - state.numInputs = 1; - state.cInputs[0].inputSlot = kMaxVertexInputs - 1; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; + state.cBuffers[0].inputSlot = kMaxVertexBuffers - 1; CreatePipeline(true, state, R"( #version 450 void main() { @@ -155,7 +155,7 @@ TEST_F(InputStateTest, SetInputSlotOutOfBounds) { )"); // Test input slot OOB - state.cInputs[0].inputSlot = kMaxVertexInputs; + state.cBuffers[0].inputSlot = kMaxVertexBuffers; CreatePipeline(false, state, R"( #version 450 void main() { @@ -165,11 +165,11 @@ TEST_F(InputStateTest, SetInputSlotOutOfBounds) { } // Check out of bounds condition on input stride -TEST_F(InputStateTest, SetInputStrideOutOfBounds) { +TEST_F(VertexInputTest, SetInputStrideOutOfBounds) { // Control case, setting max input stride - utils::ComboInputStateDescriptor state; - state.numInputs = 1; - state.cInputs[0].stride = kMaxVertexInputStride; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; + state.cBuffers[0].stride = kMaxVertexBufferStride; CreatePipeline(true, state, R"( #version 450 void main() { @@ -178,7 +178,7 @@ TEST_F(InputStateTest, SetInputStrideOutOfBounds) { )"); // Test input stride OOB - state.cInputs[0].stride = kMaxVertexInputStride + 1; + state.cBuffers[0].stride = kMaxVertexBufferStride + 1; CreatePipeline(false, state, R"( #version 450 void main() { @@ -188,10 +188,10 @@ TEST_F(InputStateTest, SetInputStrideOutOfBounds) { } // Test that we cannot set an already set attribute -TEST_F(InputStateTest, AlreadySetAttribute) { +TEST_F(VertexInputTest, AlreadySetAttribute) { // Control case, setting last attribute - utils::ComboInputStateDescriptor state; - state.numInputs = 1; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; state.numAttributes = 1; CreatePipeline(true, state, R"( #version 450 @@ -211,10 +211,10 @@ TEST_F(InputStateTest, AlreadySetAttribute) { } // Check out of bounds condition on attribute shader location -TEST_F(InputStateTest, SetAttributeLocationOutOfBounds) { +TEST_F(VertexInputTest, SetAttributeLocationOutOfBounds) { // Control case, setting last attribute shader location - utils::ComboInputStateDescriptor state; - state.numInputs = 1; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; state.numAttributes = 1; state.cAttributes[0].shaderLocation = kMaxVertexAttributes - 1; CreatePipeline(true, state, R"( @@ -235,10 +235,10 @@ TEST_F(InputStateTest, SetAttributeLocationOutOfBounds) { } // Check attribute offset out of bounds -TEST_F(InputStateTest, SetAttributeOffsetOutOfBounds) { +TEST_F(VertexInputTest, SetAttributeOffsetOutOfBounds) { // Control case, setting max attribute offset for FloatR32 vertex format - utils::ComboInputStateDescriptor state; - state.numInputs = 1; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; state.numAttributes = 1; state.cAttributes[0].offset = kMaxVertexAttributeEnd - sizeof(dawn::VertexFormat::Float); CreatePipeline(true, state, R"( @@ -259,9 +259,9 @@ TEST_F(InputStateTest, SetAttributeOffsetOutOfBounds) { } // Check attribute offset overflow -TEST_F(InputStateTest, SetAttributeOffsetOverflow) { - utils::ComboInputStateDescriptor state; - state.numInputs = 1; +TEST_F(VertexInputTest, SetAttributeOffsetOverflow) { + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; state.numAttributes = 1; state.cAttributes[0].offset = std::numeric_limits::max(); CreatePipeline(false, state, R"( @@ -273,10 +273,10 @@ TEST_F(InputStateTest, SetAttributeOffsetOverflow) { } // Check that all attributes must be backed by an input -TEST_F(InputStateTest, RequireInputForAttribute) { +TEST_F(VertexInputTest, RequireInputForAttribute) { // Control case - utils::ComboInputStateDescriptor state; - state.numInputs = 1; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; state.numAttributes = 1; CreatePipeline(true, state, R"( #version 450 @@ -296,10 +296,10 @@ TEST_F(InputStateTest, RequireInputForAttribute) { } // Check OOB checks for an attribute's input -TEST_F(InputStateTest, SetAttributeOOBCheckForInputs) { +TEST_F(VertexInputTest, SetAttributeOOBCheckForInputs) { // Control case - utils::ComboInputStateDescriptor state; - state.numInputs = 1; + utils::ComboVertexInputDescriptor state; + state.numBuffers = 1; state.numAttributes = 1; CreatePipeline(true, state, R"( #version 450 diff --git a/src/tests/unittests/wire/WireArgumentTests.cpp b/src/tests/unittests/wire/WireArgumentTests.cpp index 965ab2c34c..c63435a15d 100644 --- a/src/tests/unittests/wire/WireArgumentTests.cpp +++ b/src/tests/unittests/wire/WireArgumentTests.cpp @@ -97,13 +97,13 @@ TEST_F(WireArgumentTests, CStringArgument) { colorStateDescriptor.writeMask = DAWN_COLOR_WRITE_MASK_ALL; // Create the input state - DawnInputStateDescriptor inputState; - inputState.nextInChain = nullptr; - inputState.indexFormat = DAWN_INDEX_FORMAT_UINT32; - inputState.numInputs = 0; - inputState.inputs = nullptr; - inputState.numAttributes = 0; - inputState.attributes = nullptr; + DawnVertexInputDescriptor vertexInput; + vertexInput.nextInChain = nullptr; + vertexInput.indexFormat = DAWN_INDEX_FORMAT_UINT32; + vertexInput.numBuffers = 0; + vertexInput.buffers = nullptr; + vertexInput.numAttributes = 0; + vertexInput.attributes = nullptr; // Create the rasterization state DawnRasterizationStateDescriptor rasterizationState; @@ -162,7 +162,7 @@ TEST_F(WireArgumentTests, CStringArgument) { pipelineDescriptor.sampleCount = 1; pipelineDescriptor.layout = layout; - pipelineDescriptor.inputState = &inputState; + pipelineDescriptor.vertexInput = &vertexInput; pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; pipelineDescriptor.rasterizationState = &rasterizationState; pipelineDescriptor.depthStencilState = &depthStencilState; diff --git a/src/tests/unittests/wire/WireOptionalTests.cpp b/src/tests/unittests/wire/WireOptionalTests.cpp index 02a32510e0..5a94a29768 100644 --- a/src/tests/unittests/wire/WireOptionalTests.cpp +++ b/src/tests/unittests/wire/WireOptionalTests.cpp @@ -87,13 +87,13 @@ TEST_F(WireOptionalTests, OptionalStructPointer) { colorStateDescriptor.writeMask = DAWN_COLOR_WRITE_MASK_ALL; // Create the input state - DawnInputStateDescriptor inputState; - inputState.nextInChain = nullptr; - inputState.indexFormat = DAWN_INDEX_FORMAT_UINT32; - inputState.numInputs = 0; - inputState.inputs = nullptr; - inputState.numAttributes = 0; - inputState.attributes = nullptr; + DawnVertexInputDescriptor vertexInput; + vertexInput.nextInChain = nullptr; + vertexInput.indexFormat = DAWN_INDEX_FORMAT_UINT32; + vertexInput.numBuffers = 0; + vertexInput.buffers = nullptr; + vertexInput.numAttributes = 0; + vertexInput.attributes = nullptr; // Create the rasterization state DawnRasterizationStateDescriptor rasterizationState; @@ -152,7 +152,7 @@ TEST_F(WireOptionalTests, OptionalStructPointer) { pipelineDescriptor.sampleCount = 1; pipelineDescriptor.layout = layout; - pipelineDescriptor.inputState = &inputState; + pipelineDescriptor.vertexInput = &vertexInput; pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; pipelineDescriptor.rasterizationState = &rasterizationState; diff --git a/src/utils/ComboRenderPipelineDescriptor.cpp b/src/utils/ComboRenderPipelineDescriptor.cpp index e0a1a1a041..ee0a3d5787 100644 --- a/src/utils/ComboRenderPipelineDescriptor.cpp +++ b/src/utils/ComboRenderPipelineDescriptor.cpp @@ -18,21 +18,21 @@ namespace utils { - ComboInputStateDescriptor::ComboInputStateDescriptor() { - dawn::InputStateDescriptor* descriptor = this; + ComboVertexInputDescriptor::ComboVertexInputDescriptor() { + dawn::VertexInputDescriptor* descriptor = this; descriptor->indexFormat = dawn::IndexFormat::Uint32; - // Fill the default values for vertexInput. - descriptor->numInputs = 0; - dawn::VertexInputDescriptor vertexInput; - vertexInput.inputSlot = 0; - vertexInput.stride = 0; - vertexInput.stepMode = dawn::InputStepMode::Vertex; - for (uint32_t i = 0; i < kMaxVertexInputs; ++i) { - cInputs[i] = vertexInput; + // Fill the default values for vertexBuffer. + descriptor->numBuffers = 0; + dawn::VertexBufferDescriptor vertexBuffer; + vertexBuffer.inputSlot = 0; + vertexBuffer.stride = 0; + vertexBuffer.stepMode = dawn::InputStepMode::Vertex; + for (uint32_t i = 0; i < kMaxVertexBuffers; ++i) { + cBuffers[i] = vertexBuffer; } - descriptor->inputs = &cInputs[0]; + descriptor->buffers = &cBuffers[0]; // Fill the default values for vertexAttribute. descriptor->numAttributes = 0; @@ -66,7 +66,7 @@ namespace utils { } // Set defaults for the input state descriptors. - descriptor->inputState = &cInputState; + descriptor->vertexInput = &cVertexInput; // Set defaults for the rasterization state descriptor. { diff --git a/src/utils/ComboRenderPipelineDescriptor.h b/src/utils/ComboRenderPipelineDescriptor.h index 69ab6883e7..8be63d23e0 100644 --- a/src/utils/ComboRenderPipelineDescriptor.h +++ b/src/utils/ComboRenderPipelineDescriptor.h @@ -23,11 +23,11 @@ namespace utils { - class ComboInputStateDescriptor : public dawn::InputStateDescriptor { + class ComboVertexInputDescriptor : public dawn::VertexInputDescriptor { public: - ComboInputStateDescriptor(); + ComboVertexInputDescriptor(); - std::array cInputs; + std::array cBuffers; std::array cAttributes; }; @@ -38,7 +38,7 @@ namespace utils { dawn::PipelineStageDescriptor cVertexStage; dawn::PipelineStageDescriptor cFragmentStage; - ComboInputStateDescriptor cInputState; + ComboVertexInputDescriptor cVertexInput; dawn::RasterizationStateDescriptor cRasterizationState; std::array cColorStates; dawn::DepthStencilStateDescriptor cDepthStencilState;