mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-18 01:15:39 +00:00
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:
committed by
Commit Bot service account
parent
820a04b9ce
commit
eea2091068
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
DAWN_INSTANTIATE_TEST(VertexFormatTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);
|
||||
|
||||
494
src/tests/end2end/VertexInputTests.cpp
Normal file
494
src/tests/end2end/VertexInputTests.cpp
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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<uint32_t>::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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user