Render Pipeline Descriptorization -- Part I

This patch remove render pipeline builder and use descriptor to create render pipeline.
Sub-objects in descriptor will be removed in future.

Bug: dawn:4
Change-Id: I58dd569c7be42c2648311847b939c681189c2854
Reviewed-on: https://dawn-review.googlesource.com/c/2180
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Yan, Shaobo
2018-12-10 19:47:22 +00:00
committed by Commit Bot service account
parent 07df605a2b
commit a49242766a
51 changed files with 916 additions and 763 deletions

View File

@@ -318,24 +318,99 @@ TEST_F(WireTests, ValueArrayArgument) {
// Test that the wire is able to send C strings
TEST_F(WireTests, CStringArgument) {
// Create shader module
dawnShaderModuleDescriptor descriptor;
descriptor.nextInChain = nullptr;
descriptor.codeSize = 0;
dawnShaderModule shaderModule = dawnDeviceCreateShaderModule(device, &descriptor);
dawnShaderModule apiShaderModule = api.GetNewShaderModule();
dawnShaderModuleDescriptor vertexDescriptor;
vertexDescriptor.nextInChain = nullptr;
vertexDescriptor.codeSize = 0;
dawnShaderModule vsModule = dawnDeviceCreateShaderModule(device, &vertexDescriptor);
dawnShaderModule apiVsModule = api.GetNewShaderModule();
EXPECT_CALL(api, DeviceCreateShaderModule(apiDevice, _))
.WillOnce(Return(apiShaderModule));
.WillOnce(Return(apiVsModule));
// Create the blend state
dawnBlendStateBuilder blendStateBuilder = dawnDeviceCreateBlendStateBuilder(device);
dawnBlendStateBuilder apiBlendStateBuilder = api.GetNewBlendStateBuilder();
EXPECT_CALL(api, DeviceCreateBlendStateBuilder(apiDevice))
.WillOnce(Return(apiBlendStateBuilder));
dawnBlendState blendState = dawnBlendStateBuilderGetResult(blendStateBuilder);
dawnBlendState apiBlendState = api.GetNewBlendState();
EXPECT_CALL(api, BlendStateBuilderGetResult(apiBlendStateBuilder))
.WillOnce(Return(apiBlendState));
// 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
dawnDepthStencilStateBuilder depthStencilStateBuilder = dawnDeviceCreateDepthStencilStateBuilder(device);
dawnDepthStencilStateBuilder apiDepthStencilStateBuilder = api.GetNewDepthStencilStateBuilder();
EXPECT_CALL(api, DeviceCreateDepthStencilStateBuilder(apiDevice))
.WillOnce(Return(apiDepthStencilStateBuilder));
dawnDepthStencilState depthStencilState = dawnDepthStencilStateBuilderGetResult(depthStencilStateBuilder);
dawnDepthStencilState apiDepthStencilState = api.GetNewDepthStencilState();
EXPECT_CALL(api, DepthStencilStateBuilderGetResult(apiDepthStencilStateBuilder))
.WillOnce(Return(apiDepthStencilState));
// 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
dawnRenderPipelineBuilder pipelineBuilder = dawnDeviceCreateRenderPipelineBuilder(device);
dawnRenderPipelineBuilderSetStage(pipelineBuilder, DAWN_SHADER_STAGE_FRAGMENT, shaderModule, "my entry point");
dawnRenderPipelineDescriptor pipelineDescriptor;
pipelineDescriptor.nextInChain = nullptr;
dawnRenderPipelineBuilder apiPipelineBuilder = api.GetNewRenderPipelineBuilder();
EXPECT_CALL(api, DeviceCreateRenderPipelineBuilder(apiDevice))
.WillOnce(Return(apiPipelineBuilder));
dawnPipelineStageDescriptor vertexStage;
vertexStage.nextInChain = nullptr;
vertexStage.module = vsModule;
vertexStage.entryPoint = "main";
pipelineDescriptor.vertexStage = &vertexStage;
EXPECT_CALL(api, RenderPipelineBuilderSetStage(apiPipelineBuilder, DAWN_SHADER_STAGE_FRAGMENT, apiShaderModule, StrEq("my entry point")));
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};
attachmentsState.colorAttachments = &colorAttachment;
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 = &blendState;
pipelineDescriptor.sampleCount = 1;
pipelineDescriptor.layout = layout;
pipelineDescriptor.inputState = inputState;
pipelineDescriptor.indexFormat = DAWN_INDEX_FORMAT_UINT32;
pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
pipelineDescriptor.depthStencilState = depthStencilState;
dawnDeviceCreateRenderPipeline(device, &pipelineDescriptor);
EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, MatchesLambda([](const dawnRenderPipelineDescriptor* desc) -> bool {
return desc->vertexStage->entryPoint == std::string("main");
})))
.WillOnce(Return(nullptr));
FlushClient();
}

View File

@@ -14,15 +14,12 @@
#include "tests/unittests/validation/ValidationTest.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
// Maximums for Dawn, tests will start failing when this changes
static constexpr uint32_t kMaxVertexAttributes = 16u;
static constexpr uint32_t kMaxVertexInputs = 16u;
class InputStateTest : public ValidationTest {
protected:
dawn::RenderPipeline CreatePipeline(bool success, const dawn::InputState& inputState, std::string vertexSource) {
void CreatePipeline(bool success, const dawn::InputState& inputState, std::string vertexSource) {
DummyRenderPass renderpassData = CreateDummyRenderPass();
dawn::ShaderModule vsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vertexSource.c_str());
@@ -34,18 +31,18 @@ class InputStateTest : public ValidationTest {
}
)");
dawn::RenderPipelineBuilder builder;
if (success) {
builder = AssertWillBeSuccess(device.CreateRenderPipelineBuilder());
} else {
builder = AssertWillBeError(device.CreateRenderPipelineBuilder());
}
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.inputState = inputState;
descriptor.cColorAttachments[0].format =
renderpassData.attachmentFormat;
return builder.SetColorAttachmentFormat(0, renderpassData.attachmentFormat)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState)
.GetResult();
if (!success) {
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
} else {
device.CreateRenderPipeline(&descriptor);
}
}
};

View File

@@ -15,6 +15,7 @@
#include "tests/unittests/validation/ValidationTest.h"
#include "common/Constants.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
class RenderPipelineValidationTest : public ValidationTest {
@@ -24,12 +25,6 @@ class RenderPipelineValidationTest : public ValidationTest {
renderpass = CreateSimpleRenderPass();
pipelineLayout = utils::MakeBasicPipelineLayout(device, nullptr);
inputState = device.CreateInputStateBuilder().GetResult();
blendState = device.CreateBlendStateBuilder().GetResult();
vsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"(
#version 450
void main() {
@@ -45,167 +40,49 @@ class RenderPipelineValidationTest : public ValidationTest {
})");
}
dawn::RenderPipelineBuilder& AddDefaultStates(dawn::RenderPipelineBuilder&& builder) {
builder.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList);
return builder;
}
dawn::RenderPassDescriptor renderpass;
dawn::ShaderModule vsModule;
dawn::ShaderModule fsModule;
dawn::InputState inputState;
dawn::BlendState blendState;
dawn::PipelineLayout pipelineLayout;
};
// Test cases where creation should succeed
TEST_F(RenderPipelineValidationTest, CreationSuccess) {
AddDefaultStates(AssertWillBeSuccess(device.CreateRenderPipelineBuilder()))
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
AddDefaultStates(AssertWillBeSuccess(device.CreateRenderPipelineBuilder()))
.SetInputState(inputState)
.GetResult();
AddDefaultStates(AssertWillBeSuccess(device.CreateRenderPipelineBuilder()))
.SetColorAttachmentBlendState(0, blendState)
.GetResult();
}
// Test creation failure when properties are missing
TEST_F(RenderPipelineValidationTest, CreationMissingProperty) {
// Vertex stage not set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.GetResult();
}
// Fragment stage not set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.GetResult();
}
// No attachment set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.GetResult();
}
device.CreateRenderPipeline(&descriptor);
}
TEST_F(RenderPipelineValidationTest, BlendState) {
// Fails because blend state is set on a nonexistent color attachment
{
// This one succeeds because attachment 0 is the color attachment
AssertWillBeSuccess(device.CreateRenderPipelineBuilder())
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.SetColorAttachmentBlendState(0, blendState)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.numBlendStates = 1;
// This fails because attachment 1 is not one of the color attachments
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.SetColorAttachmentBlendState(1, blendState)
.GetResult();
device.CreateRenderPipeline(&descriptor);
}
// Fails because color attachment is out of bounds
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetColorAttachmentBlendState(kMaxColorAttachments, blendState)
.GetResult();
{ // Fail because lack of blend states for color attachments
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.numBlendStates = 0;
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
}
// Fails because color attachment blend state is set twice
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetColorAttachmentBlendState(0, blendState)
.SetColorAttachmentBlendState(0, blendState)
.GetResult();
// Fail because set blend states for empty color attachments
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.numBlendStates = 2;
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
}
}
// TODO(enga@google.com): These should be added to the test above when validation is implemented
TEST_F(RenderPipelineValidationTest, DISABLED_TodoCreationMissingProperty) {
// Fails because pipeline layout is not set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.GetResult();
}
// Fails because primitive topology is not set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
}
}
// Test creation failure when specifying properties multiple times
TEST_F(RenderPipelineValidationTest, DISABLED_CreationDuplicates) {
// Fails because input state is set twice
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetInputState(inputState)
.GetResult();
}
// Fails because primitive topology is set twice
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.GetResult();
}
// Fails because vertex stage is set twice
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
}
// Fails because fragment stage is set twice
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.GetResult();
}
// Fails because the layout is set twice
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetLayout(pipelineLayout)
.GetResult();
}
}

View File

@@ -16,6 +16,7 @@
#include "tests/unittests/validation/ValidationTest.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
class VertexBufferValidationTest : public ValidationTest {
@@ -78,12 +79,13 @@ class VertexBufferValidationTest : public ValidationTest {
}
dawn::RenderPipeline MakeRenderPipeline(const dawn::ShaderModule& vsModule, const dawn::InputState& inputState) {
return device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.inputState = inputState;
return device.CreateRenderPipeline(&descriptor);
}
dawn::RenderPassDescriptor renderpass;