Wire: Add support from optional struct/integer const*
This will allow implementing the following part of the WebGPU IDL using a nullable pointer instead of an extra hasDepthStencilState boolean: partial interface GPURenderPipelineDescriptor { GPUDepthStencilStateDescriptor? depthStencilState; }; BUG=dawn:102 Change-Id: Iae709831ad857fcef073f18753ab39567a8797da Reviewed-on: https://dawn-review.googlesource.com/c/4500 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Reviewed-by: Yunchao He <yunchao.he@intel.com>
This commit is contained in:
parent
bb5696bcd3
commit
f872e6924c
|
@ -863,7 +863,7 @@
|
|||
{"name": "primitive topology", "type": "primitive topology"},
|
||||
{"name": "attachments state", "type": "attachments state descriptor", "annotation": "const*"},
|
||||
{"name": "sample count", "type": "uint32_t"},
|
||||
{"name": "depth stencil state", "type": "depth stencil state descriptor", "annotation": "const*"},
|
||||
{"name": "depth stencil state", "type": "depth stencil state descriptor", "annotation": "const*", "optional": true},
|
||||
{"name": "num blend states", "type": "uint32_t"},
|
||||
{"name": "blend states", "type": "blend state descriptor", "annotation": "const*", "length": "num blend states"}
|
||||
]
|
||||
|
|
|
@ -105,6 +105,10 @@
|
|||
{% for member in members if member.length == "strlen" %}
|
||||
size_t {{as_varName(member.name)}}Strlen;
|
||||
{% endfor %}
|
||||
|
||||
{% for member in members if member.annotation != "value" and member.type.category != "object" %}
|
||||
bool has_{{as_varName(member.name)}};
|
||||
{% endfor %}
|
||||
};
|
||||
|
||||
//* Returns the required transfer size for `record` in addition to the transfer structure.
|
||||
|
@ -120,6 +124,9 @@
|
|||
|
||||
//* Gather how much space will be needed for pointer members.
|
||||
{% for member in members if member.annotation != "value" and member.length != "strlen" %}
|
||||
{% if member.type.category != "object" and member.optional %}
|
||||
if (record.{{as_varName(member.name)}} != nullptr)
|
||||
{% endif %}
|
||||
{
|
||||
size_t memberLength = {{member_length(member, "record.")}};
|
||||
result += memberLength * {{member_transfer_sizeof(member)}};
|
||||
|
@ -176,6 +183,12 @@
|
|||
//* Allocate space and write the non-value arguments in it.
|
||||
{% for member in members if member.annotation != "value" and member.length != "strlen" %}
|
||||
{% set memberName = as_varName(member.name) %}
|
||||
|
||||
{% if member.type.category != "object" and member.optional %}
|
||||
bool has_{{memberName}} = record.{{memberName}} != nullptr;
|
||||
transfer->has_{{memberName}} = has_{{memberName}};
|
||||
if (has_{{memberName}})
|
||||
{% endif %}
|
||||
{
|
||||
size_t memberLength = {{member_length(member, "record.")}};
|
||||
auto memberBuffer = reinterpret_cast<{{member_transfer_type(member)}}*>(*buffer);
|
||||
|
@ -277,6 +290,12 @@
|
|||
//* Get extra buffer data, and copy pointed to values in extra allocated space.
|
||||
{% for member in members if member.annotation != "value" and member.length != "strlen" %}
|
||||
{% set memberName = as_varName(member.name) %}
|
||||
|
||||
{% if member.type.category != "object" and member.optional %}
|
||||
bool has_{{memberName}} = transfer->has_{{memberName}};
|
||||
record->{{memberName}} = nullptr;
|
||||
if (has_{{memberName}})
|
||||
{% endif %}
|
||||
{
|
||||
size_t memberLength = {{member_length(member, "record->")}};
|
||||
auto memberBuffer = reinterpret_cast<const {{member_transfer_type(member)}}*>(buffer);
|
||||
|
|
|
@ -439,6 +439,141 @@ TEST_F(WireTests, CStringArgument) {
|
|||
FlushClient();
|
||||
}
|
||||
|
||||
// Test that the wire is able to send optional pointers to structures
|
||||
TEST_F(WireTests, OptionalStructPointer) {
|
||||
// Create shader module
|
||||
dawnShaderModuleDescriptor vertexDescriptor;
|
||||
vertexDescriptor.nextInChain = nullptr;
|
||||
vertexDescriptor.codeSize = 0;
|
||||
dawnShaderModule vsModule = dawnDeviceCreateShaderModule(device, &vertexDescriptor);
|
||||
dawnShaderModule apiVsModule = api.GetNewShaderModule();
|
||||
EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _))
|
||||
.WillOnce(Return(apiVsModule));
|
||||
|
||||
// Create the blend state descriptor
|
||||
dawnBlendDescriptor blendDescriptor;
|
||||
blendDescriptor.operation = DAWN_BLEND_OPERATION_ADD;
|
||||
blendDescriptor.srcFactor = DAWN_BLEND_FACTOR_ONE;
|
||||
blendDescriptor.dstFactor = DAWN_BLEND_FACTOR_ONE;
|
||||
dawnBlendStateDescriptor blendStateDescriptor;
|
||||
blendStateDescriptor.nextInChain = nullptr;
|
||||
blendStateDescriptor.alphaBlend = blendDescriptor;
|
||||
blendStateDescriptor.colorBlend = blendDescriptor;
|
||||
blendStateDescriptor.colorWriteMask = DAWN_COLOR_WRITE_MASK_ALL;
|
||||
|
||||
// Create the input state
|
||||
dawnInputStateBuilder inputStateBuilder = dawnDeviceCreateInputStateBuilder(device);
|
||||
dawnInputStateBuilder apiInputStateBuilder = api.GetNewInputStateBuilder();
|
||||
EXPECT_CALL(api, DeviceCreateInputStateBuilder(apiDevice))
|
||||
.WillOnce(Return(apiInputStateBuilder));
|
||||
|
||||
dawnInputState inputState = dawnInputStateBuilderGetResult(inputStateBuilder);
|
||||
dawnInputState apiInputState = api.GetNewInputState();
|
||||
EXPECT_CALL(api, InputStateBuilderGetResult(apiInputStateBuilder))
|
||||
.WillOnce(Return(apiInputState));
|
||||
|
||||
// Create the depth-stencil state
|
||||
dawnStencilStateFaceDescriptor stencilFace;
|
||||
stencilFace.compare = DAWN_COMPARE_FUNCTION_ALWAYS;
|
||||
stencilFace.failOp = DAWN_STENCIL_OPERATION_KEEP;
|
||||
stencilFace.depthFailOp = DAWN_STENCIL_OPERATION_KEEP;
|
||||
stencilFace.passOp = DAWN_STENCIL_OPERATION_KEEP;
|
||||
|
||||
dawnDepthStencilStateDescriptor depthStencilState;
|
||||
depthStencilState.nextInChain = nullptr;
|
||||
depthStencilState.depthWriteEnabled = false;
|
||||
depthStencilState.depthCompare = DAWN_COMPARE_FUNCTION_ALWAYS;
|
||||
depthStencilState.stencilBack = stencilFace;
|
||||
depthStencilState.stencilFront = stencilFace;
|
||||
depthStencilState.stencilReadMask = 0xff;
|
||||
depthStencilState.stencilWriteMask = 0xff;
|
||||
|
||||
// Create the pipeline layout
|
||||
dawnPipelineLayoutDescriptor layoutDescriptor;
|
||||
layoutDescriptor.nextInChain = nullptr;
|
||||
layoutDescriptor.numBindGroupLayouts = 0;
|
||||
layoutDescriptor.bindGroupLayouts = nullptr;
|
||||
dawnPipelineLayout layout = dawnDeviceCreatePipelineLayout(device, &layoutDescriptor);
|
||||
dawnPipelineLayout apiLayout = api.GetNewPipelineLayout();
|
||||
EXPECT_CALL(api, DeviceCreatePipelineLayout(apiDevice, _))
|
||||
.WillOnce(Return(apiLayout));
|
||||
|
||||
// Create pipeline
|
||||
dawnRenderPipelineDescriptor pipelineDescriptor;
|
||||
pipelineDescriptor.nextInChain = nullptr;
|
||||
|
||||
dawnPipelineStageDescriptor vertexStage;
|
||||
vertexStage.nextInChain = nullptr;
|
||||
vertexStage.module = vsModule;
|
||||
vertexStage.entryPoint = "main";
|
||||
pipelineDescriptor.vertexStage = &vertexStage;
|
||||
|
||||
dawnPipelineStageDescriptor fragmentStage;
|
||||
fragmentStage.nextInChain = nullptr;
|
||||
fragmentStage.module = vsModule;
|
||||
fragmentStage.entryPoint = "main";
|
||||
pipelineDescriptor.fragmentStage = &fragmentStage;
|
||||
|
||||
dawnAttachmentsStateDescriptor attachmentsState;
|
||||
attachmentsState.nextInChain = nullptr;
|
||||
attachmentsState.numColorAttachments = 1;
|
||||
dawnAttachmentDescriptor colorAttachment = {nullptr, DAWN_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM};
|
||||
dawnAttachmentDescriptor* colorAttachmentPtr[] = {&colorAttachment};
|
||||
attachmentsState.colorAttachments = colorAttachmentPtr;
|
||||
attachmentsState.hasDepthStencilAttachment = false;
|
||||
// Even with hasDepthStencilAttachment = false, depthStencilAttachment must point to valid
|
||||
// data because we don't have optional substructures yet.
|
||||
attachmentsState.depthStencilAttachment = &colorAttachment;
|
||||
pipelineDescriptor.attachmentsState = &attachmentsState;
|
||||
|
||||
pipelineDescriptor.numBlendStates = 1;
|
||||
pipelineDescriptor.blendStates = &blendStateDescriptor;
|
||||
|
||||
pipelineDescriptor.sampleCount = 1;
|
||||
pipelineDescriptor.layout = layout;
|
||||
pipelineDescriptor.inputState = inputState;
|
||||
pipelineDescriptor.indexFormat = DAWN_INDEX_FORMAT_UINT32;
|
||||
pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
|
||||
// First case: depthStencilState is not null.
|
||||
pipelineDescriptor.depthStencilState = &depthStencilState;
|
||||
dawnDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
||||
EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, MatchesLambda([](const dawnRenderPipelineDescriptor* desc) -> bool {
|
||||
return desc->depthStencilState != nullptr &&
|
||||
desc->depthStencilState->nextInChain == nullptr &&
|
||||
desc->depthStencilState->depthWriteEnabled == false &&
|
||||
desc->depthStencilState->depthCompare == DAWN_COMPARE_FUNCTION_ALWAYS &&
|
||||
desc->depthStencilState->stencilBack.compare == DAWN_COMPARE_FUNCTION_ALWAYS &&
|
||||
desc->depthStencilState->stencilBack.failOp == DAWN_STENCIL_OPERATION_KEEP &&
|
||||
desc->depthStencilState->stencilBack.depthFailOp == DAWN_STENCIL_OPERATION_KEEP &&
|
||||
desc->depthStencilState->stencilBack.passOp == DAWN_STENCIL_OPERATION_KEEP &&
|
||||
desc->depthStencilState->stencilFront.compare == DAWN_COMPARE_FUNCTION_ALWAYS &&
|
||||
desc->depthStencilState->stencilFront.failOp == DAWN_STENCIL_OPERATION_KEEP &&
|
||||
desc->depthStencilState->stencilFront.depthFailOp == DAWN_STENCIL_OPERATION_KEEP &&
|
||||
desc->depthStencilState->stencilFront.passOp == DAWN_STENCIL_OPERATION_KEEP &&
|
||||
desc->depthStencilState->stencilReadMask == 0xff &&
|
||||
desc->depthStencilState->stencilWriteMask == 0xff;
|
||||
})))
|
||||
.WillOnce(Return(nullptr));
|
||||
|
||||
FlushClient();
|
||||
|
||||
// Second case: depthStencilState is null.
|
||||
pipelineDescriptor.depthStencilState = nullptr;
|
||||
dawnDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
||||
EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, MatchesLambda([](const dawnRenderPipelineDescriptor* desc) -> bool {
|
||||
return desc->depthStencilState == nullptr;
|
||||
})))
|
||||
.WillOnce(Return(nullptr));
|
||||
|
||||
EXPECT_CALL(api, ShaderModuleRelease(apiVsModule));
|
||||
EXPECT_CALL(api, InputStateBuilderRelease(apiInputStateBuilder));
|
||||
EXPECT_CALL(api, InputStateRelease(apiInputState));
|
||||
EXPECT_CALL(api, PipelineLayoutRelease(apiLayout));
|
||||
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test that the wire is able to send objects as value arguments
|
||||
TEST_F(WireTests, ObjectAsValueArgument) {
|
||||
// Create a RenderPassDescriptor
|
||||
|
|
Loading…
Reference in New Issue