mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-06 06:33:30 +00:00
Record zero-attribute vertex buffer when creating render pipeline
Currently Dawn ignores all zero-attribute vertex buffer in the given pipeline descriptor when creating RenderPipelineBase because zero-attribute vertex buffer is treated as unused slot, however the spec doesn't state that zero-attribute vertex buffer should be ignored. To support zero-attribute vertex buffer, this commit has the following changes. 1. Add VertexBufferNotUsed enum value to wgpu::VertexStepMode to represent unused slots 2. Ignore VertexBufferNotUsed step mode buffers when creating RenderPipelineBase and add tests to check it 3. Record zero-attribute vertex buffers when creating RenderPipelineBase and add tests to check it 4. Fix VertexStateTest::LastAllowedVertexBuffer broken by the above changes Temporarily we set the enum value of wgpu::VertexStepMode::VertexBufferNotUsed to 0 to pass the CTS tests because currently empty vertex buffer slots step mode can be zero-initialized. We will make a CL to Blink to explicitly set wgpu::VertexStepMode::VertexBufferNotUsed for empty slots and change the enum value to 2. Bug: dawn:1000 Change-Id: Ibd4ab87f2c922e8e460f2311547f13d58f1d5611 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/89340 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Takahiro <hogehoge@gachapin.jp>
This commit is contained in:
parent
a09b0dbd83
commit
d42a809e8c
@ -1479,8 +1479,9 @@
|
|||||||
"vertex step mode": {
|
"vertex step mode": {
|
||||||
"category": "enum",
|
"category": "enum",
|
||||||
"values": [
|
"values": [
|
||||||
{"value": 0, "name": "vertex"},
|
{"value": 0, "name": "vertex buffer not used"},
|
||||||
{"value": 1, "name": "instance"}
|
{"value": 1, "name": "vertex"},
|
||||||
|
{"value": 2, "name": "instance"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"load op": {
|
"load op": {
|
||||||
|
@ -498,7 +498,8 @@ RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
|
|||||||
mVertexBufferCount = descriptor->vertex.bufferCount;
|
mVertexBufferCount = descriptor->vertex.bufferCount;
|
||||||
const VertexBufferLayout* buffers = descriptor->vertex.buffers;
|
const VertexBufferLayout* buffers = descriptor->vertex.buffers;
|
||||||
for (uint8_t slot = 0; slot < mVertexBufferCount; ++slot) {
|
for (uint8_t slot = 0; slot < mVertexBufferCount; ++slot) {
|
||||||
if (buffers[slot].attributeCount == 0) {
|
// Skip unused slots
|
||||||
|
if (buffers[slot].stepMode == wgpu::VertexStepMode::VertexBufferNotUsed) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,8 +112,9 @@ tint::transform::VertexStepMode ToTintVertexStepMode(wgpu::VertexStepMode mode)
|
|||||||
return tint::transform::VertexStepMode::kVertex;
|
return tint::transform::VertexStepMode::kVertex;
|
||||||
case wgpu::VertexStepMode::Instance:
|
case wgpu::VertexStepMode::Instance:
|
||||||
return tint::transform::VertexStepMode::kInstance;
|
return tint::transform::VertexStepMode::kInstance;
|
||||||
|
case wgpu::VertexStepMode::VertexBufferNotUsed:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<SingleShaderStage> TintPipelineStageToShaderStage(tint::ast::PipelineStage stage) {
|
ResultOrError<SingleShaderStage> TintPipelineStageToShaderStage(tint::ast::PipelineStage stage) {
|
||||||
|
@ -106,6 +106,8 @@ D3D12_INPUT_CLASSIFICATION VertexStepModeFunction(wgpu::VertexStepMode mode) {
|
|||||||
return D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
return D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
||||||
case wgpu::VertexStepMode::Instance:
|
case wgpu::VertexStepMode::Instance:
|
||||||
return D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
|
return D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
|
||||||
|
case wgpu::VertexStepMode::VertexBufferNotUsed:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,8 @@ MTLVertexStepFunction VertexStepModeFunction(wgpu::VertexStepMode mode) {
|
|||||||
return MTLVertexStepFunctionPerVertex;
|
return MTLVertexStepFunctionPerVertex;
|
||||||
case wgpu::VertexStepMode::Instance:
|
case wgpu::VertexStepMode::Instance:
|
||||||
return MTLVertexStepFunctionPerInstance;
|
return MTLVertexStepFunctionPerInstance;
|
||||||
|
case wgpu::VertexStepMode::VertexBufferNotUsed:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +276,8 @@ void RenderPipeline::CreateVAOForVertexState() {
|
|||||||
case wgpu::VertexStepMode::Instance:
|
case wgpu::VertexStepMode::Instance:
|
||||||
gl.VertexAttribDivisor(glAttrib, 1);
|
gl.VertexAttribDivisor(glAttrib, 1);
|
||||||
break;
|
break;
|
||||||
|
case wgpu::VertexStepMode::VertexBufferNotUsed:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,9 @@ VkVertexInputRate VulkanInputRate(wgpu::VertexStepMode stepMode) {
|
|||||||
return VK_VERTEX_INPUT_RATE_VERTEX;
|
return VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
case wgpu::VertexStepMode::Instance:
|
case wgpu::VertexStepMode::Instance:
|
||||||
return VK_VERTEX_INPUT_RATE_INSTANCE;
|
return VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||||
|
case wgpu::VertexStepMode::VertexBufferNotUsed:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VkFormat VulkanVertexFormat(wgpu::VertexFormat format) {
|
VkFormat VulkanVertexFormat(wgpu::VertexFormat format) {
|
||||||
|
@ -550,6 +550,10 @@ TEST_P(VertexStateTest, LastAllowedVertexBuffer) {
|
|||||||
vertexState.cAttributes[0].offset = 0;
|
vertexState.cAttributes[0].offset = 0;
|
||||||
vertexState.cAttributes[0].format = VertexFormat::Float32x4;
|
vertexState.cAttributes[0].format = VertexFormat::Float32x4;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < kBufferIndex; i++) {
|
||||||
|
vertexState.cVertexBuffers[i].stepMode = VertexStepMode::VertexBufferNotUsed;
|
||||||
|
}
|
||||||
|
|
||||||
wgpu::RenderPipeline pipeline =
|
wgpu::RenderPipeline pipeline =
|
||||||
MakeTestPipeline(vertexState, 1, {{0, VertexFormat::Float32x4, VertexStepMode::Vertex}});
|
MakeTestPipeline(vertexState, 1, {{0, VertexFormat::Float32x4, VertexStepMode::Vertex}});
|
||||||
|
|
||||||
|
@ -440,6 +440,50 @@ TEST_F(DrawVertexAndIndexBufferOOBValidationTests, DrawVertexBufferOutOfBoundWit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify zero-attribute vertex buffer OOB for non-instanced Draw are caught in command encoder
|
||||||
|
TEST_F(DrawVertexAndIndexBufferOOBValidationTests, ZeroAttribute) {
|
||||||
|
// Create a render pipeline with zero-attribute vertex buffer description
|
||||||
|
wgpu::RenderPipeline pipeline =
|
||||||
|
CreateRenderPipelineWithBufferDesc({{kFloat32x4Stride, wgpu::VertexStepMode::Vertex, {}}});
|
||||||
|
|
||||||
|
wgpu::Buffer vertexBuffer = CreateBuffer(3 * kFloat32x4Stride);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Valid
|
||||||
|
VertexBufferList vertexBufferList = {{0, vertexBuffer, 0, wgpu::kWholeSize}};
|
||||||
|
TestRenderPassDraw(pipeline, vertexBufferList, 3, 1, 0, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// OOB
|
||||||
|
VertexBufferList vertexBufferList = {{0, vertexBuffer, 0, 0}};
|
||||||
|
TestRenderPassDraw(pipeline, vertexBufferList, 3, 1, 0, 0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify vertex buffers don't need to be set to unused (hole) slots for Draw
|
||||||
|
TEST_F(DrawVertexAndIndexBufferOOBValidationTests, UnusedSlots) {
|
||||||
|
// Set vertex buffer only to the second slot
|
||||||
|
wgpu::Buffer vertexBuffer = CreateBuffer(3 * kFloat32x4Stride);
|
||||||
|
VertexBufferList vertexBufferList = {{1, vertexBuffer, 0, wgpu::kWholeSize}};
|
||||||
|
|
||||||
|
{
|
||||||
|
// The first slot it unused so valid even if vertex buffer is not set to it.
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithBufferDesc(
|
||||||
|
{{0, wgpu::VertexStepMode::VertexBufferNotUsed, {}},
|
||||||
|
{kFloat32x4Stride, wgpu::VertexStepMode::Vertex, {}}});
|
||||||
|
TestRenderPassDraw(pipeline, vertexBufferList, 3, 1, 0, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// The first slot it used so invalid if vertex buffer is not set to it.
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithBufferDesc(
|
||||||
|
{{0, wgpu::VertexStepMode::Vertex, {}},
|
||||||
|
{kFloat32x4Stride, wgpu::VertexStepMode::Vertex, {}}});
|
||||||
|
TestRenderPassDraw(pipeline, vertexBufferList, 3, 1, 0, 0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Control case for DrawIndexed
|
// Control case for DrawIndexed
|
||||||
TEST_F(DrawVertexAndIndexBufferOOBValidationTests, DrawIndexedBasic) {
|
TEST_F(DrawVertexAndIndexBufferOOBValidationTests, DrawIndexedBasic) {
|
||||||
wgpu::RenderPipeline pipeline = CreateBasicRenderPipeline();
|
wgpu::RenderPipeline pipeline = CreateBasicRenderPipeline();
|
||||||
@ -556,6 +600,75 @@ TEST_F(DrawVertexAndIndexBufferOOBValidationTests, DrawIndexedVertexBufferOOB) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify zero-attribute instance step mode vertex buffer OOB for instanced DrawIndex
|
||||||
|
// are caught in command encoder
|
||||||
|
TEST_F(DrawVertexAndIndexBufferOOBValidationTests, DrawIndexedZeroAttribute) {
|
||||||
|
// Create a render pipeline with a vertex step mode and a zero-attribute
|
||||||
|
// instance step mode vertex buffer description
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithBufferDesc(
|
||||||
|
{{kFloat32x4Stride, wgpu::VertexStepMode::Vertex, {{0, wgpu::VertexFormat::Float32x4}}},
|
||||||
|
{kFloat32x2Stride, wgpu::VertexStepMode::Instance, {}}});
|
||||||
|
|
||||||
|
// Build index buffer for 12 indexes
|
||||||
|
wgpu::Buffer indexBuffer = CreateBuffer(12 * sizeof(uint32_t), wgpu::BufferUsage::Index);
|
||||||
|
IndexBufferDesc indexBufferDesc = {indexBuffer, wgpu::IndexFormat::Uint32};
|
||||||
|
|
||||||
|
// Build vertex buffer for 3 vertices
|
||||||
|
wgpu::Buffer vertexBuffer = CreateBuffer(3 * kFloat32x4Stride);
|
||||||
|
|
||||||
|
// Build vertex buffer for 3 instances
|
||||||
|
wgpu::Buffer instanceBuffer = CreateBuffer(3 * kFloat32x2Stride);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Valid
|
||||||
|
VertexBufferList vertexBufferList = {{0, vertexBuffer, 0, wgpu::kWholeSize},
|
||||||
|
{1, vertexBuffer, 0, wgpu::kWholeSize}};
|
||||||
|
TestRenderPassDrawIndexed(pipeline, indexBufferDesc, vertexBufferList, 12, 3, 0, 0, 0,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// OOB
|
||||||
|
VertexBufferList vertexBufferList = {{0, vertexBuffer, 0, wgpu::kWholeSize},
|
||||||
|
{1, vertexBuffer, 0, 0}};
|
||||||
|
TestRenderPassDrawIndexed(pipeline, indexBufferDesc, vertexBufferList, 12, 3, 0, 0, 0,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify vertex buffers don't need to be set to unused (hole) slots for DrawIndexed
|
||||||
|
TEST_F(DrawVertexAndIndexBufferOOBValidationTests, DrawIndexedUnusedSlots) {
|
||||||
|
// Build index buffer
|
||||||
|
wgpu::Buffer indexBuffer = CreateBuffer(12 * sizeof(uint32_t), wgpu::BufferUsage::Index);
|
||||||
|
IndexBufferDesc indexBufferDesc = {indexBuffer, wgpu::IndexFormat::Uint32};
|
||||||
|
|
||||||
|
// Set vertex buffers only to the second and third slots
|
||||||
|
wgpu::Buffer vertexBuffer = CreateBuffer(3 * kFloat32x4Stride);
|
||||||
|
wgpu::Buffer instanceBuffer = CreateBuffer(3 * kFloat32x2Stride);
|
||||||
|
VertexBufferList vertexBufferList = {{1, vertexBuffer, 0, wgpu::kWholeSize},
|
||||||
|
{2, instanceBuffer, 0, wgpu::kWholeSize}};
|
||||||
|
|
||||||
|
{
|
||||||
|
// The first slot it unused so valid even if vertex buffer is not set to it.
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithBufferDesc(
|
||||||
|
{{0, wgpu::VertexStepMode::VertexBufferNotUsed, {}},
|
||||||
|
{kFloat32x4Stride, wgpu::VertexStepMode::Vertex, {}},
|
||||||
|
{kFloat32x2Stride, wgpu::VertexStepMode::Instance, {}}});
|
||||||
|
TestRenderPassDrawIndexed(pipeline, indexBufferDesc, vertexBufferList, 12, 3, 0, 0, 0,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// The first slot it used so invalid if vertex buffer is not set to it.
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithBufferDesc(
|
||||||
|
{{0, wgpu::VertexStepMode::Vertex, {}},
|
||||||
|
{kFloat32x4Stride, wgpu::VertexStepMode::Vertex, {}},
|
||||||
|
{kFloat32x2Stride, wgpu::VertexStepMode::Instance, {}}});
|
||||||
|
TestRenderPassDrawIndexed(pipeline, indexBufferDesc, vertexBufferList, 12, 3, 0, 0, 0,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify zero array stride vertex buffer OOB for Draw and DrawIndexed are caught in command encoder
|
// Verify zero array stride vertex buffer OOB for Draw and DrawIndexed are caught in command encoder
|
||||||
// This test only test cases that strideCount > 0. Cases of strideCount == 0 are tested in
|
// This test only test cases that strideCount > 0. Cases of strideCount == 0 are tested in
|
||||||
// ZeroStrideCountVertexBufferNeverOOB.
|
// ZeroStrideCountVertexBufferNeverOOB.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user