mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-23 06:53:32 +00:00
Bug: none Change-Id: I69904944db1d4c2fbcca74bb8b66b5a7524e76bb Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24642 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Kai Ninomiya <kainino@chromium.org>
362 lines
16 KiB
C++
362 lines
16 KiB
C++
// Copyright 2019 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/unittests/wire/WireTest.h"
|
|
|
|
#include "common/Constants.h"
|
|
|
|
#include <array>
|
|
|
|
using namespace testing;
|
|
using namespace dawn_wire;
|
|
|
|
class WireArgumentTests : public WireTest {
|
|
public:
|
|
WireArgumentTests() {
|
|
}
|
|
~WireArgumentTests() override = default;
|
|
};
|
|
|
|
// Test that the wire is able to send numerical values
|
|
TEST_F(WireArgumentTests, ValueArgument) {
|
|
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
|
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
|
|
wgpuComputePassEncoderDispatch(pass, 1, 2, 3);
|
|
|
|
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr)).WillOnce(Return(apiEncoder));
|
|
|
|
WGPUComputePassEncoder apiPass = api.GetNewComputePassEncoder();
|
|
EXPECT_CALL(api, CommandEncoderBeginComputePass(apiEncoder, nullptr)).WillOnce(Return(apiPass));
|
|
|
|
EXPECT_CALL(api, ComputePassEncoderDispatch(apiPass, 1, 2, 3)).Times(1);
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test that the wire is able to send arrays of numerical values
|
|
TEST_F(WireArgumentTests, ValueArrayArgument) {
|
|
// Create a bindgroup.
|
|
WGPUBindGroupLayoutDescriptor bglDescriptor = {};
|
|
bglDescriptor.entryCount = 0;
|
|
bglDescriptor.entries = nullptr;
|
|
|
|
WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device, &bglDescriptor);
|
|
WGPUBindGroupLayout apiBgl = api.GetNewBindGroupLayout();
|
|
EXPECT_CALL(api, DeviceCreateBindGroupLayout(apiDevice, _)).WillOnce(Return(apiBgl));
|
|
|
|
WGPUBindGroupDescriptor bindGroupDescriptor = {};
|
|
bindGroupDescriptor.layout = bgl;
|
|
bindGroupDescriptor.entryCount = 0;
|
|
bindGroupDescriptor.entries = nullptr;
|
|
|
|
WGPUBindGroup bindGroup = wgpuDeviceCreateBindGroup(device, &bindGroupDescriptor);
|
|
WGPUBindGroup apiBindGroup = api.GetNewBindGroup();
|
|
EXPECT_CALL(api, DeviceCreateBindGroup(apiDevice, _)).WillOnce(Return(apiBindGroup));
|
|
|
|
// Use the bindgroup in SetBindGroup that takes an array of value offsets.
|
|
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
|
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
|
|
|
|
std::array<uint32_t, 4> testOffsets = {0, 42, 0xDEAD'BEEFu, 0xFFFF'FFFFu};
|
|
wgpuComputePassEncoderSetBindGroup(pass, 0, bindGroup, testOffsets.size(), testOffsets.data());
|
|
|
|
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr)).WillOnce(Return(apiEncoder));
|
|
|
|
WGPUComputePassEncoder apiPass = api.GetNewComputePassEncoder();
|
|
EXPECT_CALL(api, CommandEncoderBeginComputePass(apiEncoder, nullptr)).WillOnce(Return(apiPass));
|
|
|
|
EXPECT_CALL(api, ComputePassEncoderSetBindGroup(
|
|
apiPass, 0, apiBindGroup, testOffsets.size(),
|
|
MatchesLambda([testOffsets](const uint32_t* offsets) -> bool {
|
|
for (size_t i = 0; i < testOffsets.size(); i++) {
|
|
if (offsets[i] != testOffsets[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
})));
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test that the wire is able to send C strings
|
|
TEST_F(WireArgumentTests, CStringArgument) {
|
|
// Create shader module
|
|
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
|
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
|
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
|
EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _)).WillOnce(Return(apiVsModule));
|
|
|
|
// Create the color state descriptor
|
|
WGPUBlendDescriptor blendDescriptor = {};
|
|
blendDescriptor.operation = WGPUBlendOperation_Add;
|
|
blendDescriptor.srcFactor = WGPUBlendFactor_One;
|
|
blendDescriptor.dstFactor = WGPUBlendFactor_One;
|
|
WGPUColorStateDescriptor colorStateDescriptor = {};
|
|
colorStateDescriptor.format = WGPUTextureFormat_RGBA8Unorm;
|
|
colorStateDescriptor.alphaBlend = blendDescriptor;
|
|
colorStateDescriptor.colorBlend = blendDescriptor;
|
|
colorStateDescriptor.writeMask = WGPUColorWriteMask_All;
|
|
|
|
// Create the input state
|
|
WGPUVertexStateDescriptor vertexState = {};
|
|
vertexState.indexFormat = WGPUIndexFormat_Uint32;
|
|
vertexState.vertexBufferCount = 0;
|
|
vertexState.vertexBuffers = nullptr;
|
|
|
|
// Create the rasterization state
|
|
WGPURasterizationStateDescriptor rasterizationState = {};
|
|
rasterizationState.frontFace = WGPUFrontFace_CCW;
|
|
rasterizationState.cullMode = WGPUCullMode_None;
|
|
rasterizationState.depthBias = 0;
|
|
rasterizationState.depthBiasSlopeScale = 0.0;
|
|
rasterizationState.depthBiasClamp = 0.0;
|
|
|
|
// Create the depth-stencil state
|
|
WGPUStencilStateFaceDescriptor stencilFace = {};
|
|
stencilFace.compare = WGPUCompareFunction_Always;
|
|
stencilFace.failOp = WGPUStencilOperation_Keep;
|
|
stencilFace.depthFailOp = WGPUStencilOperation_Keep;
|
|
stencilFace.passOp = WGPUStencilOperation_Keep;
|
|
|
|
WGPUDepthStencilStateDescriptor depthStencilState = {};
|
|
depthStencilState.format = WGPUTextureFormat_Depth24PlusStencil8;
|
|
depthStencilState.depthWriteEnabled = false;
|
|
depthStencilState.depthCompare = WGPUCompareFunction_Always;
|
|
depthStencilState.stencilBack = stencilFace;
|
|
depthStencilState.stencilFront = stencilFace;
|
|
depthStencilState.stencilReadMask = 0xff;
|
|
depthStencilState.stencilWriteMask = 0xff;
|
|
|
|
// Create the pipeline layout
|
|
WGPUPipelineLayoutDescriptor layoutDescriptor = {};
|
|
layoutDescriptor.bindGroupLayoutCount = 0;
|
|
layoutDescriptor.bindGroupLayouts = nullptr;
|
|
WGPUPipelineLayout layout = wgpuDeviceCreatePipelineLayout(device, &layoutDescriptor);
|
|
WGPUPipelineLayout apiLayout = api.GetNewPipelineLayout();
|
|
EXPECT_CALL(api, DeviceCreatePipelineLayout(apiDevice, _)).WillOnce(Return(apiLayout));
|
|
|
|
// Create pipeline
|
|
WGPURenderPipelineDescriptor pipelineDescriptor = {};
|
|
|
|
pipelineDescriptor.vertexStage.module = vsModule;
|
|
pipelineDescriptor.vertexStage.entryPoint = "main";
|
|
|
|
WGPUProgrammableStageDescriptor fragmentStage = {};
|
|
fragmentStage.module = vsModule;
|
|
fragmentStage.entryPoint = "main";
|
|
pipelineDescriptor.fragmentStage = &fragmentStage;
|
|
|
|
pipelineDescriptor.colorStateCount = 1;
|
|
pipelineDescriptor.colorStates = &colorStateDescriptor;
|
|
|
|
pipelineDescriptor.sampleCount = 1;
|
|
pipelineDescriptor.sampleMask = 0xFFFFFFFF;
|
|
pipelineDescriptor.alphaToCoverageEnabled = false;
|
|
pipelineDescriptor.layout = layout;
|
|
pipelineDescriptor.vertexState = &vertexState;
|
|
pipelineDescriptor.primitiveTopology = WGPUPrimitiveTopology_TriangleList;
|
|
pipelineDescriptor.rasterizationState = &rasterizationState;
|
|
pipelineDescriptor.depthStencilState = &depthStencilState;
|
|
|
|
wgpuDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
|
|
|
WGPURenderPipeline apiDummyPipeline = api.GetNewRenderPipeline();
|
|
EXPECT_CALL(api,
|
|
DeviceCreateRenderPipeline(
|
|
apiDevice, MatchesLambda([](const WGPURenderPipelineDescriptor* desc) -> bool {
|
|
return desc->vertexStage.entryPoint == std::string("main");
|
|
})))
|
|
.WillOnce(Return(apiDummyPipeline));
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test that the wire is able to send objects as value arguments
|
|
TEST_F(WireArgumentTests, ObjectAsValueArgument) {
|
|
WGPUCommandEncoder cmdBufEncoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
|
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr)).WillOnce(Return(apiEncoder));
|
|
|
|
WGPUBufferDescriptor descriptor = {};
|
|
descriptor.size = 8;
|
|
descriptor.usage =
|
|
static_cast<WGPUBufferUsage>(WGPUBufferUsage_CopySrc | WGPUBufferUsage_CopyDst);
|
|
|
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
|
|
.WillOnce(Return(apiBuffer))
|
|
.RetiresOnSaturation();
|
|
|
|
wgpuCommandEncoderCopyBufferToBuffer(cmdBufEncoder, buffer, 0, buffer, 4, 4);
|
|
EXPECT_CALL(api, CommandEncoderCopyBufferToBuffer(apiEncoder, apiBuffer, 0, apiBuffer, 4, 4));
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test that the wire is able to send array of objects
|
|
TEST_F(WireArgumentTests, ObjectsAsPointerArgument) {
|
|
WGPUCommandBuffer cmdBufs[2];
|
|
WGPUCommandBuffer apiCmdBufs[2];
|
|
|
|
// Create two command buffers we need to use a GMock sequence otherwise the order of the
|
|
// CreateCommandEncoder might be swapped since they are equivalent in term of matchers
|
|
Sequence s;
|
|
for (int i = 0; i < 2; ++i) {
|
|
WGPUCommandEncoder cmdBufEncoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
|
cmdBufs[i] = wgpuCommandEncoderFinish(cmdBufEncoder, nullptr);
|
|
|
|
WGPUCommandEncoder apiCmdBufEncoder = api.GetNewCommandEncoder();
|
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
|
.InSequence(s)
|
|
.WillOnce(Return(apiCmdBufEncoder));
|
|
|
|
apiCmdBufs[i] = api.GetNewCommandBuffer();
|
|
EXPECT_CALL(api, CommandEncoderFinish(apiCmdBufEncoder, nullptr))
|
|
.WillOnce(Return(apiCmdBufs[i]));
|
|
}
|
|
|
|
// Submit command buffer and check we got a call with both API-side command buffers
|
|
wgpuQueueSubmit(queue, 2, cmdBufs);
|
|
|
|
EXPECT_CALL(
|
|
api, QueueSubmit(apiQueue, 2, MatchesLambda([=](const WGPUCommandBuffer* cmdBufs) -> bool {
|
|
return cmdBufs[0] == apiCmdBufs[0] && cmdBufs[1] == apiCmdBufs[1];
|
|
})));
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test that the wire is able to send structures that contain pure values (non-objects)
|
|
TEST_F(WireArgumentTests, StructureOfValuesArgument) {
|
|
WGPUSamplerDescriptor descriptor = {};
|
|
descriptor.magFilter = WGPUFilterMode_Linear;
|
|
descriptor.minFilter = WGPUFilterMode_Nearest;
|
|
descriptor.mipmapFilter = WGPUFilterMode_Linear;
|
|
descriptor.addressModeU = WGPUAddressMode_ClampToEdge;
|
|
descriptor.addressModeV = WGPUAddressMode_Repeat;
|
|
descriptor.addressModeW = WGPUAddressMode_MirrorRepeat;
|
|
descriptor.lodMinClamp = kLodMin;
|
|
descriptor.lodMaxClamp = kLodMax;
|
|
descriptor.compare = WGPUCompareFunction_Never;
|
|
|
|
wgpuDeviceCreateSampler(device, &descriptor);
|
|
|
|
WGPUSampler apiDummySampler = api.GetNewSampler();
|
|
EXPECT_CALL(api, DeviceCreateSampler(
|
|
apiDevice, MatchesLambda([](const WGPUSamplerDescriptor* desc) -> bool {
|
|
return desc->nextInChain == nullptr &&
|
|
desc->magFilter == WGPUFilterMode_Linear &&
|
|
desc->minFilter == WGPUFilterMode_Nearest &&
|
|
desc->mipmapFilter == WGPUFilterMode_Linear &&
|
|
desc->addressModeU == WGPUAddressMode_ClampToEdge &&
|
|
desc->addressModeV == WGPUAddressMode_Repeat &&
|
|
desc->addressModeW == WGPUAddressMode_MirrorRepeat &&
|
|
desc->compare == WGPUCompareFunction_Never &&
|
|
desc->lodMinClamp == kLodMin && desc->lodMaxClamp == kLodMax;
|
|
})))
|
|
.WillOnce(Return(apiDummySampler));
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test that the wire is able to send structures that contain objects
|
|
TEST_F(WireArgumentTests, StructureOfObjectArrayArgument) {
|
|
WGPUBindGroupLayoutDescriptor bglDescriptor = {};
|
|
bglDescriptor.entryCount = 0;
|
|
bglDescriptor.entries = nullptr;
|
|
|
|
WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device, &bglDescriptor);
|
|
WGPUBindGroupLayout apiBgl = api.GetNewBindGroupLayout();
|
|
EXPECT_CALL(api, DeviceCreateBindGroupLayout(apiDevice, _)).WillOnce(Return(apiBgl));
|
|
|
|
WGPUPipelineLayoutDescriptor descriptor = {};
|
|
descriptor.bindGroupLayoutCount = 1;
|
|
descriptor.bindGroupLayouts = &bgl;
|
|
|
|
wgpuDeviceCreatePipelineLayout(device, &descriptor);
|
|
|
|
WGPUPipelineLayout apiDummyLayout = api.GetNewPipelineLayout();
|
|
EXPECT_CALL(api, DeviceCreatePipelineLayout(
|
|
apiDevice,
|
|
MatchesLambda([apiBgl](const WGPUPipelineLayoutDescriptor* desc) -> bool {
|
|
return desc->nextInChain == nullptr &&
|
|
desc->bindGroupLayoutCount == 1 &&
|
|
desc->bindGroupLayouts[0] == apiBgl;
|
|
})))
|
|
.WillOnce(Return(apiDummyLayout));
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test that the wire is able to send structures that contain objects
|
|
TEST_F(WireArgumentTests, StructureOfStructureArrayArgument) {
|
|
static constexpr int NUM_BINDINGS = 3;
|
|
WGPUBindGroupLayoutEntry entries[NUM_BINDINGS]{
|
|
{0, WGPUShaderStage_Vertex, WGPUBindingType_Sampler, false, 0, false,
|
|
WGPUTextureViewDimension_2D, WGPUTextureComponentType_Float, WGPUTextureFormat_RGBA8Unorm},
|
|
{1, WGPUShaderStage_Vertex, WGPUBindingType_SampledTexture, false, 0, false,
|
|
WGPUTextureViewDimension_2D, WGPUTextureComponentType_Float, WGPUTextureFormat_RGBA8Unorm},
|
|
{2, static_cast<WGPUShaderStage>(WGPUShaderStage_Vertex | WGPUShaderStage_Fragment),
|
|
WGPUBindingType_UniformBuffer, false, 0, false, WGPUTextureViewDimension_2D,
|
|
WGPUTextureComponentType_Float, WGPUTextureFormat_RGBA8Unorm},
|
|
};
|
|
WGPUBindGroupLayoutDescriptor bglDescriptor = {};
|
|
bglDescriptor.entryCount = NUM_BINDINGS;
|
|
bglDescriptor.entries = entries;
|
|
|
|
wgpuDeviceCreateBindGroupLayout(device, &bglDescriptor);
|
|
WGPUBindGroupLayout apiBgl = api.GetNewBindGroupLayout();
|
|
EXPECT_CALL(
|
|
api,
|
|
DeviceCreateBindGroupLayout(
|
|
apiDevice, MatchesLambda([entries](const WGPUBindGroupLayoutDescriptor* desc) -> bool {
|
|
for (int i = 0; i < NUM_BINDINGS; ++i) {
|
|
const auto& a = desc->entries[i];
|
|
const auto& b = entries[i];
|
|
if (a.binding != b.binding || a.visibility != b.visibility ||
|
|
a.type != b.type) {
|
|
return false;
|
|
}
|
|
}
|
|
return desc->nextInChain == nullptr && desc->entryCount == 3;
|
|
})))
|
|
.WillOnce(Return(apiBgl));
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test passing nullptr instead of objects - array of objects version
|
|
TEST_F(WireArgumentTests, DISABLED_NullptrInArray) {
|
|
WGPUBindGroupLayout nullBGL = nullptr;
|
|
|
|
WGPUPipelineLayoutDescriptor descriptor = {};
|
|
descriptor.bindGroupLayoutCount = 1;
|
|
descriptor.bindGroupLayouts = &nullBGL;
|
|
|
|
wgpuDeviceCreatePipelineLayout(device, &descriptor);
|
|
EXPECT_CALL(api,
|
|
DeviceCreatePipelineLayout(
|
|
apiDevice, MatchesLambda([](const WGPUPipelineLayoutDescriptor* desc) -> bool {
|
|
return desc->nextInChain == nullptr && desc->bindGroupLayoutCount == 1 &&
|
|
desc->bindGroupLayouts[0] == nullptr;
|
|
})))
|
|
.WillOnce(Return(nullptr));
|
|
|
|
FlushClient();
|
|
}
|