Make vertex input descriptor optional
Following WebGPU spec change at https://github.com/gpuweb/gpuweb/issues/378, vertexInput descriptor from GPURenderPipelineDescriptor should not be required anymore. BUG=dawn:22 Change-Id: I5d2500a758f44b7a7db2d2c23b359f1012221227 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10640 Commit-Queue: François Beaufort <beaufort.francois@gmail.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
18b2cb51d7
commit
13c472e196
|
@ -648,7 +648,7 @@
|
||||||
"extensible": true,
|
"extensible": true,
|
||||||
"members": [
|
"members": [
|
||||||
{"name": "index format", "type": "index format", "default": "uint32"},
|
{"name": "index format", "type": "index format", "default": "uint32"},
|
||||||
{"name": "buffer count", "type": "uint32_t"},
|
{"name": "buffer count", "type": "uint32_t", "default": 0},
|
||||||
{"name": "buffers", "type": "vertex buffer descriptor", "annotation": "const*", "length": "buffer count"}
|
{"name": "buffers", "type": "vertex buffer descriptor", "annotation": "const*", "length": "buffer count"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -1031,7 +1031,7 @@
|
||||||
{"name": "layout", "type": "pipeline layout"},
|
{"name": "layout", "type": "pipeline layout"},
|
||||||
{"name": "vertex stage", "type": "pipeline stage descriptor", "annotation": "const*"},
|
{"name": "vertex stage", "type": "pipeline stage descriptor", "annotation": "const*"},
|
||||||
{"name": "fragment stage", "type": "pipeline stage descriptor", "annotation": "const*", "optional": true},
|
{"name": "fragment stage", "type": "pipeline stage descriptor", "annotation": "const*", "optional": true},
|
||||||
{"name": "vertex input", "type": "vertex input descriptor", "annotation": "const*"},
|
{"name": "vertex input", "type": "vertex input descriptor", "annotation": "const*", "optional": true},
|
||||||
{"name": "primitive topology", "type": "primitive topology"},
|
{"name": "primitive topology", "type": "primitive topology"},
|
||||||
{"name": "rasterization state", "type": "rasterization state descriptor", "annotation": "const*", "optional": true},
|
{"name": "rasterization state", "type": "rasterization state descriptor", "annotation": "const*", "optional": true},
|
||||||
{"name": "sample count", "type": "uint32_t", "default": "1"},
|
{"name": "sample count", "type": "uint32_t", "default": "1"},
|
||||||
|
|
|
@ -272,17 +272,16 @@ namespace dawn_native {
|
||||||
|
|
||||||
DAWN_TRY(device->ValidateObject(descriptor->layout));
|
DAWN_TRY(device->ValidateObject(descriptor->layout));
|
||||||
|
|
||||||
if (descriptor->vertexInput == nullptr) {
|
|
||||||
return DAWN_VALIDATION_ERROR("Input state must not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(crbug.com/dawn/136): Support vertex-only pipelines.
|
// TODO(crbug.com/dawn/136): Support vertex-only pipelines.
|
||||||
if (descriptor->fragmentStage == nullptr) {
|
if (descriptor->fragmentStage == nullptr) {
|
||||||
return DAWN_VALIDATION_ERROR("Null fragment stage is not supported (yet)");
|
return DAWN_VALIDATION_ERROR("Null fragment stage is not supported (yet)");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::bitset<kMaxVertexAttributes> attributesSetMask;
|
std::bitset<kMaxVertexAttributes> attributesSetMask;
|
||||||
|
if (descriptor->vertexInput) {
|
||||||
DAWN_TRY(ValidateVertexInputDescriptor(descriptor->vertexInput, &attributesSetMask));
|
DAWN_TRY(ValidateVertexInputDescriptor(descriptor->vertexInput, &attributesSetMask));
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology));
|
DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology));
|
||||||
DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->vertexStage,
|
DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->vertexStage,
|
||||||
descriptor->layout, SingleShaderStage::Vertex));
|
descriptor->layout, SingleShaderStage::Vertex));
|
||||||
|
@ -358,7 +357,6 @@ namespace dawn_native {
|
||||||
: PipelineBase(device,
|
: PipelineBase(device,
|
||||||
descriptor->layout,
|
descriptor->layout,
|
||||||
dawn::ShaderStage::Vertex | dawn::ShaderStage::Fragment),
|
dawn::ShaderStage::Vertex | dawn::ShaderStage::Fragment),
|
||||||
mVertexInput(*descriptor->vertexInput),
|
|
||||||
mAttachmentState(device->GetOrCreateAttachmentState(descriptor)),
|
mAttachmentState(device->GetOrCreateAttachmentState(descriptor)),
|
||||||
mPrimitiveTopology(descriptor->primitiveTopology),
|
mPrimitiveTopology(descriptor->primitiveTopology),
|
||||||
mSampleMask(descriptor->sampleMask),
|
mSampleMask(descriptor->sampleMask),
|
||||||
|
@ -368,6 +366,12 @@ namespace dawn_native {
|
||||||
mFragmentModule(descriptor->fragmentStage->module),
|
mFragmentModule(descriptor->fragmentStage->module),
|
||||||
mFragmentEntryPoint(descriptor->fragmentStage->entryPoint),
|
mFragmentEntryPoint(descriptor->fragmentStage->entryPoint),
|
||||||
mIsBlueprint(blueprint) {
|
mIsBlueprint(blueprint) {
|
||||||
|
if (descriptor->vertexInput != nullptr) {
|
||||||
|
mVertexInput = *descriptor->vertexInput;
|
||||||
|
} else {
|
||||||
|
mVertexInput = VertexInputDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t slot = 0; slot < mVertexInput.bufferCount; ++slot) {
|
for (uint32_t slot = 0; slot < mVertexInput.bufferCount; ++slot) {
|
||||||
if (mVertexInput.buffers[slot].attributeCount == 0) {
|
if (mVertexInput.buffers[slot].attributeCount == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -518,3 +518,52 @@ DAWN_INSTANTIATE_TEST(VertexInputTest, D3D12Backend, MetalBackend, OpenGLBackend
|
||||||
// - Add checks for alignement of vertex buffers and attributes if needed
|
// - Add checks for alignement of vertex buffers and attributes if needed
|
||||||
// - Check for attribute narrowing
|
// - Check for attribute narrowing
|
||||||
// - Check that the input state and the pipeline vertex input types match
|
// - Check that the input state and the pipeline vertex input types match
|
||||||
|
|
||||||
|
class OptionalVertexInputTest : public DawnTest {};
|
||||||
|
|
||||||
|
// Test that vertex input is not required in render pipeline descriptor.
|
||||||
|
TEST_P(OptionalVertexInputTest, Basic) {
|
||||||
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 3, 3);
|
||||||
|
|
||||||
|
dawn::ShaderModule vsModule =
|
||||||
|
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||||
|
#version 450
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
})");
|
||||||
|
|
||||||
|
dawn::ShaderModule fsModule =
|
||||||
|
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||||
|
#version 450
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
void main() {
|
||||||
|
fragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
|
})");
|
||||||
|
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||||
|
descriptor.cVertexStage.module = vsModule;
|
||||||
|
descriptor.cFragmentStage.module = fsModule;
|
||||||
|
descriptor.primitiveTopology = dawn::PrimitiveTopology::PointList;
|
||||||
|
descriptor.vertexInput = nullptr;
|
||||||
|
|
||||||
|
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
|
||||||
|
|
||||||
|
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
{
|
||||||
|
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||||
|
pass.SetPipeline(pipeline);
|
||||||
|
pass.Draw(1, 1, 0, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn::CommandBuffer commands = encoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DAWN_INSTANTIATE_TEST(OptionalVertexInputTest,
|
||||||
|
D3D12Backend,
|
||||||
|
MetalBackend,
|
||||||
|
OpenGLBackend,
|
||||||
|
VulkanBackend);
|
||||||
|
|
|
@ -43,11 +43,31 @@ class RenderPipelineValidationTest : public ValidationTest {
|
||||||
|
|
||||||
// Test cases where creation should succeed
|
// Test cases where creation should succeed
|
||||||
TEST_F(RenderPipelineValidationTest, CreationSuccess) {
|
TEST_F(RenderPipelineValidationTest, CreationSuccess) {
|
||||||
|
{
|
||||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||||
descriptor.cVertexStage.module = vsModule;
|
descriptor.cVertexStage.module = vsModule;
|
||||||
descriptor.cFragmentStage.module = fsModule;
|
descriptor.cFragmentStage.module = fsModule;
|
||||||
|
|
||||||
device.CreateRenderPipeline(&descriptor);
|
device.CreateRenderPipeline(&descriptor);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Vertex input should be optional
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||||
|
descriptor.cVertexStage.module = vsModule;
|
||||||
|
descriptor.cFragmentStage.module = fsModule;
|
||||||
|
descriptor.vertexInput = nullptr;
|
||||||
|
|
||||||
|
device.CreateRenderPipeline(&descriptor);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Rasterization state should be optional
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||||
|
descriptor.cVertexStage.module = vsModule;
|
||||||
|
descriptor.cFragmentStage.module = fsModule;
|
||||||
|
descriptor.rasterizationState = nullptr;
|
||||||
|
|
||||||
|
device.CreateRenderPipeline(&descriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that at least one color state is required.
|
// Tests that at least one color state is required.
|
||||||
|
|
Loading…
Reference in New Issue