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

@ -731,6 +731,8 @@ static_library("dawn_utils") {
sources = [
"src/utils/BackendBinding.cpp",
"src/utils/BackendBinding.h",
"src/utils/ComboRenderPipelineDescriptor.cpp",
"src/utils/ComboRenderPipelineDescriptor.h",
"src/utils/DawnHelpers.cpp",
"src/utils/DawnHelpers.h",
"src/utils/SystemUtils.cpp",

114
dawn.json
View File

@ -22,6 +22,13 @@
{"value": 2, "name":"clamp to edge"}
]
},
"attachment descriptor": {
"category": "structure",
"extensible": true,
"members": [
{"name": "format", "type": "texture format"}
]
},
"bind group": {
"category": "object"
},
@ -463,8 +470,11 @@
]
},
{
"name": "create render pipeline builder",
"returns": "render pipeline builder"
"name": "create render pipeline",
"returns": "render pipeline",
"args": [
{"name": "descriptor", "type": "render pipeline descriptor", "annotation": "const*"}
]
},
{
"name": "create pipeline layout",
@ -679,6 +689,16 @@
{"name": "z", "type": "uint32_t"}
]
},
"attachments state descriptor": {
"category": "structure",
"extensible": true,
"members": [
{"name": "num color attachments", "type": "uint32_t"},
{"name": "color attachments", "type": "attachment descriptor", "annotation": "const*", "length": "num color attachments"},
{"name": "has depth stencil attachment", "type": "bool"},
{"name": "depth stencil attachment", "type": "attachment descriptor", "annotation":"const*"}
]
},
"pipeline layout": {
"category": "object"
},
@ -690,6 +710,14 @@
{"name": "bind group layouts", "type": "bind group layout", "annotation": "const*", "length": "num bind group layouts"}
]
},
"pipeline stage descriptor": {
"category": "structure",
"extensible": true,
"members": [
{"name": "module", "type": "shader module"},
{"name": "entry point", "type": "char", "annotation": "const*", "length": "strlen"}
]
},
"primitive topology": {
"category": "enum",
"values": [
@ -863,73 +891,21 @@
"render pipeline": {
"category": "object"
},
"render pipeline builder": {
"category": "object",
"methods": [
{
"name": "get result",
"returns": "render pipeline"
},
{
"name": "set color attachment format",
"TODO": "Also need sample count",
"args": [
{"name": "attachment slot", "type": "uint32_t"},
{"name": "format", "type": "texture format"}
]
},
{
"name": "set depth stencil attachment format",
"TODO": "Also need sample count",
"args": [
{"name": "format", "type": "texture format"}
]
},
{
"name": "set color attachment blend state",
"args": [
{"name": "attachment slot", "type": "uint32_t"},
{"name": "blend state", "type": "blend state"}
]
},
{
"name": "set depth stencil state",
"args": [
{"name": "depth stencil state", "type": "depth stencil state"}
]
},
{
"name": "set index format",
"args": [
{"name": "format", "type": "index format"}
]
},
{
"name": "set input state",
"args": [
{"name": "input", "type": "input state"}
]
},
{
"name": "set layout",
"args": [
{"name": "layout", "type": "pipeline layout"}
]
},
{
"name": "set primitive topology",
"args": [
{"name": "primitive topology", "type": "primitive topology"}
]
},
{
"name": "set stage",
"args": [
{"name": "stage", "type": "shader stage"},
{"name": "module", "type": "shader module"},
{"name": "entry point", "type": "char", "annotation": "const*", "length": "strlen"}
]
}
"render pipeline descriptor": {
"category": "structure",
"extensible": true,
"members": [
{"name": "layout", "type": "pipeline layout"},
{"name": "vertex stage", "type": "pipeline stage descriptor", "annotation": "const*"},
{"name": "fragment stage", "type": "pipeline stage descriptor", "annotation": "const*"},
{"name": "input state", "type": "input state"},
{"name": "index format", "type": "index format"},
{"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"},
{"name": "num blend states", "type": "uint32_t"},
{"name": "blend states", "type": "blend state", "annotation": "const*", "length": "num blend states"}
]
},
"sampler": {

View File

@ -14,6 +14,7 @@
#include "SampleUtils.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
#include "utils/SystemUtils.h"
@ -109,12 +110,15 @@ void init() {
depthStencilView = CreateDefaultDepthStencilView(device);
pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat())
.SetDepthStencilAttachmentFormat(dawn::TextureFormat::D32FloatS8Uint)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.cColorAttachments[0].format =
GetPreferredSwapChainTextureFormat();
pipeline = device.CreateRenderPipeline(&descriptor);
shaderData.resize(10000);
for (auto& data : shaderData) {

View File

@ -56,12 +56,62 @@ void init() {
dawnShaderModule fsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, fs).Release();
{
dawnRenderPipelineBuilder builder = dawnDeviceCreateRenderPipelineBuilder(device);
dawnRenderPipelineBuilderSetColorAttachmentFormat(builder, 0, swapChainFormat);
dawnRenderPipelineBuilderSetStage(builder, DAWN_SHADER_STAGE_VERTEX, vsModule, "main");
dawnRenderPipelineBuilderSetStage(builder, DAWN_SHADER_STAGE_FRAGMENT, fsModule, "main");
pipeline = dawnRenderPipelineBuilderGetResult(builder);
dawnRenderPipelineBuilderRelease(builder);
dawnRenderPipelineDescriptor descriptor;
descriptor.nextInChain = nullptr;
dawnPipelineStageDescriptor vertexStage;
vertexStage.nextInChain = nullptr;
vertexStage.module = vsModule;
vertexStage.entryPoint = "main";
descriptor.vertexStage = &vertexStage;
dawnPipelineStageDescriptor fragmentStage;
fragmentStage.nextInChain = nullptr;
fragmentStage.module = fsModule;
fragmentStage.entryPoint = "main";
descriptor.fragmentStage = &fragmentStage;
dawnAttachmentsStateDescriptor attachmentsState;
attachmentsState.nextInChain = nullptr;
attachmentsState.numColorAttachments = 1;
dawnAttachmentDescriptor colorAttachment = {nullptr, swapChainFormat};
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;
descriptor.attachmentsState = &attachmentsState;
descriptor.sampleCount = 1;
descriptor.numBlendStates = 1;
dawnBlendStateBuilder blendStateBuilder = dawnDeviceCreateBlendStateBuilder(device);
dawnBlendState blendState = dawnBlendStateBuilderGetResult(blendStateBuilder);
descriptor.blendStates = &blendState;
dawnBlendStateBuilderRelease(blendStateBuilder);
dawnPipelineLayoutDescriptor pl;
pl.nextInChain = nullptr;
pl.numBindGroupLayouts = 0;
pl.bindGroupLayouts = nullptr;
descriptor.layout = dawnDeviceCreatePipelineLayout(device, &pl);
dawnInputStateBuilder inputStateBuilder = dawnDeviceCreateInputStateBuilder(device);
descriptor.inputState = dawnInputStateBuilderGetResult(inputStateBuilder);
dawnInputStateBuilderRelease(inputStateBuilder);
descriptor.indexFormat = DAWN_INDEX_FORMAT_UINT32;
descriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
dawnDepthStencilStateBuilder depthStencilBuilder = dawnDeviceCreateDepthStencilStateBuilder(device);
descriptor.depthStencilState = dawnDepthStencilStateBuilderGetResult(depthStencilBuilder);
dawnDepthStencilStateBuilderRelease(depthStencilBuilder);
pipeline = dawnDeviceCreateRenderPipeline(device, &descriptor);
dawnBlendStateRelease(descriptor.blendStates[0]);
dawnDepthStencilStateRelease(descriptor.depthStencilState);
dawnInputStateRelease(descriptor.inputState);
}
dawnShaderModuleRelease(vsModule);

View File

@ -14,6 +14,7 @@
#include "SampleUtils.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
#include "utils/SystemUtils.h"
@ -123,13 +124,16 @@ void initRender() {
depthStencilView = CreateDefaultDepthStencilView(device);
renderPipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat())
.SetDepthStencilAttachmentFormat(dawn::TextureFormat::D32FloatS8Uint)
.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;
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.cColorAttachments[0].format =
GetPreferredSwapChainTextureFormat();
renderPipeline = device.CreateRenderPipeline(&descriptor);
}
void initSim() {

View File

@ -14,6 +14,7 @@
#include "SampleUtils.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
#include "utils/SystemUtils.h"
@ -125,15 +126,17 @@ void init() {
depthStencilView = CreateDefaultDepthStencilView(device);
pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat())
.SetDepthStencilAttachmentFormat(dawn::TextureFormat::D32FloatS8Uint)
.SetLayout(pl)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetIndexFormat(dawn::IndexFormat::Uint32)
.SetInputState(inputState)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.inputState = inputState;
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.cColorAttachments[0].format =
GetPreferredSwapChainTextureFormat();
pipeline = device.CreateRenderPipeline(&descriptor);
dawn::TextureView view = texture.CreateDefaultTextureView();

View File

@ -14,6 +14,7 @@
#include "SampleUtils.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
#include "utils/SystemUtils.h"
@ -197,16 +198,18 @@ void init() {
.SetDepthWriteEnabled(true)
.GetResult();
pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat())
.SetDepthStencilAttachmentFormat(dawn::TextureFormat::D32FloatS8Uint)
.SetLayout(pl)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetIndexFormat(dawn::IndexFormat::Uint32)
.SetInputState(inputState)
.SetDepthStencilState(depthStencilState)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.layout = pl;
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.inputState = inputState;
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.cColorAttachments[0].format =
GetPreferredSwapChainTextureFormat();
descriptor.depthStencilState = depthStencilState;
pipeline = device.CreateRenderPipeline(&descriptor);
auto planeStencilState = device.CreateDepthStencilStateBuilder()
.SetDepthCompareFunction(dawn::CompareFunction::Less)
@ -214,15 +217,18 @@ void init() {
.SetStencilFunction(dawn::Face::Both, dawn::CompareFunction::Always, dawn::StencilOperation::Keep, dawn::StencilOperation::Keep, dawn::StencilOperation::Replace)
.GetResult();
planePipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat())
.SetDepthStencilAttachmentFormat(dawn::TextureFormat::D32FloatS8Uint)
.SetLayout(pl)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState)
.SetDepthStencilState(planeStencilState)
.GetResult();
utils::ComboRenderPipelineDescriptor pDescriptor(device);
pDescriptor.layout = pl;
pDescriptor.cVertexStage.module = vsModule;
pDescriptor.cFragmentStage.module = fsModule;
pDescriptor.inputState = inputState;
pDescriptor.cAttachmentsState.hasDepthStencilAttachment = true;
pDescriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
pDescriptor.cColorAttachments[0].format =
GetPreferredSwapChainTextureFormat();
pDescriptor.depthStencilState = planeStencilState;
planePipeline = device.CreateRenderPipeline(&pDescriptor);
auto reflectionStencilState = device.CreateDepthStencilStateBuilder()
.SetDepthCompareFunction(dawn::CompareFunction::Less)
@ -230,15 +236,18 @@ void init() {
.SetStencilFunction(dawn::Face::Both, dawn::CompareFunction::Equal, dawn::StencilOperation::Keep, dawn::StencilOperation::Keep, dawn::StencilOperation::Replace)
.GetResult();
reflectionPipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat())
.SetDepthStencilAttachmentFormat(dawn::TextureFormat::D32FloatS8Uint)
.SetLayout(pl)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsReflectionModule, "main")
.SetInputState(inputState)
.SetDepthStencilState(reflectionStencilState)
.GetResult();
utils::ComboRenderPipelineDescriptor rfDescriptor(device);
rfDescriptor.layout = pl;
rfDescriptor.cVertexStage.module = vsModule;
rfDescriptor.cFragmentStage.module = fsReflectionModule;
rfDescriptor.inputState = inputState;
rfDescriptor.cAttachmentsState.hasDepthStencilAttachment = true;
rfDescriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
rfDescriptor.cColorAttachments[0].format =
GetPreferredSwapChainTextureFormat();
rfDescriptor.depthStencilState = reflectionStencilState;
reflectionPipeline = device.CreateRenderPipeline(&rfDescriptor);
cameraData.proj = glm::perspective(glm::radians(45.0f), 1.f, 1.0f, 100.0f);
}

View File

@ -23,6 +23,7 @@
#include "common/Assert.h"
#include "common/Math.h"
#include "common/Constants.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
#include "utils/SystemUtils.h"
@ -287,16 +288,20 @@ namespace {
.GetResult();
auto pipelineLayout = utils::MakeBasicPipelineLayout(device, &bindGroupLayout);
auto pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat())
.SetDepthStencilAttachmentFormat(dawn::TextureFormat::D32FloatS8Uint)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, oVSModule, "main")
.SetStage(dawn::ShaderStage::Fragment, oFSModule, "main")
.SetIndexFormat(dawn::IndexFormat::Uint16)
.SetInputState(inputState)
.SetDepthStencilState(depthStencilState)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.layout = pipelineLayout;
descriptor.cVertexStage.module = oVSModule;
descriptor.cFragmentStage.module = oFSModule;
descriptor.inputState = inputState;
descriptor.indexFormat = dawn::IndexFormat::Uint16;
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.cColorAttachments[0].format =
GetPreferredSwapChainTextureFormat();
descriptor.depthStencilState = depthStencilState;
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
dawn::BindGroup bindGroup;

View File

@ -182,9 +182,6 @@ namespace dawn_native {
RenderPassDescriptorBuilder* DeviceBase::CreateRenderPassDescriptorBuilder() {
return new RenderPassDescriptorBuilder(this);
}
RenderPipelineBuilder* DeviceBase::CreateRenderPipelineBuilder() {
return new RenderPipelineBuilder(this);
}
SamplerBase* DeviceBase::CreateSampler(const SamplerDescriptor* descriptor) {
SamplerBase* result = nullptr;
@ -194,6 +191,16 @@ namespace dawn_native {
return result;
}
RenderPipelineBase* DeviceBase::CreateRenderPipeline(
const RenderPipelineDescriptor* descriptor) {
RenderPipelineBase* result = nullptr;
if (ConsumedError(CreateRenderPipelineInternal(&result, descriptor))) {
return nullptr;
}
return result;
}
ShaderModuleBase* DeviceBase::CreateShaderModule(const ShaderModuleDescriptor* descriptor) {
ShaderModuleBase* result = nullptr;
@ -296,6 +303,14 @@ namespace dawn_native {
return {};
}
MaybeError DeviceBase::CreateRenderPipelineInternal(
RenderPipelineBase** result,
const RenderPipelineDescriptor* descriptor) {
DAWN_TRY(ValidateRenderPipelineDescriptor(this, descriptor));
DAWN_TRY_ASSIGN(*result, CreateRenderPipelineImpl(descriptor));
return {};
}
MaybeError DeviceBase::CreateSamplerInternal(SamplerBase** result,
const SamplerDescriptor* descriptor) {
DAWN_TRY(ValidateSamplerDescriptor(this, descriptor));

View File

@ -58,7 +58,6 @@ namespace dawn_native {
virtual InputStateBase* CreateInputState(InputStateBuilder* builder) = 0;
virtual RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) = 0;
virtual RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) = 0;
virtual SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) = 0;
virtual Serial GetCompletedCommandSerial() const = 0;
@ -96,7 +95,7 @@ namespace dawn_native {
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
QueueBase* CreateQueue();
RenderPassDescriptorBuilder* CreateRenderPassDescriptorBuilder();
RenderPipelineBuilder* CreateRenderPipelineBuilder();
RenderPipelineBase* CreateRenderPipeline(const RenderPipelineDescriptor* descriptor);
SamplerBase* CreateSampler(const SamplerDescriptor* descriptor);
ShaderModuleBase* CreateShaderModule(const ShaderModuleDescriptor* descriptor);
SwapChainBuilder* CreateSwapChainBuilder();
@ -127,6 +126,8 @@ namespace dawn_native {
virtual ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<QueueBase*> CreateQueueImpl() = 0;
virtual ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) = 0;
virtual ResultOrError<SamplerBase*> CreateSamplerImpl(
const SamplerDescriptor* descriptor) = 0;
virtual ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
@ -148,6 +149,8 @@ namespace dawn_native {
MaybeError CreatePipelineLayoutInternal(PipelineLayoutBase** result,
const PipelineLayoutDescriptor* descriptor);
MaybeError CreateQueueInternal(QueueBase** result);
MaybeError CreateRenderPipelineInternal(RenderPipelineBase** result,
const RenderPipelineDescriptor* descriptor);
MaybeError CreateSamplerInternal(SamplerBase** result, const SamplerDescriptor* descriptor);
MaybeError CreateShaderModuleInternal(ShaderModuleBase** result,
const ShaderModuleDescriptor* descriptor);

View File

@ -21,48 +21,141 @@
#include "dawn_native/InputState.h"
#include "dawn_native/RenderPassDescriptor.h"
#include "dawn_native/Texture.h"
#include "dawn_native/ValidationUtils_autogen.h"
namespace dawn_native {
// Helper functions
namespace {
MaybeError ValidatePipelineStageDescriptor(const PipelineStageDescriptor* descriptor,
const PipelineLayoutBase* layout,
dawn::ShaderStage stage) {
if (descriptor->entryPoint != std::string("main")) {
return DAWN_VALIDATION_ERROR("Entry point must be \"main\"");
}
if (descriptor->module->GetExecutionModel() != stage) {
return DAWN_VALIDATION_ERROR("Setting module with wrong stages");
}
if (!descriptor->module->IsCompatibleWithPipelineLayout(layout)) {
return DAWN_VALIDATION_ERROR("Stage not compatible with layout");
}
return {};
}
MaybeError ValidateAttachmentsStateDescriptor(
const AttachmentsStateDescriptor* descriptor) {
if (descriptor->numColorAttachments > kMaxColorAttachments) {
return DAWN_VALIDATION_ERROR("Color attachments number exceeds maximum");
}
if (descriptor->numColorAttachments == 0 && !descriptor->hasDepthStencilAttachment) {
return DAWN_VALIDATION_ERROR("Should have at least one attachment");
}
if (descriptor->hasDepthStencilAttachment) {
dawn::TextureFormat format = descriptor->depthStencilAttachment->format;
DAWN_TRY(ValidateTextureFormat(format));
if (!IsDepthStencilRenderableTextureFormat(format)) {
return DAWN_VALIDATION_ERROR(
"Depth stencil format must be depth-stencil renderable");
}
}
for (uint32_t i = 0; i < descriptor->numColorAttachments; ++i) {
dawn::TextureFormat format = descriptor->colorAttachments[i].format;
DAWN_TRY(ValidateTextureFormat(format));
if (!IsColorRenderableTextureFormat(format)) {
return DAWN_VALIDATION_ERROR("Color format must be color renderable");
}
}
return {};
}
} // namespace
MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
const RenderPipelineDescriptor* descriptor) {
if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
}
if (descriptor->layout == nullptr) {
return DAWN_VALIDATION_ERROR("Layout must not be null");
}
if (descriptor->inputState == nullptr) {
return DAWN_VALIDATION_ERROR("Input state must not be null");
}
if (descriptor->depthStencilState == nullptr) {
return DAWN_VALIDATION_ERROR("Depth stencil state must not be null");
}
for (uint32_t i = 0; i < descriptor->numBlendStates; ++i) {
if (descriptor->blendStates[i] == nullptr) {
return DAWN_VALIDATION_ERROR("Blend state must not be null");
}
}
DAWN_TRY(ValidateIndexFormat(descriptor->indexFormat));
DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology));
DAWN_TRY(ValidatePipelineStageDescriptor(descriptor->vertexStage, descriptor->layout,
dawn::ShaderStage::Vertex));
DAWN_TRY(ValidatePipelineStageDescriptor(descriptor->fragmentStage, descriptor->layout,
dawn::ShaderStage::Fragment));
DAWN_TRY(ValidateAttachmentsStateDescriptor(descriptor->attachmentsState));
if ((descriptor->vertexStage->module->GetUsedVertexAttributes() &
~descriptor->inputState->GetAttributesSetMask())
.any()) {
return DAWN_VALIDATION_ERROR(
"Pipeline vertex stage uses inputs not in the input state");
}
if (descriptor->sampleCount != 1) {
return DAWN_VALIDATION_ERROR("Sample count must be one");
}
if (descriptor->numBlendStates > kMaxColorAttachments) {
return DAWN_VALIDATION_ERROR("Blend states number exceeds maximum");
}
if (descriptor->attachmentsState->numColorAttachments != descriptor->numBlendStates) {
return DAWN_VALIDATION_ERROR("Each color attachment should have blend state");
}
// TODO: validate depth stencil state
return {};
}
// RenderPipelineBase
RenderPipelineBase::RenderPipelineBase(RenderPipelineBuilder* builder)
: PipelineBase(builder->GetDevice(), builder),
mDepthStencilState(std::move(builder->mDepthStencilState)),
mIndexFormat(builder->mIndexFormat),
mInputState(std::move(builder->mInputState)),
mPrimitiveTopology(builder->mPrimitiveTopology),
mBlendStates(builder->mBlendStates),
mColorAttachmentsSet(builder->mColorAttachmentsSet),
mColorAttachmentFormats(builder->mColorAttachmentFormats),
mDepthStencilFormatSet(builder->mDepthStencilFormatSet),
mDepthStencilFormat(builder->mDepthStencilFormat) {
if (GetStageMask() != (dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment)) {
builder->HandleError("Render pipeline should have exactly a vertex and fragment stage");
return;
RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
const RenderPipelineDescriptor* descriptor)
: PipelineBase(device,
descriptor->layout,
dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment),
mDepthStencilState(descriptor->depthStencilState),
mIndexFormat(descriptor->indexFormat),
mInputState(descriptor->inputState),
mPrimitiveTopology(descriptor->primitiveTopology),
mHasDepthStencilAttachment(descriptor->attachmentsState->hasDepthStencilAttachment) {
if (mHasDepthStencilAttachment) {
mDepthStencilFormat = descriptor->attachmentsState->depthStencilAttachment->format;
}
ExtractModuleData(dawn::ShaderStage::Vertex, descriptor->vertexStage->module);
ExtractModuleData(dawn::ShaderStage::Fragment, descriptor->fragmentStage->module);
// TODO(kainino@chromium.org): Need to verify the pipeline against its render subpass.
if ((builder->GetStageInfo(dawn::ShaderStage::Vertex).module->GetUsedVertexAttributes() &
~mInputState->GetAttributesSetMask())
.any()) {
builder->HandleError("Pipeline vertex stage uses inputs not in the input state");
return;
for (uint32_t i = 0; i < descriptor->attachmentsState->numColorAttachments; ++i) {
mColorAttachmentsSet.set(i);
mBlendStates[i] = descriptor->blendStates[i];
mColorAttachmentFormats[i] = descriptor->attachmentsState->colorAttachments[i].format;
}
// TODO(cwallez@chromium.org): Check against the shader module that the correct color
// attachment are set?
size_t attachmentCount = mColorAttachmentsSet.count();
if (mDepthStencilFormatSet) {
attachmentCount++;
}
if (attachmentCount == 0) {
builder->HandleError("Should have at least one attachment");
return;
}
}
BlendStateBase* RenderPipelineBase::GetBlendState(uint32_t attachmentSlot) {
@ -91,7 +184,7 @@ namespace dawn_native {
}
bool RenderPipelineBase::HasDepthStencilAttachment() const {
return mDepthStencilFormatSet;
return mHasDepthStencilAttachment;
}
dawn::TextureFormat RenderPipelineBase::GetColorAttachmentFormat(uint32_t attachment) const {
@ -99,6 +192,7 @@ namespace dawn_native {
}
dawn::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const {
ASSERT(mHasDepthStencilAttachment);
return mDepthStencilFormat;
}
@ -118,11 +212,11 @@ namespace dawn_native {
}
}
if (renderPass->HasDepthStencilAttachment() != mDepthStencilFormatSet) {
if (renderPass->HasDepthStencilAttachment() != mHasDepthStencilAttachment) {
return false;
}
if (mDepthStencilFormatSet &&
if (mHasDepthStencilAttachment &&
(renderPass->GetDepthStencilAttachment().view->GetTexture()->GetFormat() !=
mDepthStencilFormat)) {
return false;
@ -131,106 +225,4 @@ namespace dawn_native {
return true;
}
// RenderPipelineBuilder
RenderPipelineBuilder::RenderPipelineBuilder(DeviceBase* device)
: Builder(device), PipelineBuilder(this) {
}
RenderPipelineBase* RenderPipelineBuilder::GetResultImpl() {
DeviceBase* device = GetDevice();
// TODO(cwallez@chromium.org): the layout should be required, and put the default objects in
// the device
if (!mInputState) {
auto builder = device->CreateInputStateBuilder();
mInputState = builder->GetResult();
// Remove the external ref objects are created with
mInputState->Release();
builder->Release();
}
if (!mDepthStencilState) {
auto builder = device->CreateDepthStencilStateBuilder();
mDepthStencilState = builder->GetResult();
// Remove the external ref objects are created with
mDepthStencilState->Release();
builder->Release();
}
if ((mBlendStatesSet | mColorAttachmentsSet) != mColorAttachmentsSet) {
HandleError("Blend state set on unset color attachment");
return nullptr;
}
// Assign all color attachments without a blend state the default state
// TODO(enga@google.com): Put the default objects in the device
for (uint32_t attachmentSlot : IterateBitSet(mColorAttachmentsSet & ~mBlendStatesSet)) {
mBlendStates[attachmentSlot] = device->CreateBlendStateBuilder()->GetResult();
// Remove the external ref objects are created with
mBlendStates[attachmentSlot]->Release();
}
return device->CreateRenderPipeline(this);
}
void RenderPipelineBuilder::SetColorAttachmentFormat(uint32_t attachmentSlot,
dawn::TextureFormat format) {
if (attachmentSlot >= kMaxColorAttachments) {
HandleError("Attachment index out of bounds");
return;
}
mColorAttachmentsSet.set(attachmentSlot);
mColorAttachmentFormats[attachmentSlot] = format;
}
void RenderPipelineBuilder::SetColorAttachmentBlendState(uint32_t attachmentSlot,
BlendStateBase* blendState) {
if (attachmentSlot >= kMaxColorAttachments) {
HandleError("Attachment index out of bounds");
return;
}
if (blendState == nullptr) {
HandleError("Blend state must not be null");
return;
}
if (mBlendStatesSet[attachmentSlot]) {
HandleError("Attachment blend state already set");
return;
}
mBlendStatesSet.set(attachmentSlot);
mBlendStates[attachmentSlot] = blendState;
}
void RenderPipelineBuilder::SetDepthStencilState(DepthStencilStateBase* depthStencilState) {
if (depthStencilState == nullptr) {
HandleError("Depth stencil state must not be null");
return;
}
mDepthStencilState = depthStencilState;
}
void RenderPipelineBuilder::SetDepthStencilAttachmentFormat(dawn::TextureFormat format) {
mDepthStencilFormatSet = true;
mDepthStencilFormat = format;
}
void RenderPipelineBuilder::SetIndexFormat(dawn::IndexFormat format) {
mIndexFormat = format;
}
void RenderPipelineBuilder::SetInputState(InputStateBase* inputState) {
if (inputState == nullptr) {
HandleError("Input state must not be null");
return;
}
mInputState = inputState;
}
void RenderPipelineBuilder::SetPrimitiveTopology(dawn::PrimitiveTopology primitiveTopology) {
mPrimitiveTopology = primitiveTopology;
}
} // namespace dawn_native

View File

@ -27,9 +27,14 @@
namespace dawn_native {
class DeviceBase;
MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
const RenderPipelineDescriptor* descriptor);
class RenderPipelineBase : public PipelineBase {
public:
RenderPipelineBase(RenderPipelineBuilder* builder);
RenderPipelineBase(DeviceBase* device, const RenderPipelineDescriptor* descriptor);
BlendStateBase* GetBlendState(uint32_t attachmentSlot);
DepthStencilStateBase* GetDepthStencilState();
@ -55,39 +60,7 @@ namespace dawn_native {
std::bitset<kMaxColorAttachments> mColorAttachmentsSet;
std::array<dawn::TextureFormat, kMaxColorAttachments> mColorAttachmentFormats;
bool mDepthStencilFormatSet = false;
dawn::TextureFormat mDepthStencilFormat;
};
class RenderPipelineBuilder : public Builder<RenderPipelineBase>, public PipelineBuilder {
public:
RenderPipelineBuilder(DeviceBase* device);
// Dawn API
void SetColorAttachmentFormat(uint32_t attachmentSlot, dawn::TextureFormat format);
void SetColorAttachmentBlendState(uint32_t attachmentSlot, BlendStateBase* blendState);
void SetDepthStencilAttachmentFormat(dawn::TextureFormat format);
void SetDepthStencilState(DepthStencilStateBase* depthStencilState);
void SetPrimitiveTopology(dawn::PrimitiveTopology primitiveTopology);
void SetIndexFormat(dawn::IndexFormat format);
void SetInputState(InputStateBase* inputState);
private:
friend class RenderPipelineBase;
RenderPipelineBase* GetResultImpl() override;
Ref<DepthStencilStateBase> mDepthStencilState;
Ref<InputStateBase> mInputState;
// TODO(enga@google.com): Remove default when we validate that all required properties are
// set
dawn::PrimitiveTopology mPrimitiveTopology = dawn::PrimitiveTopology::TriangleList;
dawn::IndexFormat mIndexFormat = dawn::IndexFormat::Uint32;
std::bitset<kMaxColorAttachments> mBlendStatesSet;
std::array<Ref<BlendStateBase>, kMaxColorAttachments> mBlendStates;
std::bitset<kMaxColorAttachments> mColorAttachmentsSet;
std::array<dawn::TextureFormat, kMaxColorAttachments> mColorAttachmentFormats;
bool mDepthStencilFormatSet = false;
bool mHasDepthStencilAttachment = false;
dawn::TextureFormat mDepthStencilFormat;
};

View File

@ -250,6 +250,26 @@ namespace dawn_native {
}
}
bool IsDepthStencilRenderableTextureFormat(dawn::TextureFormat format) {
switch (format) {
case dawn::TextureFormat::D32FloatS8Uint:
return true;
case dawn::TextureFormat::B8G8R8A8Unorm:
case dawn::TextureFormat::R8G8B8A8Uint:
case dawn::TextureFormat::R8G8B8A8Unorm:
case dawn::TextureFormat::R8G8Uint:
case dawn::TextureFormat::R8G8Unorm:
case dawn::TextureFormat::R8Uint:
case dawn::TextureFormat::R8Unorm:
return false;
default:
UNREACHABLE();
return false;
}
}
// TextureBase
TextureBase::TextureBase(DeviceBase* device, const TextureDescriptor* descriptor)

View File

@ -33,6 +33,7 @@ namespace dawn_native {
bool TextureFormatHasStencil(dawn::TextureFormat format);
bool TextureFormatHasDepthOrStencil(dawn::TextureFormat format);
bool IsColorRenderableTextureFormat(dawn::TextureFormat format);
bool IsDepthStencilRenderableTextureFormat(dawn::TextureFormat format);
static constexpr dawn::TextureUsageBit kReadOnlyTextureUsages =
dawn::TextureUsageBit::TransferSrc | dawn::TextureUsageBit::Sampled |

View File

@ -324,8 +324,9 @@ namespace dawn_native { namespace d3d12 {
RenderPassDescriptorBuilder* builder) {
return new RenderPassDescriptor(builder);
}
RenderPipelineBase* Device::CreateRenderPipeline(RenderPipelineBuilder* builder) {
return new RenderPipeline(builder);
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return new RenderPipeline(this, descriptor);
}
ResultOrError<SamplerBase*> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return new Sampler(this, descriptor);

View File

@ -47,7 +47,6 @@ namespace dawn_native { namespace d3d12 {
InputStateBase* CreateInputState(InputStateBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
Serial GetCompletedCommandSerial() const final override;
@ -88,6 +87,8 @@ namespace dawn_native { namespace d3d12 {
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor) override;

View File

@ -63,10 +63,9 @@ namespace dawn_native { namespace d3d12 {
}
} // namespace
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
: RenderPipelineBase(builder),
mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())),
mDevice(ToBackend(builder->GetDevice())) {
RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
: RenderPipelineBase(device, descriptor),
mD3d12PrimitiveTopology(D3D12PrimitiveTopology(GetPrimitiveTopology())) {
uint32_t compileFlags = 0;
#if defined(_DEBUG)
// Enable better shader debugging with the graphics debugging tools.
@ -75,36 +74,41 @@ namespace dawn_native { namespace d3d12 {
// SPRIV-cross does matrix multiplication expecting row major matrices
compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
D3D12_GRAPHICS_PIPELINE_STATE_DESC descriptor = {};
D3D12_GRAPHICS_PIPELINE_STATE_DESC descriptorD3D12 = {};
PerStage<ComPtr<ID3DBlob>> compiledShader;
ComPtr<ID3DBlob> errors;
for (auto stage : IterateStages(GetStageMask())) {
const auto& module = ToBackend(builder->GetStageInfo(stage).module);
const auto& entryPoint = builder->GetStageInfo(stage).entryPoint;
const auto& hlslSource = module->GetHLSLSource(ToBackend(GetLayout()));
dawn::ShaderStageBit renderStages =
dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment;
for (auto stage : IterateStages(renderStages)) {
const ShaderModule* module = nullptr;
const char* entryPoint = nullptr;
const char* compileTarget = nullptr;
D3D12_SHADER_BYTECODE* shader = nullptr;
switch (stage) {
case dawn::ShaderStage::Vertex:
shader = &descriptor.VS;
module = ToBackend(descriptor->vertexStage->module);
entryPoint = descriptor->vertexStage->entryPoint;
shader = &descriptorD3D12.VS;
compileTarget = "vs_5_1";
break;
case dawn::ShaderStage::Fragment:
shader = &descriptor.PS;
module = ToBackend(descriptor->fragmentStage->module);
entryPoint = descriptor->fragmentStage->entryPoint;
shader = &descriptorD3D12.PS;
compileTarget = "ps_5_1";
break;
case dawn::ShaderStage::Compute:
default:
UNREACHABLE();
break;
}
const PlatformFunctions* functions = ToBackend(builder->GetDevice())->GetFunctions();
const std::string hlslSource = module->GetHLSLSource(ToBackend(GetLayout()));
const PlatformFunctions* functions = device->GetFunctions();
if (FAILED(functions->d3dCompile(hlslSource.c_str(), hlslSource.length(), nullptr,
nullptr, nullptr, entryPoint.c_str(), compileTarget,
nullptr, nullptr, entryPoint, compileTarget,
compileFlags, 0, &compiledShader[stage], &errors))) {
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
ASSERT(false);
@ -118,54 +122,55 @@ namespace dawn_native { namespace d3d12 {
PipelineLayout* layout = ToBackend(GetLayout());
descriptor.pRootSignature = layout->GetRootSignature().Get();
descriptorD3D12.pRootSignature = layout->GetRootSignature().Get();
// D3D12 logs warnings if any empty input state is used
InputState* inputState = ToBackend(GetInputState());
if (inputState->GetAttributesSetMask().any()) {
descriptor.InputLayout = inputState->GetD3D12InputLayoutDescriptor();
descriptorD3D12.InputLayout = inputState->GetD3D12InputLayoutDescriptor();
}
descriptor.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
descriptor.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
descriptor.RasterizerState.FrontCounterClockwise = FALSE;
descriptor.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
descriptor.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
descriptor.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
descriptor.RasterizerState.DepthClipEnable = TRUE;
descriptor.RasterizerState.MultisampleEnable = FALSE;
descriptor.RasterizerState.AntialiasedLineEnable = FALSE;
descriptor.RasterizerState.ForcedSampleCount = 0;
descriptor.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
descriptorD3D12.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
descriptorD3D12.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
descriptorD3D12.RasterizerState.FrontCounterClockwise = FALSE;
descriptorD3D12.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
descriptorD3D12.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
descriptorD3D12.RasterizerState.SlopeScaledDepthBias =
D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
descriptorD3D12.RasterizerState.DepthClipEnable = TRUE;
descriptorD3D12.RasterizerState.MultisampleEnable = FALSE;
descriptorD3D12.RasterizerState.AntialiasedLineEnable = FALSE;
descriptorD3D12.RasterizerState.ForcedSampleCount = 0;
descriptorD3D12.RasterizerState.ConservativeRaster =
D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
if (HasDepthStencilAttachment()) {
descriptor.DSVFormat = D3D12TextureFormat(GetDepthStencilFormat());
descriptorD3D12.DSVFormat = D3D12TextureFormat(GetDepthStencilFormat());
}
for (uint32_t i : IterateBitSet(GetColorAttachmentsMask())) {
descriptor.RTVFormats[i] = D3D12TextureFormat(GetColorAttachmentFormat(i));
descriptor.BlendState.RenderTarget[i] =
descriptorD3D12.RTVFormats[i] = D3D12TextureFormat(GetColorAttachmentFormat(i));
descriptorD3D12.BlendState.RenderTarget[i] =
ToBackend(GetBlendState(i))->GetD3D12BlendDesc();
}
descriptor.NumRenderTargets = static_cast<uint32_t>(GetColorAttachmentsMask().count());
descriptorD3D12.NumRenderTargets = static_cast<uint32_t>(GetColorAttachmentsMask().count());
descriptor.BlendState.AlphaToCoverageEnable = FALSE;
descriptor.BlendState.IndependentBlendEnable = TRUE;
descriptorD3D12.BlendState.AlphaToCoverageEnable = FALSE;
descriptorD3D12.BlendState.IndependentBlendEnable = TRUE;
DepthStencilState* depthStencilState = ToBackend(GetDepthStencilState());
descriptor.DepthStencilState = depthStencilState->GetD3D12DepthStencilDescriptor();
descriptorD3D12.DepthStencilState = depthStencilState->GetD3D12DepthStencilDescriptor();
descriptor.SampleMask = UINT_MAX;
descriptor.PrimitiveTopologyType = D3D12PrimitiveTopologyType(GetPrimitiveTopology());
descriptor.SampleDesc.Count = 1;
descriptorD3D12.SampleMask = UINT_MAX;
descriptorD3D12.PrimitiveTopologyType = D3D12PrimitiveTopologyType(GetPrimitiveTopology());
descriptorD3D12.SampleDesc.Count = 1;
Device* device = ToBackend(builder->GetDevice());
ASSERT_SUCCESS(device->GetD3D12Device()->CreateGraphicsPipelineState(
&descriptor, IID_PPV_ARGS(&mPipelineState)));
&descriptorD3D12, IID_PPV_ARGS(&mPipelineState)));
}
RenderPipeline::~RenderPipeline() {
mDevice->ReferenceUntilUnused(mPipelineState);
ToBackend(GetDevice())->ReferenceUntilUnused(mPipelineState);
}
D3D12_PRIMITIVE_TOPOLOGY RenderPipeline::GetD3D12PrimitiveTopology() const {

View File

@ -25,7 +25,7 @@ namespace dawn_native { namespace d3d12 {
class RenderPipeline : public RenderPipelineBase {
public:
RenderPipeline(RenderPipelineBuilder* builder);
RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor);
~RenderPipeline();
D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
@ -34,8 +34,6 @@ namespace dawn_native { namespace d3d12 {
private:
D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology;
ComPtr<ID3D12PipelineState> mPipelineState;
Device* mDevice = nullptr;
};
}} // namespace dawn_native::d3d12

View File

@ -43,7 +43,6 @@ namespace dawn_native { namespace metal {
InputStateBase* CreateInputState(InputStateBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
Serial GetCompletedCommandSerial() const final override;
@ -72,6 +71,8 @@ namespace dawn_native { namespace metal {
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor) override;

View File

@ -197,12 +197,13 @@ namespace dawn_native { namespace metal {
RenderPassDescriptorBuilder* builder) {
return new RenderPassDescriptor(builder);
}
RenderPipelineBase* Device::CreateRenderPipeline(RenderPipelineBuilder* builder) {
return new RenderPipeline(builder);
}
ResultOrError<QueueBase*> Device::CreateQueueImpl() {
return new Queue(this);
}
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return new RenderPipeline(this, descriptor);
}
ResultOrError<SamplerBase*> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return new Sampler(this, descriptor);
}

View File

@ -21,9 +21,11 @@
namespace dawn_native { namespace metal {
class Device;
class RenderPipeline : public RenderPipelineBase {
public:
RenderPipeline(RenderPipelineBuilder* builder);
RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor);
~RenderPipeline();
MTLIndexType GetMTLIndexType() const;

View File

@ -64,65 +64,57 @@ namespace dawn_native { namespace metal {
}
}
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
: RenderPipelineBase(builder),
RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
: RenderPipelineBase(device, descriptor),
mMtlIndexType(MTLIndexFormat(GetIndexFormat())),
mMtlPrimitiveTopology(MTLPrimitiveTopology(GetPrimitiveTopology())) {
auto mtlDevice = ToBackend(builder->GetDevice())->GetMTLDevice();
auto mtlDevice = device->GetMTLDevice();
MTLRenderPipelineDescriptor* descriptor = [MTLRenderPipelineDescriptor new];
MTLRenderPipelineDescriptor* descriptorMTL = [MTLRenderPipelineDescriptor new];
for (auto stage : IterateStages(GetStageMask())) {
const auto& module = ToBackend(builder->GetStageInfo(stage).module);
const ShaderModule* vertexModule = ToBackend(descriptor->vertexStage->module);
const char* vertexEntryPoint = descriptor->vertexStage->entryPoint;
ShaderModule::MetalFunctionData vertexData = vertexModule->GetFunction(
vertexEntryPoint, dawn::ShaderStage::Vertex, ToBackend(GetLayout()));
descriptorMTL.vertexFunction = vertexData.function;
const auto& entryPoint = builder->GetStageInfo(stage).entryPoint;
ShaderModule::MetalFunctionData data =
module->GetFunction(entryPoint.c_str(), stage, ToBackend(GetLayout()));
id<MTLFunction> function = data.function;
switch (stage) {
case dawn::ShaderStage::Vertex:
descriptor.vertexFunction = function;
break;
case dawn::ShaderStage::Fragment:
descriptor.fragmentFunction = function;
break;
case dawn::ShaderStage::Compute:
UNREACHABLE();
}
}
const ShaderModule* fragmentModule = ToBackend(descriptor->fragmentStage->module);
const char* fragmentEntryPoint = descriptor->fragmentStage->entryPoint;
ShaderModule::MetalFunctionData fragmentData = fragmentModule->GetFunction(
fragmentEntryPoint, dawn::ShaderStage::Fragment, ToBackend(GetLayout()));
descriptorMTL.fragmentFunction = fragmentData.function;
if (HasDepthStencilAttachment()) {
// TODO(kainino@chromium.org): Handle depth-only and stencil-only formats.
dawn::TextureFormat depthStencilFormat = GetDepthStencilFormat();
descriptor.depthAttachmentPixelFormat = MetalPixelFormat(depthStencilFormat);
descriptor.stencilAttachmentPixelFormat = MetalPixelFormat(depthStencilFormat);
descriptorMTL.depthAttachmentPixelFormat = MetalPixelFormat(depthStencilFormat);
descriptorMTL.stencilAttachmentPixelFormat = MetalPixelFormat(depthStencilFormat);
}
for (uint32_t i : IterateBitSet(GetColorAttachmentsMask())) {
descriptor.colorAttachments[i].pixelFormat =
descriptorMTL.colorAttachments[i].pixelFormat =
MetalPixelFormat(GetColorAttachmentFormat(i));
ToBackend(GetBlendState(i))->ApplyBlendState(descriptor.colorAttachments[i]);
ToBackend(GetBlendState(i))->ApplyBlendState(descriptorMTL.colorAttachments[i]);
}
descriptor.inputPrimitiveTopology = MTLInputPrimitiveTopology(GetPrimitiveTopology());
descriptorMTL.inputPrimitiveTopology = MTLInputPrimitiveTopology(GetPrimitiveTopology());
InputState* inputState = ToBackend(GetInputState());
descriptor.vertexDescriptor = inputState->GetMTLVertexDescriptor();
descriptorMTL.vertexDescriptor = inputState->GetMTLVertexDescriptor();
// TODO(kainino@chromium.org): push constants, textures, samplers
NSError* error = nil;
mMtlRenderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor:descriptor
mMtlRenderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor:descriptorMTL
error:&error];
if (error != nil) {
NSLog(@" error => %@", error);
builder->HandleError("Error creating pipeline state");
[descriptor release];
device->HandleError("Error creating rendering pipeline state");
[descriptorMTL release];
return;
}
[descriptor release];
[descriptorMTL release];
}
RenderPipeline::~RenderPipeline() {

View File

@ -72,8 +72,9 @@ namespace dawn_native { namespace null {
RenderPassDescriptorBuilder* builder) {
return new RenderPassDescriptor(builder);
}
RenderPipelineBase* Device::CreateRenderPipeline(RenderPipelineBuilder* builder) {
return new RenderPipeline(builder);
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return new RenderPipeline(this, descriptor);
}
ResultOrError<SamplerBase*> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return new Sampler(this, descriptor);

View File

@ -99,7 +99,6 @@ namespace dawn_native { namespace null {
InputStateBase* CreateInputState(InputStateBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
Serial GetCompletedCommandSerial() const final override;
@ -122,6 +121,8 @@ namespace dawn_native { namespace null {
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor) override;

View File

@ -99,8 +99,9 @@ namespace dawn_native { namespace opengl {
RenderPassDescriptorBuilder* builder) {
return new RenderPassDescriptor(builder);
}
RenderPipelineBase* Device::CreateRenderPipeline(RenderPipelineBuilder* builder) {
return new RenderPipeline(builder);
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return new RenderPipeline(this, descriptor);
}
ResultOrError<SamplerBase*> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return new Sampler(this, descriptor);

View File

@ -46,7 +46,6 @@ namespace dawn_native { namespace opengl {
InputStateBase* CreateInputState(InputStateBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
Serial GetCompletedCommandSerial() const final override;
@ -66,6 +65,8 @@ namespace dawn_native { namespace opengl {
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor) override;

View File

@ -16,6 +16,7 @@
#include "dawn_native/opengl/BlendStateGL.h"
#include "dawn_native/opengl/DepthStencilStateGL.h"
#include "dawn_native/opengl/DeviceGL.h"
#include "dawn_native/opengl/Forward.h"
#include "dawn_native/opengl/InputStateGL.h"
#include "dawn_native/opengl/PersistentPipelineStateGL.h"
@ -41,13 +42,12 @@ namespace dawn_native { namespace opengl {
}
} // namespace
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
: RenderPipelineBase(builder),
RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
: RenderPipelineBase(device, descriptor),
mGlPrimitiveTopology(GLPrimitiveTopology(GetPrimitiveTopology())) {
PerStage<const ShaderModule*> modules(nullptr);
for (dawn::ShaderStage stage : IterateStages(GetStageMask())) {
modules[stage] = ToBackend(builder->GetStageInfo(stage).module.Get());
}
modules[dawn::ShaderStage::Vertex] = ToBackend(descriptor->vertexStage->module);
modules[dawn::ShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
PipelineGL::Initialize(ToBackend(GetLayout()), modules);
}

View File

@ -25,11 +25,12 @@
namespace dawn_native { namespace opengl {
class Device;
class PersistentPipelineState;
class RenderPipeline : public RenderPipelineBase, public PipelineGL {
public:
RenderPipeline(RenderPipelineBuilder* builder);
RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor);
GLenum GetGLPrimitiveTopology() const;

View File

@ -250,8 +250,9 @@ namespace dawn_native { namespace vulkan {
RenderPassDescriptorBuilder* builder) {
return new RenderPassDescriptor(builder);
}
RenderPipelineBase* Device::CreateRenderPipeline(RenderPipelineBuilder* builder) {
return new RenderPipeline(builder);
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return new RenderPipeline(this, descriptor);
}
ResultOrError<SamplerBase*> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
return new Sampler(this, descriptor);

View File

@ -69,7 +69,6 @@ namespace dawn_native { namespace vulkan {
InputStateBase* CreateInputState(InputStateBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
Serial GetCompletedCommandSerial() const final override;
@ -89,6 +88,8 @@ namespace dawn_native { namespace vulkan {
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor) override;

View File

@ -47,32 +47,29 @@ namespace dawn_native { namespace vulkan {
} // anonymous namespace
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
: RenderPipelineBase(builder), mDevice(ToBackend(builder->GetDevice())) {
RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
: RenderPipelineBase(device, descriptor) {
// Eventually a bunch of the structures that need to be chained in the create info will be
// held by objects such as the BlendState. They aren't implemented yet so we initialize
// everything here.
VkPipelineShaderStageCreateInfo shaderStages[2];
{
const auto& vertexStageInfo = builder->GetStageInfo(dawn::ShaderStage::Vertex);
const auto& fragmentStageInfo = builder->GetStageInfo(dawn::ShaderStage::Fragment);
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].pNext = nullptr;
shaderStages[0].flags = 0;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].module = ToBackend(vertexStageInfo.module)->GetHandle();
shaderStages[0].pName = vertexStageInfo.entryPoint.c_str();
shaderStages[0].pSpecializationInfo = nullptr;
shaderStages[0].module = ToBackend(descriptor->vertexStage->module)->GetHandle();
shaderStages[0].pName = descriptor->vertexStage->entryPoint;
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].pNext = nullptr;
shaderStages[1].flags = 0;
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStages[1].module = ToBackend(fragmentStageInfo.module)->GetHandle();
shaderStages[1].pName = fragmentStageInfo.entryPoint.c_str();
shaderStages[1].pSpecializationInfo = nullptr;
shaderStages[1].module = ToBackend(descriptor->fragmentStage->module)->GetHandle();
shaderStages[1].pName = descriptor->fragmentStage->entryPoint;
}
VkPipelineInputAssemblyStateCreateInfo inputAssembly;
@ -183,7 +180,7 @@ namespace dawn_native { namespace vulkan {
dawn::LoadOp::Load);
}
renderPass = mDevice->GetRenderPassCache()->GetRenderPass(query);
renderPass = device->GetRenderPassCache()->GetRenderPass(query);
}
// The create info chains in a bunch of things created on the stack here or inside state
@ -209,15 +206,15 @@ namespace dawn_native { namespace vulkan {
createInfo.basePipelineHandle = VK_NULL_HANDLE;
createInfo.basePipelineIndex = -1;
if (mDevice->fn.CreateGraphicsPipelines(mDevice->GetVkDevice(), VK_NULL_HANDLE, 1,
&createInfo, nullptr, &mHandle) != VK_SUCCESS) {
if (device->fn.CreateGraphicsPipelines(device->GetVkDevice(), VK_NULL_HANDLE, 1,
&createInfo, nullptr, &mHandle) != VK_SUCCESS) {
ASSERT(false);
}
}
RenderPipeline::~RenderPipeline() {
if (mHandle != VK_NULL_HANDLE) {
mDevice->GetFencedDeleter()->DeleteWhenUnused(mHandle);
ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
mHandle = VK_NULL_HANDLE;
}
}

View File

@ -25,14 +25,13 @@ namespace dawn_native { namespace vulkan {
class RenderPipeline : public RenderPipelineBase {
public:
RenderPipeline(RenderPipelineBuilder* builder);
RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor);
~RenderPipeline();
VkPipeline GetHandle() const;
private:
VkPipeline mHandle = VK_NULL_HANDLE;
Device* mDevice = nullptr;
};
}} // namespace dawn_native::vulkan

View File

@ -15,6 +15,7 @@
#include "common/Assert.h"
#include "common/Constants.h"
#include "tests/DawnTest.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
constexpr static unsigned int kRTSize = 8;
@ -114,13 +115,15 @@ TEST_P(BindGroupTests, ReusedUBO) {
);
dawn::PipelineLayout pipelineLayout = utils::MakeBasicPipelineLayout(device, &bgl);
dawn::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor textureDescriptor(device);
textureDescriptor.layout = pipelineLayout;
textureDescriptor.cVertexStage.module = vsModule;
textureDescriptor.cFragmentStage.module = fsModule;
textureDescriptor.cColorAttachments[0].format =
renderPass.colorFormat;
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&textureDescriptor);
struct Data {
float transform[8];
char padding[256 - 8 * sizeof(float)];
@ -198,13 +201,15 @@ TEST_P(BindGroupTests, UBOSamplerAndTexture) {
);
dawn::PipelineLayout pipelineLayout = utils::MakeBasicPipelineLayout(device, &bgl);
dawn::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);
pipelineDescriptor.layout = pipelineLayout;
pipelineDescriptor.cVertexStage.module = vsModule;
pipelineDescriptor.cFragmentStage.module = fsModule;
pipelineDescriptor.cColorAttachments[0].format =
renderPass.colorFormat;
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
constexpr float dummy = 0.0f;
constexpr float transform[] = { 1.f, 0.f, dummy, dummy, 0.f, 1.f, dummy, dummy };
dawn::Buffer buffer = utils::CreateBufferFromData(device, &transform, sizeof(transform), dawn::BufferUsageBit::Uniform);

View File

@ -19,6 +19,7 @@
#include "common/Assert.h"
#include "common/Constants.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
constexpr static unsigned int kRTSize = 64;
@ -66,20 +67,24 @@ class BlendStateTest : public DawnTest {
}
)");
basePipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor baseDescriptor(device);
baseDescriptor.layout = pipelineLayout;
baseDescriptor.cVertexStage.module = vsModule;
baseDescriptor.cFragmentStage.module = fsModule;
baseDescriptor.cColorAttachments[0].format =
renderPass.colorFormat;
testPipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetColorAttachmentBlendState(0, blendState)
.GetResult();
basePipeline = device.CreateRenderPipeline(&baseDescriptor);
utils::ComboRenderPipelineDescriptor testDescriptor(device);
testDescriptor.layout = pipelineLayout;
testDescriptor.cVertexStage.module = vsModule;
testDescriptor.cFragmentStage.module = fsModule;
testDescriptor.cColorAttachments[0].format =
renderPass.colorFormat;
testDescriptor.cBlendStates[0] = blendState;
testPipeline = device.CreateRenderPipeline(&testDescriptor);
}
// Create a bind group to set the colors as a uniform buffer
@ -766,7 +771,7 @@ TEST_P(BlendStateTest, IndependentBlendState) {
blend3.srcFactor = dawn::BlendFactor::One;
blend3.dstFactor = dawn::BlendFactor::One;
std::array<dawn::BlendState, 3> blendStates = { {
std::array<dawn::BlendState, 4> blendStates = { {
device.CreateBlendStateBuilder()
.SetBlendEnabled(true)
.SetColorBlend(&blend1)
@ -777,6 +782,7 @@ TEST_P(BlendStateTest, IndependentBlendState) {
.SetColorBlend(&blend2)
.SetAlphaBlend(&blend2)
.GetResult(),
device.CreateBlendStateBuilder().GetResult(),
device.CreateBlendStateBuilder()
.SetBlendEnabled(true)
.SetColorBlend(&blend3)
@ -784,30 +790,24 @@ TEST_P(BlendStateTest, IndependentBlendState) {
.GetResult(),
} };
basePipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(1, dawn::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(2, dawn::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(3, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor baseDescriptor(device);
baseDescriptor.layout = pipelineLayout;
baseDescriptor.cVertexStage.module = vsModule;
baseDescriptor.cFragmentStage.module = fsModule;
baseDescriptor.cAttachmentsState.numColorAttachments = 4;
baseDescriptor.numBlendStates = 4;
testPipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(1, dawn::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(2, dawn::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(3, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetColorAttachmentBlendState(0, blendStates[0])
.SetColorAttachmentBlendState(1, blendStates[1])
// Blend state not set on third color attachment. It should be default
.SetColorAttachmentBlendState(3, blendStates[2])
.GetResult();
basePipeline = device.CreateRenderPipeline(&baseDescriptor);
utils::ComboRenderPipelineDescriptor testDescriptor(device);
testDescriptor.layout = pipelineLayout;
testDescriptor.cVertexStage.module = vsModule;
testDescriptor.cFragmentStage.module = fsModule;
testDescriptor.cAttachmentsState.numColorAttachments = 4;
testDescriptor.numBlendStates = 4;
testDescriptor.blendStates = blendStates.data();
testPipeline = device.CreateRenderPipeline(&testDescriptor);
for (unsigned int c = 0; c < kColors.size(); ++c) {
RGBA8 base = kColors[((c + 31) * 29) % kColors.size()];
@ -870,20 +870,24 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
}
)");
basePipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor baseDescriptor(device);
baseDescriptor.layout = pipelineLayout;
baseDescriptor.cVertexStage.module = vsModule;
baseDescriptor.cFragmentStage.module = fsModule;
baseDescriptor.cColorAttachments[0].format =
renderPass.colorFormat;
testPipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetColorAttachmentBlendState(0, blendState)
.GetResult();
basePipeline = device.CreateRenderPipeline(&baseDescriptor);
utils::ComboRenderPipelineDescriptor testDescriptor(device);
testDescriptor.layout = pipelineLayout;
testDescriptor.cVertexStage.module = vsModule;
testDescriptor.cFragmentStage.module = fsModule;
testDescriptor.cColorAttachments[0].format =
renderPass.colorFormat;
testDescriptor.cBlendStates[0] = blendState;
testPipeline = device.CreateRenderPipeline(&testDescriptor);
// Check that the initial blend color is (0,0,0,0)
{

View File

@ -15,6 +15,7 @@
#include "tests/DawnTest.h"
#include "common/Assert.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
constexpr static unsigned int kRTSize = 64;
@ -213,14 +214,16 @@ class DepthStencilStateTest : public DawnTest {
dawn::BindGroup bindGroup = utils::MakeBindGroup(device, bindGroupLayout, {{0, buffer, 0, sizeof(TriangleData)}});
// Create a pipeline for the triangles with the test spec's depth stencil state
dawn::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetDepthStencilAttachmentFormat(dawn::TextureFormat::D32FloatS8Uint)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetDepthStencilState(test.depthStencilState)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.layout = pipelineLayout;
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
descriptor.depthStencilState = test.depthStencilState;
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
pass.SetRenderPipeline(pipeline);
pass.SetStencilReference(test.stencil); // Set the stencil reference

View File

@ -14,6 +14,7 @@
#include "tests/DawnTest.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
constexpr uint32_t kRTSize = 4;
@ -46,14 +47,16 @@ class DrawElementsTest : public DawnTest {
})"
);
pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleStrip)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetIndexFormat(dawn::IndexFormat::Uint32)
.SetInputState(inputState)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
descriptor.indexFormat = dawn::IndexFormat::Uint32;
descriptor.inputState = inputState;
descriptor.cColorAttachments[0].format =
renderPass.colorFormat;
pipeline = device.CreateRenderPipeline(&descriptor);
vertexBuffer = utils::CreateBufferFromData<float>(device, dawn::BufferUsageBit::Vertex, {
-1.0f, -1.0f, 0.0f, 1.0f,

View File

@ -15,6 +15,7 @@
#include "tests/DawnTest.h"
#include "common/Assert.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
constexpr uint32_t kRTSize = 400;
@ -51,14 +52,16 @@ class IndexFormatTest : public DawnTest {
})"
);
return device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleStrip)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetIndexFormat(format)
.SetInputState(inputState)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
descriptor.indexFormat = format;
descriptor.inputState = inputState;
descriptor.cColorAttachments[0].format =
renderPass.colorFormat;
return device.CreateRenderPipeline(&descriptor);
}
};

View File

@ -15,6 +15,7 @@
#include "tests/DawnTest.h"
#include "common/Assert.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
using dawn::InputStepMode;
@ -120,12 +121,14 @@ class InputStateTest : public DawnTest {
})"
);
return device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.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;
descriptor.cColorAttachments[0].format =
renderPass.colorFormat;
return device.CreateRenderPipeline(&descriptor);
}
struct InputSpec {

View File

@ -15,6 +15,7 @@
#include "tests/DawnTest.h"
#include "common/Assert.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
// Primitive topology tests work by drawing the following vertices with all the different primitive topology states:
@ -185,13 +186,16 @@ class PrimitiveTopologyTest : public DawnTest {
// Draw the vertices with the given primitive topology and check the pixel values of the test locations
void DoTest(dawn::PrimitiveTopology primitiveTopology, const std::vector<LocationSpec> &locationSpecs) {
dawn::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState)
.SetPrimitiveTopology(primitiveTopology)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = primitiveTopology;
descriptor.inputState = inputState;
descriptor.cColorAttachments[0].format =
renderPass.colorFormat;
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
static const uint32_t zeroOffset = 0;
dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();

View File

@ -16,6 +16,7 @@
#include "common/Assert.h"
#include "common/Constants.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
#include <array>
@ -189,20 +190,18 @@ class PushConstantTest: public DawnTest {
blend.srcFactor = dawn::BlendFactor::One;
blend.dstFactor = dawn::BlendFactor::One;
dawn::BlendState blendState = device.CreateBlendStateBuilder()
.SetBlendEnabled(true)
.SetColorBlend(&blend)
.SetAlphaBlend(&blend)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.layout = layout;
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::PointList;
descriptor.cBlendStates[0] = device.CreateBlendStateBuilder()
.SetBlendEnabled(true)
.SetColorBlend(&blend)
.SetAlphaBlend(&blend)
.GetResult();
return device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(layout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::PointList)
.SetColorAttachmentBlendState(0, blendState)
.GetResult();
return device.CreateRenderPipeline(&descriptor);
}
};

View File

@ -14,6 +14,7 @@
#include "tests/DawnTest.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
#include <array>
@ -23,28 +24,29 @@ constexpr static unsigned int kRTSize = 16;
class DrawQuad {
public:
DrawQuad() {}
DrawQuad(dawn::Device* device, const char* vsSource, const char* fsSource)
DrawQuad(dawn::Device device, const char* vsSource, const char* fsSource)
: device(device) {
vsModule = utils::CreateShaderModule(*device, dawn::ShaderStage::Vertex, vsSource);
fsModule = utils::CreateShaderModule(*device, dawn::ShaderStage::Fragment, fsSource);
vsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, vsSource);
fsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, fsSource);
pipelineLayout = utils::MakeBasicPipelineLayout(*device, nullptr);
pipelineLayout = utils::MakeBasicPipelineLayout(device, nullptr);
}
void Draw(dawn::RenderPassEncoder* pass) {
auto renderPipeline = device->CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.layout = pipelineLayout;
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
auto renderPipeline = device.CreateRenderPipeline(&descriptor);
pass->SetRenderPipeline(renderPipeline);
pass->Draw(6, 1, 0, 0);
}
private:
dawn::Device* device = nullptr;
dawn::Device device;
dawn::ShaderModule vsModule = {};
dawn::ShaderModule fsModule = {};
dawn::PipelineLayout pipelineLayout = {};
@ -94,7 +96,7 @@ class RenderPassLoadOpTests : public DawnTest {
color = vec4(0.f, 0.f, 1.f, 1.f);
}
)";
blueQuad = DrawQuad(&device, vsSource, fsSource);
blueQuad = DrawQuad(device, vsSource, fsSource);
}
dawn::Texture renderTarget;

View File

@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <array>
#include <cmath>
#include "tests/DawnTest.h"
#include "common/Assert.h"
#include "common/Constants.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
constexpr static unsigned int kRTSize = 64;
@ -73,12 +73,14 @@ protected:
}
)");
mPipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, mRenderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);
pipelineDescriptor.layout = pipelineLayout;
pipelineDescriptor.cVertexStage.module = vsModule;
pipelineDescriptor.cFragmentStage.module = fsModule;
pipelineDescriptor.cColorAttachments[0].format =
mRenderPass.colorFormat;
mPipeline = device.CreateRenderPipeline(&pipelineDescriptor);
dawn::TextureDescriptor descriptor;
descriptor.dimension = dawn::TextureDimension::e2D;

View File

@ -14,6 +14,7 @@
#include "tests/DawnTest.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
class ScissorTest: public DawnTest {
@ -36,13 +37,13 @@ class ScissorTest: public DawnTest {
fragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
})");
dawn::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, format)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.cColorAttachments[0].format =
format;
return pipeline;
return device.CreateRenderPipeline(&descriptor);
}
};

View File

@ -17,6 +17,7 @@
#include "common/Assert.h"
#include "common/Constants.h"
#include "common/Math.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
#include <array>
@ -163,12 +164,14 @@ protected:
dawn::ShaderModule fsModule =
utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, fragmentShader);
dawn::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, mRenderPass.colorFormat)
.SetLayout(mPipelineLayout)
.SetStage(dawn::ShaderStage::Vertex, mVSModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor textureDescriptor(device);
textureDescriptor.cVertexStage.module = mVSModule;
textureDescriptor.cFragmentStage.module = fsModule;
textureDescriptor.layout = mPipelineLayout;
textureDescriptor.cColorAttachments[0].format =
mRenderPass.colorFormat;
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&textureDescriptor);
dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
{
@ -502,11 +505,13 @@ class TextureViewRenderingTest : public DawnTest {
dawn::ShaderModule oneColorFsModule =
utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, oneColorFragmentShader);
dawn::RenderPipeline oneColorPipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, kDefaultFormat)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, oneColorFsModule, "main")
.GetResult();
utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);
pipelineDescriptor.cVertexStage.module = vsModule;
pipelineDescriptor.cFragmentStage.module = oneColorFsModule;
pipelineDescriptor.cColorAttachments[0].format = kDefaultFormat;
dawn::RenderPipeline oneColorPipeline = device.CreateRenderPipeline(&pipelineDescriptor);
dawn::CommandBufferBuilder commandBufferBuilder = device.CreateCommandBufferBuilder();
{
dawn::RenderPassEncoder pass =

View File

@ -14,6 +14,7 @@
#include "tests/DawnTest.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
class ViewportOrientationTests : public DawnTest {};
@ -35,12 +36,14 @@ TEST_P(ViewportOrientationTests, OriginAt0x0) {
fragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
})");
dawn::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetStage(dawn::ShaderStage::Vertex, vsModule, "main")
.SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(dawn::PrimitiveTopology::PointList)
.GetResult();
utils::ComboRenderPipelineDescriptor descriptor(device);
descriptor.cVertexStage.module = vsModule;
descriptor.cFragmentStage.module = fsModule;
descriptor.primitiveTopology = dawn::PrimitiveTopology::PointList;
descriptor.cColorAttachments[0].format =
renderPass.colorFormat;
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
{

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;

View File

@ -0,0 +1,65 @@
// Copyright 2018 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 "utils/ComboRenderPipelineDescriptor.h"
#include "utils/DawnHelpers.h"
namespace utils {
ComboRenderPipelineDescriptor::ComboRenderPipelineDescriptor(const dawn::Device& device) {
dawn::RenderPipelineDescriptor* descriptor = this;
descriptor->indexFormat = dawn::IndexFormat::Uint32;
descriptor->primitiveTopology = dawn::PrimitiveTopology::TriangleList;
descriptor->sampleCount = 1;
// Set defaults for the vertex stage descriptor.
{
descriptor->vertexStage = &cVertexStage;
cVertexStage.entryPoint = "main";
}
// Set defaults for the fragment stage desriptor.
{
descriptor->fragmentStage = &cFragmentStage;
cFragmentStage.entryPoint = "main";
}
// Set defaults for the attachment states.
{
descriptor->attachmentsState = &cAttachmentsState;
cAttachmentsState.numColorAttachments = 1;
cAttachmentsState.colorAttachments = cColorAttachments;
cAttachmentsState.depthStencilAttachment = &cDepthStencilAttachment;
cAttachmentsState.hasDepthStencilAttachment = false;
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
cColorAttachments[i].format = dawn::TextureFormat::R8G8B8A8Unorm;
}
}
descriptor->inputState = device.CreateInputStateBuilder().GetResult();
descriptor->depthStencilState = device.CreateDepthStencilStateBuilder().GetResult();
descriptor->layout = utils::MakeBasicPipelineLayout(device, nullptr);
descriptor->numBlendStates = 1;
descriptor->blendStates = cBlendStates;
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
cBlendStates[i] = device.CreateBlendStateBuilder().GetResult();
}
}
} // namespace utils

View File

@ -0,0 +1,39 @@
// Copyright 2018 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.
#ifndef UTILS_COMBORENDERPIPELINEDESCRIPTOR_H_
#define UTILS_COMBORENDERPIPELINEDESCRIPTOR_H_
#include <dawn/dawncpp.h>
#include "common/Constants.h"
namespace utils {
class ComboRenderPipelineDescriptor : public dawn::RenderPipelineDescriptor {
public:
ComboRenderPipelineDescriptor(const dawn::Device& device);
dawn::PipelineStageDescriptor cVertexStage;
dawn::PipelineStageDescriptor cFragmentStage;
dawn::AttachmentsStateDescriptor cAttachmentsState;
dawn::AttachmentDescriptor cColorAttachments[kMaxColorAttachments];
dawn::AttachmentDescriptor cDepthStencilAttachment;
dawn::BlendState cBlendStates[kMaxColorAttachments];
};
} // namespace utils
#endif // UTILS_COMBORENDERPIPELINEDESCRIPTOR_H_