Deduplicate AttachmentState shared by RenderPipeline and RenderPasses

This both deduplicates shared state by multiple passes or pipelines and
makes checking pipeline compatibility a single pointer check. It will be
useful for also checking RenderBundle compatibility.

Bug: dawn:154
Change-Id: I0fb289fab5ac76a7fbd500f64b8a6409a246ab32
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9461
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Austin Eng 2019-07-26 19:08:18 +00:00 committed by Commit Bot service account
parent e69627f35e
commit b98f0faa4d
13 changed files with 347 additions and 102 deletions

View File

@ -104,6 +104,8 @@ source_set("libdawn_native_sources") {
sources += [ sources += [
"src/dawn_native/Adapter.cpp", "src/dawn_native/Adapter.cpp",
"src/dawn_native/Adapter.h", "src/dawn_native/Adapter.h",
"src/dawn_native/AttachmentState.cpp",
"src/dawn_native/AttachmentState.h",
"src/dawn_native/BackendConnection.cpp", "src/dawn_native/BackendConnection.cpp",
"src/dawn_native/BackendConnection.h", "src/dawn_native/BackendConnection.h",
"src/dawn_native/BindGroup.cpp", "src/dawn_native/BindGroup.cpp",

View File

@ -0,0 +1,146 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn_native/AttachmentState.h"
#include "common/BitSetIterator.h"
#include "common/HashUtils.h"
#include "dawn_native/Device.h"
#include "dawn_native/Texture.h"
namespace dawn_native {
AttachmentStateBlueprint::AttachmentStateBlueprint(const RenderPipelineDescriptor* descriptor)
: mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr),
mSampleCount(descriptor->sampleCount) {
for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) {
ASSERT(descriptor->colorStates[i] != nullptr);
mColorAttachmentsSet.set(i);
mColorFormats[i] = descriptor->colorStates[i]->format;
}
if (mHasDepthStencilAttachment) {
mDepthStencilFormat = descriptor->depthStencilState->format;
}
}
AttachmentStateBlueprint::AttachmentStateBlueprint(const RenderPassDescriptor* descriptor)
: mHasDepthStencilAttachment(descriptor->depthStencilAttachment != nullptr) {
for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
TextureViewBase* attachment = descriptor->colorAttachments[i]->attachment;
mColorAttachmentsSet.set(i);
mColorFormats[i] = attachment->GetFormat().format;
if (mSampleCount == 0) {
mSampleCount = attachment->GetTexture()->GetSampleCount();
} else {
ASSERT(mSampleCount == attachment->GetTexture()->GetSampleCount());
}
}
if (mHasDepthStencilAttachment) {
TextureViewBase* attachment = descriptor->depthStencilAttachment->attachment;
mDepthStencilFormat = attachment->GetFormat().format;
if (mSampleCount == 0) {
mSampleCount = attachment->GetTexture()->GetSampleCount();
} else {
ASSERT(mSampleCount == attachment->GetTexture()->GetSampleCount());
}
}
ASSERT(mSampleCount > 0);
}
AttachmentStateBlueprint::AttachmentStateBlueprint(const AttachmentStateBlueprint& rhs) =
default;
size_t AttachmentStateBlueprint::HashFunc::operator()(
const AttachmentStateBlueprint* attachmentState) const {
size_t hash = 0;
// Hash color formats
HashCombine(&hash, attachmentState->mColorAttachmentsSet);
for (uint32_t i : IterateBitSet(attachmentState->mColorAttachmentsSet)) {
HashCombine(&hash, attachmentState->mColorFormats[i]);
}
// Hash depth stencil attachments
if (attachmentState->mHasDepthStencilAttachment) {
HashCombine(&hash, attachmentState->mDepthStencilFormat);
}
// Hash sample count
HashCombine(&hash, attachmentState->mSampleCount);
return hash;
}
bool AttachmentStateBlueprint::EqualityFunc::operator()(
const AttachmentStateBlueprint* a,
const AttachmentStateBlueprint* b) const {
// Check set attachments
if (a->mColorAttachmentsSet != b->mColorAttachmentsSet ||
a->mHasDepthStencilAttachment != b->mHasDepthStencilAttachment) {
return false;
}
// Check color formats
for (uint32_t i : IterateBitSet(a->mColorAttachmentsSet)) {
if (a->mColorFormats[i] != b->mColorFormats[i]) {
return false;
}
}
// Check depth stencil format
if (a->mHasDepthStencilAttachment) {
if (a->mDepthStencilFormat != b->mDepthStencilFormat) {
return false;
}
}
// Check sample count
if (a->mSampleCount != b->mSampleCount) {
return false;
}
return true;
}
AttachmentState::AttachmentState(DeviceBase* device, const AttachmentStateBlueprint& blueprint)
: AttachmentStateBlueprint(blueprint), RefCounted(), mDevice(device) {
}
AttachmentState::~AttachmentState() {
mDevice->UncacheAttachmentState(this);
}
std::bitset<kMaxColorAttachments> AttachmentState::GetColorAttachmentsMask() const {
return mColorAttachmentsSet;
}
dawn::TextureFormat AttachmentState::GetColorAttachmentFormat(uint32_t index) const {
ASSERT(mColorAttachmentsSet[index]);
return mColorFormats[index];
}
bool AttachmentState::HasDepthStencilAttachment() const {
return mHasDepthStencilAttachment;
}
dawn::TextureFormat AttachmentState::GetDepthStencilFormat() const {
ASSERT(mHasDepthStencilAttachment);
return mDepthStencilFormat;
}
uint32_t AttachmentState::GetSampleCount() const {
return mSampleCount;
}
} // namespace dawn_native

View File

@ -0,0 +1,75 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DAWNNATIVE_ATTACHMENTSTATE_H_
#define DAWNNATIVE_ATTACHMENTSTATE_H_
#include "common/Constants.h"
#include "dawn_native/RefCounted.h"
#include "dawn_native/dawn_platform.h"
#include <array>
#include <bitset>
namespace dawn_native {
class DeviceBase;
// AttachmentStateBlueprint and AttachmentState are separated so the AttachmentState
// can be constructed by copying the blueprint state instead of traversing descriptors.
// Also, AttachmentStateBlueprint does not need a refcount like AttachmentState.
class AttachmentStateBlueprint {
public:
// Note: Descriptors must be validated before the AttachmentState is constructed.
AttachmentStateBlueprint(const RenderPipelineDescriptor* descriptor);
AttachmentStateBlueprint(const RenderPassDescriptor* descriptor);
AttachmentStateBlueprint(const AttachmentStateBlueprint& rhs);
// Functors necessary for the unordered_set<AttachmentState*>-based cache.
struct HashFunc {
size_t operator()(const AttachmentStateBlueprint* attachmentState) const;
};
struct EqualityFunc {
bool operator()(const AttachmentStateBlueprint* a,
const AttachmentStateBlueprint* b) const;
};
protected:
std::bitset<kMaxColorAttachments> mColorAttachmentsSet;
std::array<dawn::TextureFormat, kMaxColorAttachments> mColorFormats;
bool mHasDepthStencilAttachment = false;
dawn::TextureFormat mDepthStencilFormat;
uint32_t mSampleCount = 0;
};
class AttachmentState : public AttachmentStateBlueprint, public RefCounted {
public:
AttachmentState(DeviceBase* device, const AttachmentStateBlueprint& blueprint);
~AttachmentState() override;
std::bitset<kMaxColorAttachments> GetColorAttachmentsMask() const;
dawn::TextureFormat GetColorAttachmentFormat(uint32_t index) const;
bool HasDepthStencilAttachment() const;
dawn::TextureFormat GetDepthStencilFormat() const;
uint32_t GetSampleCount() const;
private:
DeviceBase* mDevice;
};
} // namespace dawn_native
#endif // DAWNNATIVE_ATTACHMENTSTATE_H_

View File

@ -678,22 +678,19 @@ namespace dawn_native {
BeginRenderPassCmd* cmd = BeginRenderPassCmd* cmd =
allocator->Allocate<BeginRenderPassCmd>(Command::BeginRenderPass); allocator->Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);
for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) { cmd->attachmentState = device->GetOrCreateAttachmentState(descriptor);
if (descriptor->colorAttachments[i] != nullptr) {
cmd->colorAttachmentsSet.set(i); for (uint32_t i : IterateBitSet(cmd->attachmentState->GetColorAttachmentsMask())) {
cmd->colorAttachments[i].view = descriptor->colorAttachments[i]->attachment; cmd->colorAttachments[i].view = descriptor->colorAttachments[i]->attachment;
cmd->colorAttachments[i].resolveTarget = cmd->colorAttachments[i].resolveTarget =
descriptor->colorAttachments[i]->resolveTarget; descriptor->colorAttachments[i]->resolveTarget;
cmd->colorAttachments[i].loadOp = descriptor->colorAttachments[i]->loadOp; cmd->colorAttachments[i].loadOp = descriptor->colorAttachments[i]->loadOp;
cmd->colorAttachments[i].storeOp = descriptor->colorAttachments[i]->storeOp; cmd->colorAttachments[i].storeOp = descriptor->colorAttachments[i]->storeOp;
cmd->colorAttachments[i].clearColor = cmd->colorAttachments[i].clearColor =
descriptor->colorAttachments[i]->clearColor; descriptor->colorAttachments[i]->clearColor;
}
} }
cmd->hasDepthStencilAttachment = descriptor->depthStencilAttachment != nullptr; if (cmd->attachmentState->HasDepthStencilAttachment()) {
if (cmd->hasDepthStencilAttachment) {
cmd->hasDepthStencilAttachment = true;
cmd->depthStencilAttachment.view = cmd->depthStencilAttachment.view =
descriptor->depthStencilAttachment->attachment; descriptor->depthStencilAttachment->attachment;
cmd->depthStencilAttachment.clearDepth = cmd->depthStencilAttachment.clearDepth =
@ -712,7 +709,6 @@ namespace dawn_native {
cmd->width = width; cmd->width = width;
cmd->height = height; cmd->height = height;
cmd->sampleCount = sampleCount;
return {}; return {};
}); });
@ -1071,7 +1067,7 @@ namespace dawn_native {
CommandBufferStateTracker persistentState; CommandBufferStateTracker persistentState;
// Track usage of the render pass attachments // Track usage of the render pass attachments
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
RenderPassColorAttachmentInfo* colorAttachment = &renderPass->colorAttachments[i]; RenderPassColorAttachmentInfo* colorAttachment = &renderPass->colorAttachments[i];
TextureBase* texture = colorAttachment->view->GetTexture(); TextureBase* texture = colorAttachment->view->GetTexture();
usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment); usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
@ -1083,7 +1079,7 @@ namespace dawn_native {
} }
} }
if (renderPass->hasDepthStencilAttachment) { if (renderPass->attachmentState->HasDepthStencilAttachment()) {
TextureBase* texture = renderPass->depthStencilAttachment.view->GetTexture(); TextureBase* texture = renderPass->depthStencilAttachment.view->GetTexture();
usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment); usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
} }

View File

@ -17,6 +17,7 @@
#include "common/Constants.h" #include "common/Constants.h"
#include "dawn_native/AttachmentState.h"
#include "dawn_native/Texture.h" #include "dawn_native/Texture.h"
#include "dawn_native/dawn_platform.h" #include "dawn_native/dawn_platform.h"
@ -80,15 +81,13 @@ namespace dawn_native {
}; };
struct BeginRenderPassCmd { struct BeginRenderPassCmd {
std::bitset<kMaxColorAttachments> colorAttachmentsSet; Ref<AttachmentState> attachmentState;
RenderPassColorAttachmentInfo colorAttachments[kMaxColorAttachments]; RenderPassColorAttachmentInfo colorAttachments[kMaxColorAttachments];
bool hasDepthStencilAttachment;
RenderPassDepthStencilAttachmentInfo depthStencilAttachment; RenderPassDepthStencilAttachmentInfo depthStencilAttachment;
// Cache the width, height and sample count of all attachments for convenience // Cache the width and height of all attachments for convenience
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
uint32_t sampleCount;
}; };
struct BufferCopy { struct BufferCopy {

View File

@ -15,6 +15,7 @@
#include "dawn_native/Device.h" #include "dawn_native/Device.h"
#include "dawn_native/Adapter.h" #include "dawn_native/Adapter.h"
#include "dawn_native/AttachmentState.h"
#include "dawn_native/BindGroup.h" #include "dawn_native/BindGroup.h"
#include "dawn_native/BindGroupLayout.h" #include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Buffer.h" #include "dawn_native/Buffer.h"
@ -47,6 +48,7 @@ namespace dawn_native {
std::unordered_set<Object*, typename Object::HashFunc, typename Object::EqualityFunc>; std::unordered_set<Object*, typename Object::HashFunc, typename Object::EqualityFunc>;
struct DeviceBase::Caches { struct DeviceBase::Caches {
ContentLessObjectCache<AttachmentStateBlueprint> attachmentStates;
ContentLessObjectCache<BindGroupLayoutBase> bindGroupLayouts; ContentLessObjectCache<BindGroupLayoutBase> bindGroupLayouts;
ContentLessObjectCache<ComputePipelineBase> computePipelines; ContentLessObjectCache<ComputePipelineBase> computePipelines;
ContentLessObjectCache<PipelineLayoutBase> pipelineLayouts; ContentLessObjectCache<PipelineLayoutBase> pipelineLayouts;
@ -249,6 +251,43 @@ namespace dawn_native {
ASSERT(removedCount == 1); ASSERT(removedCount == 1);
} }
AttachmentState* DeviceBase::GetOrCreateAttachmentState(
const RenderPipelineDescriptor* descriptor) {
AttachmentStateBlueprint blueprint(descriptor);
auto iter = mCaches->attachmentStates.find(&blueprint);
if (iter != mCaches->attachmentStates.end()) {
AttachmentState* cachedState = static_cast<AttachmentState*>(*iter);
cachedState->Reference();
return cachedState;
}
AttachmentState* attachmentState = new AttachmentState(this, blueprint);
mCaches->attachmentStates.insert(attachmentState);
return attachmentState;
}
AttachmentState* DeviceBase::GetOrCreateAttachmentState(
const RenderPassDescriptor* descriptor) {
AttachmentStateBlueprint blueprint(descriptor);
auto iter = mCaches->attachmentStates.find(&blueprint);
if (iter != mCaches->attachmentStates.end()) {
AttachmentState* cachedState = static_cast<AttachmentState*>(*iter);
cachedState->Reference();
return cachedState;
}
AttachmentState* attachmentState = new AttachmentState(this, blueprint);
mCaches->attachmentStates.insert(attachmentState);
return attachmentState;
}
void DeviceBase::UncacheAttachmentState(AttachmentState* obj) {
size_t removedCount = mCaches->attachmentStates.erase(obj);
ASSERT(removedCount == 1);
}
// Object creation API methods // Object creation API methods
BindGroupBase* DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor) { BindGroupBase* DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor) {

View File

@ -32,6 +32,7 @@ namespace dawn_native {
using ErrorCallback = void (*)(const char* errorMessage, void* userData); using ErrorCallback = void (*)(const char* errorMessage, void* userData);
class AdapterBase; class AdapterBase;
class AttachmentState;
class FenceSignalTracker; class FenceSignalTracker;
class DynamicUploader; class DynamicUploader;
class StagingBufferBase; class StagingBufferBase;
@ -113,6 +114,10 @@ namespace dawn_native {
const ShaderModuleDescriptor* descriptor); const ShaderModuleDescriptor* descriptor);
void UncacheShaderModule(ShaderModuleBase* obj); void UncacheShaderModule(ShaderModuleBase* obj);
AttachmentState* GetOrCreateAttachmentState(const RenderPipelineDescriptor* descriptor);
AttachmentState* GetOrCreateAttachmentState(const RenderPassDescriptor* descriptor);
void UncacheAttachmentState(AttachmentState* obj);
// Dawn API // Dawn API
BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor); BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor);
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor); BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);

View File

@ -349,9 +349,8 @@ namespace dawn_native {
descriptor->layout, descriptor->layout,
dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment), dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment),
mVertexInput(*descriptor->vertexInput), mVertexInput(*descriptor->vertexInput),
mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr), mAttachmentState(device->GetOrCreateAttachmentState(descriptor)),
mPrimitiveTopology(descriptor->primitiveTopology), mPrimitiveTopology(descriptor->primitiveTopology),
mSampleCount(descriptor->sampleCount),
mSampleMask(descriptor->sampleMask), mSampleMask(descriptor->sampleMask),
mAlphaToCoverageEnabled(descriptor->alphaToCoverageEnabled), mAlphaToCoverageEnabled(descriptor->alphaToCoverageEnabled),
mVertexModule(descriptor->vertexStage->module), mVertexModule(descriptor->vertexStage->module),
@ -385,7 +384,7 @@ namespace dawn_native {
mRasterizationState = RasterizationStateDescriptor(); mRasterizationState = RasterizationStateDescriptor();
} }
if (mHasDepthStencilAttachment) { if (mAttachmentState->HasDepthStencilAttachment()) {
mDepthStencilState = *descriptor->depthStencilState; mDepthStencilState = *descriptor->depthStencilState;
} else { } else {
// These default values below are useful for backends to fill information. // These default values below are useful for backends to fill information.
@ -406,8 +405,7 @@ namespace dawn_native {
mDepthStencilState.stencilWriteMask = 0xff; mDepthStencilState.stencilWriteMask = 0xff;
} }
for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) { for (uint32_t i : IterateBitSet(mAttachmentState->GetColorAttachmentsMask())) {
mColorAttachmentsSet.set(i);
mColorStates[i] = *descriptor->colorStates[i]; mColorStates[i] = *descriptor->colorStates[i];
} }
@ -487,12 +485,12 @@ namespace dawn_native {
std::bitset<kMaxColorAttachments> RenderPipelineBase::GetColorAttachmentsMask() const { std::bitset<kMaxColorAttachments> RenderPipelineBase::GetColorAttachmentsMask() const {
ASSERT(!IsError()); ASSERT(!IsError());
return mColorAttachmentsSet; return mAttachmentState->GetColorAttachmentsMask();
} }
bool RenderPipelineBase::HasDepthStencilAttachment() const { bool RenderPipelineBase::HasDepthStencilAttachment() const {
ASSERT(!IsError()); ASSERT(!IsError());
return mHasDepthStencilAttachment; return mAttachmentState->HasDepthStencilAttachment();
} }
dawn::TextureFormat RenderPipelineBase::GetColorAttachmentFormat(uint32_t attachment) const { dawn::TextureFormat RenderPipelineBase::GetColorAttachmentFormat(uint32_t attachment) const {
@ -502,49 +500,22 @@ namespace dawn_native {
dawn::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const { dawn::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const {
ASSERT(!IsError()); ASSERT(!IsError());
ASSERT(mHasDepthStencilAttachment); ASSERT(mAttachmentState->HasDepthStencilAttachment());
return mDepthStencilState.format; return mDepthStencilState.format;
} }
uint32_t RenderPipelineBase::GetSampleCount() const { uint32_t RenderPipelineBase::GetSampleCount() const {
ASSERT(!IsError()); ASSERT(!IsError());
return mSampleCount; return mAttachmentState->GetSampleCount();
} }
MaybeError RenderPipelineBase::ValidateCompatibleWith( MaybeError RenderPipelineBase::ValidateCompatibleWith(
const BeginRenderPassCmd* renderPass) const { const BeginRenderPassCmd* renderPass) const {
ASSERT(!IsError()); ASSERT(!IsError());
// TODO(cwallez@chromium.org): This is called on every SetPipeline command. Optimize it for
// example by caching some "attachment compatibility" object that would make the
// compatibility check a single pointer comparison.
if (renderPass->colorAttachmentsSet != mColorAttachmentsSet) { if (renderPass->attachmentState.Get() != mAttachmentState.Get()) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"Pipeline doesn't have same color attachments set as renderPass"); "Pipeline attachment state is not compatible with render pass");
}
for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) {
if (renderPass->colorAttachments[i].view->GetFormat().format !=
mColorStates[i].format) {
return DAWN_VALIDATION_ERROR(
"Pipeline color attachment format doesn't match renderPass");
}
}
if (renderPass->hasDepthStencilAttachment != mHasDepthStencilAttachment) {
return DAWN_VALIDATION_ERROR(
"Pipeline depth stencil attachment doesn't match renderPass");
}
if (mHasDepthStencilAttachment &&
(renderPass->depthStencilAttachment.view->GetFormat().format !=
mDepthStencilState.format)) {
return DAWN_VALIDATION_ERROR(
"Pipeline depth stencil attachment format doesn't match renderPass");
}
if (renderPass->sampleCount != mSampleCount) {
return DAWN_VALIDATION_ERROR("Pipeline sample count doesn't match renderPass");
} }
return {}; return {};
@ -564,20 +535,23 @@ namespace dawn_native {
HashCombine(&hash, pipeline->mVertexModule.Get(), pipeline->mFragmentEntryPoint); HashCombine(&hash, pipeline->mVertexModule.Get(), pipeline->mFragmentEntryPoint);
HashCombine(&hash, pipeline->mFragmentModule.Get(), pipeline->mFragmentEntryPoint); HashCombine(&hash, pipeline->mFragmentModule.Get(), pipeline->mFragmentEntryPoint);
// Hierarchically hash the attachment state.
// It contains the attachments set, texture formats, and sample count.
HashCombine(&hash, pipeline->mAttachmentState.Get());
// Hash attachments // Hash attachments
HashCombine(&hash, pipeline->mColorAttachmentsSet); for (uint32_t i : IterateBitSet(pipeline->mAttachmentState->GetColorAttachmentsMask())) {
for (uint32_t i : IterateBitSet(pipeline->mColorAttachmentsSet)) {
const ColorStateDescriptor& desc = *pipeline->GetColorStateDescriptor(i); const ColorStateDescriptor& desc = *pipeline->GetColorStateDescriptor(i);
HashCombine(&hash, desc.format, desc.writeMask); HashCombine(&hash, desc.writeMask);
HashCombine(&hash, desc.colorBlend.operation, desc.colorBlend.srcFactor, HashCombine(&hash, desc.colorBlend.operation, desc.colorBlend.srcFactor,
desc.colorBlend.dstFactor); desc.colorBlend.dstFactor);
HashCombine(&hash, desc.alphaBlend.operation, desc.alphaBlend.srcFactor, HashCombine(&hash, desc.alphaBlend.operation, desc.alphaBlend.srcFactor,
desc.alphaBlend.dstFactor); desc.alphaBlend.dstFactor);
} }
if (pipeline->mHasDepthStencilAttachment) { if (pipeline->mAttachmentState->HasDepthStencilAttachment()) {
const DepthStencilStateDescriptor& desc = pipeline->mDepthStencilState; const DepthStencilStateDescriptor& desc = pipeline->mDepthStencilState;
HashCombine(&hash, desc.format, desc.depthWriteEnabled, desc.depthCompare); HashCombine(&hash, desc.depthWriteEnabled, desc.depthCompare);
HashCombine(&hash, desc.stencilReadMask, desc.stencilWriteMask); HashCombine(&hash, desc.stencilReadMask, desc.stencilWriteMask);
HashCombine(&hash, desc.stencilFront.compare, desc.stencilFront.failOp, HashCombine(&hash, desc.stencilFront.compare, desc.stencilFront.failOp,
desc.stencilFront.depthFailOp, desc.stencilFront.passOp); desc.stencilFront.depthFailOp, desc.stencilFront.passOp);
@ -608,8 +582,8 @@ namespace dawn_native {
} }
// Hash other state // Hash other state
HashCombine(&hash, pipeline->mSampleCount, pipeline->mPrimitiveTopology, HashCombine(&hash, pipeline->mPrimitiveTopology, pipeline->mSampleMask,
pipeline->mSampleMask, pipeline->mAlphaToCoverageEnabled); pipeline->mAlphaToCoverageEnabled);
return hash; return hash;
} }
@ -624,16 +598,16 @@ namespace dawn_native {
return false; return false;
} }
// Check attachments // Check the attachment state.
if (a->mColorAttachmentsSet != b->mColorAttachmentsSet || // It contains the attachments set, texture formats, and sample count.
a->mHasDepthStencilAttachment != b->mHasDepthStencilAttachment) { if (a->mAttachmentState.Get() != b->mAttachmentState.Get()) {
return false; return false;
} }
for (uint32_t i : IterateBitSet(a->mColorAttachmentsSet)) { for (uint32_t i : IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) {
const ColorStateDescriptor& descA = *a->GetColorStateDescriptor(i); const ColorStateDescriptor& descA = *a->GetColorStateDescriptor(i);
const ColorStateDescriptor& descB = *b->GetColorStateDescriptor(i); const ColorStateDescriptor& descB = *b->GetColorStateDescriptor(i);
if (descA.format != descB.format || descA.writeMask != descB.writeMask) { if (descA.writeMask != descB.writeMask) {
return false; return false;
} }
if (descA.colorBlend.operation != descB.colorBlend.operation || if (descA.colorBlend.operation != descB.colorBlend.operation ||
@ -648,11 +622,10 @@ namespace dawn_native {
} }
} }
if (a->mHasDepthStencilAttachment) { if (a->mAttachmentState->HasDepthStencilAttachment()) {
const DepthStencilStateDescriptor& descA = a->mDepthStencilState; const DepthStencilStateDescriptor& descA = a->mDepthStencilState;
const DepthStencilStateDescriptor& descB = b->mDepthStencilState; const DepthStencilStateDescriptor& descB = b->mDepthStencilState;
if (descA.format != descB.format || if (descA.depthWriteEnabled != descB.depthWriteEnabled ||
descA.depthWriteEnabled != descB.depthWriteEnabled ||
descA.depthCompare != descB.depthCompare) { descA.depthCompare != descB.depthCompare) {
return false; return false;
} }
@ -720,8 +693,7 @@ namespace dawn_native {
} }
// Check other state // Check other state
if (a->mSampleCount != b->mSampleCount || a->mPrimitiveTopology != b->mPrimitiveTopology || if (a->mPrimitiveTopology != b->mPrimitiveTopology || a->mSampleMask != b->mSampleMask ||
a->mSampleMask != b->mSampleMask ||
a->mAlphaToCoverageEnabled != b->mAlphaToCoverageEnabled) { a->mAlphaToCoverageEnabled != b->mAlphaToCoverageEnabled) {
return false; return false;
} }

View File

@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_RENDERPIPELINE_H_ #ifndef DAWNNATIVE_RENDERPIPELINE_H_
#define DAWNNATIVE_RENDERPIPELINE_H_ #define DAWNNATIVE_RENDERPIPELINE_H_
#include "dawn_native/AttachmentState.h"
#include "dawn_native/Pipeline.h" #include "dawn_native/Pipeline.h"
#include "dawn_native/dawn_platform.h" #include "dawn_native/dawn_platform.h"
@ -102,15 +103,13 @@ namespace dawn_native {
std::array<VertexBufferInfo, kMaxVertexBuffers> mInputInfos; std::array<VertexBufferInfo, kMaxVertexBuffers> mInputInfos;
// Attachments // Attachments
bool mHasDepthStencilAttachment = false; Ref<AttachmentState> mAttachmentState;
DepthStencilStateDescriptor mDepthStencilState; DepthStencilStateDescriptor mDepthStencilState;
std::bitset<kMaxColorAttachments> mColorAttachmentsSet;
std::array<ColorStateDescriptor, kMaxColorAttachments> mColorStates; std::array<ColorStateDescriptor, kMaxColorAttachments> mColorStates;
// Other state // Other state
dawn::PrimitiveTopology mPrimitiveTopology; dawn::PrimitiveTopology mPrimitiveTopology;
RasterizationStateDescriptor mRasterizationState; RasterizationStateDescriptor mRasterizationState;
uint32_t mSampleCount;
uint32_t mSampleMask; uint32_t mSampleMask;
bool mAlphaToCoverageEnabled; bool mAlphaToCoverageEnabled;

View File

@ -249,8 +249,9 @@ namespace dawn_native { namespace d3d12 {
void TrackRenderPass(const BeginRenderPassCmd* renderPass) { void TrackRenderPass(const BeginRenderPassCmd* renderPass) {
DAWN_ASSERT(mRTVHeap.Get() == nullptr && mDSVHeap.Get() == nullptr); DAWN_ASSERT(mRTVHeap.Get() == nullptr && mDSVHeap.Get() == nullptr);
mNumRTVs += static_cast<uint32_t>(renderPass->colorAttachmentsSet.count()); mNumRTVs += static_cast<uint32_t>(
if (renderPass->hasDepthStencilAttachment) { renderPass->attachmentState->GetColorAttachmentsMask().count());
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
++mNumDSVs; ++mNumDSVs;
} }
} }
@ -273,9 +274,11 @@ namespace dawn_native { namespace d3d12 {
OMSetRenderTargetArgs args = {}; OMSetRenderTargetArgs args = {};
unsigned int rtvIndex = 0; unsigned int rtvIndex = 0;
uint32_t rtvCount = static_cast<uint32_t>(renderPass->colorAttachmentsSet.count()); uint32_t rtvCount = static_cast<uint32_t>(
renderPass->attachmentState->GetColorAttachmentsMask().count());
DAWN_ASSERT(mAllocatedRTVs + rtvCount <= mNumRTVs); DAWN_ASSERT(mAllocatedRTVs + rtvCount <= mNumRTVs);
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
TextureView* view = ToBackend(renderPass->colorAttachments[i].view).Get(); TextureView* view = ToBackend(renderPass->colorAttachments[i].view).Get();
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRTVHeap.GetCPUHandle(mAllocatedRTVs); D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRTVHeap.GetCPUHandle(mAllocatedRTVs);
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = view->GetRTVDescriptor(); D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = view->GetRTVDescriptor();
@ -288,7 +291,7 @@ namespace dawn_native { namespace d3d12 {
} }
args.numRTVs = rtvIndex; args.numRTVs = rtvIndex;
if (renderPass->hasDepthStencilAttachment) { if (renderPass->attachmentState->HasDepthStencilAttachment()) {
DAWN_ASSERT(mAllocatedDSVs < mNumDSVs); DAWN_ASSERT(mAllocatedDSVs < mNumDSVs);
TextureView* view = ToBackend(renderPass->depthStencilAttachment.view).Get(); TextureView* view = ToBackend(renderPass->depthStencilAttachment.view).Get();
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDSVHeap.GetCPUHandle(mAllocatedDSVs); D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDSVHeap.GetCPUHandle(mAllocatedDSVs);
@ -372,7 +375,8 @@ namespace dawn_native { namespace d3d12 {
BeginRenderPassCmd* renderPass) { BeginRenderPassCmd* renderPass) {
ASSERT(renderPass != nullptr); ASSERT(renderPass != nullptr);
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
TextureViewBase* resolveTarget = TextureViewBase* resolveTarget =
renderPass->colorAttachments[i].resolveTarget.Get(); renderPass->colorAttachments[i].resolveTarget.Get();
if (resolveTarget == nullptr) { if (resolveTarget == nullptr) {
@ -759,7 +763,8 @@ namespace dawn_native { namespace d3d12 {
// Clear framebuffer attachments as needed and transition to render target // Clear framebuffer attachments as needed and transition to render target
{ {
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
auto& attachmentInfo = renderPass->colorAttachments[i]; auto& attachmentInfo = renderPass->colorAttachments[i];
TextureView* view = ToBackend(attachmentInfo.view.Get()); TextureView* view = ToBackend(attachmentInfo.view.Get());
@ -785,7 +790,7 @@ namespace dawn_native { namespace d3d12 {
} }
} }
if (renderPass->hasDepthStencilAttachment) { if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto& attachmentInfo = renderPass->depthStencilAttachment; auto& attachmentInfo = renderPass->depthStencilAttachment;
Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture()); Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture());
if ((texture->GetFormat().HasDepth() && if ((texture->GetFormat().HasDepth() &&
@ -864,7 +869,7 @@ namespace dawn_native { namespace d3d12 {
// TODO(brandon1.jones@intel.com): avoid calling this function and enable MSAA // TODO(brandon1.jones@intel.com): avoid calling this function and enable MSAA
// resolve in D3D12 render pass on the platforms that support this feature. // resolve in D3D12 render pass on the platforms that support this feature.
if (renderPass->sampleCount > 1) { if (renderPass->attachmentState->GetSampleCount() > 1) {
ResolveMultisampledRenderPass(commandList, renderPass); ResolveMultisampledRenderPass(commandList, renderPass);
} }
return; return;

View File

@ -50,7 +50,8 @@ namespace dawn_native { namespace metal {
MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(BeginRenderPassCmd* renderPass) { MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(BeginRenderPassCmd* renderPass) {
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor]; MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
auto& attachmentInfo = renderPass->colorAttachments[i]; auto& attachmentInfo = renderPass->colorAttachments[i];
if (attachmentInfo.loadOp == dawn::LoadOp::Clear) { if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
@ -83,7 +84,7 @@ namespace dawn_native { namespace metal {
} }
} }
if (renderPass->hasDepthStencilAttachment) { if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto& attachmentInfo = renderPass->depthStencilAttachment; auto& attachmentInfo = renderPass->depthStencilAttachment;
// TODO(jiawei.shao@intel.com): support rendering into a layer of a texture. // TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.

View File

@ -283,7 +283,8 @@ namespace dawn_native { namespace opengl {
GLuint readFbo = 0; GLuint readFbo = 0;
GLuint writeFbo = 0; GLuint writeFbo = 0;
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
if (renderPass->colorAttachments[i].resolveTarget.Get() != nullptr) { if (renderPass->colorAttachments[i].resolveTarget.Get() != nullptr) {
if (readFbo == 0) { if (readFbo == 0) {
ASSERT(writeFbo == 0); ASSERT(writeFbo == 0);
@ -590,7 +591,8 @@ namespace dawn_native { namespace opengl {
// Construct GL framebuffer // Construct GL framebuffer
unsigned int attachmentCount = 0; unsigned int attachmentCount = 0;
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
TextureViewBase* textureView = renderPass->colorAttachments[i].view.Get(); TextureViewBase* textureView = renderPass->colorAttachments[i].view.Get();
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle(); GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
@ -617,7 +619,7 @@ namespace dawn_native { namespace opengl {
} }
gl.DrawBuffers(attachmentCount, drawBuffers.data()); gl.DrawBuffers(attachmentCount, drawBuffers.data());
if (renderPass->hasDepthStencilAttachment) { if (renderPass->attachmentState->HasDepthStencilAttachment()) {
TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get(); TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get();
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle(); GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
const Format& format = textureView->GetTexture()->GetFormat(); const Format& format = textureView->GetTexture()->GetFormat();
@ -660,7 +662,8 @@ namespace dawn_native { namespace opengl {
// Clear framebuffer attachments as needed // Clear framebuffer attachments as needed
{ {
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
const auto& attachmentInfo = renderPass->colorAttachments[i]; const auto& attachmentInfo = renderPass->colorAttachments[i];
// Load op - color // Load op - color
@ -670,7 +673,7 @@ namespace dawn_native { namespace opengl {
} }
} }
if (renderPass->hasDepthStencilAttachment) { if (renderPass->attachmentState->HasDepthStencilAttachment()) {
const auto& attachmentInfo = renderPass->depthStencilAttachment; const auto& attachmentInfo = renderPass->depthStencilAttachment;
const Format& attachmentFormat = attachmentInfo.view->GetTexture()->GetFormat(); const Format& attachmentFormat = attachmentInfo.view->GetTexture()->GetFormat();
@ -710,7 +713,7 @@ namespace dawn_native { namespace opengl {
case Command::EndRenderPass: { case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>(); mCommands.NextCommand<EndRenderPassCmd>();
if (renderPass->sampleCount > 1) { if (renderPass->attachmentState->GetSampleCount() > 1) {
ResolveMultisampledRenderTargets(gl, renderPass); ResolveMultisampledRenderTargets(gl, renderPass);
} }
gl.DeleteFramebuffers(1, &fbo); gl.DeleteFramebuffers(1, &fbo);

View File

@ -197,7 +197,8 @@ namespace dawn_native { namespace vulkan {
{ {
RenderPassCacheQuery query; RenderPassCacheQuery query;
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
auto& attachmentInfo = renderPass->colorAttachments[i]; auto& attachmentInfo = renderPass->colorAttachments[i];
TextureView* view = ToBackend(attachmentInfo.view.Get()); TextureView* view = ToBackend(attachmentInfo.view.Get());
bool hasResolveTarget = attachmentInfo.resolveTarget.Get() != nullptr; bool hasResolveTarget = attachmentInfo.resolveTarget.Get() != nullptr;
@ -223,7 +224,7 @@ namespace dawn_native { namespace vulkan {
hasResolveTarget); hasResolveTarget);
} }
if (renderPass->hasDepthStencilAttachment) { if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto& attachmentInfo = renderPass->depthStencilAttachment; auto& attachmentInfo = renderPass->depthStencilAttachment;
query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat().format, query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat().format,
attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp); attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp);
@ -238,7 +239,7 @@ namespace dawn_native { namespace vulkan {
} }
} }
query.SetSampleCount(renderPass->sampleCount); query.SetSampleCount(renderPass->attachmentState->GetSampleCount());
renderPassVK = device->GetRenderPassCache()->GetRenderPass(query); renderPassVK = device->GetRenderPassCache()->GetRenderPass(query);
} }
@ -252,7 +253,8 @@ namespace dawn_native { namespace vulkan {
// Fill in the attachment info that will be chained in the framebuffer create info. // Fill in the attachment info that will be chained in the framebuffer create info.
std::array<VkImageView, kMaxColorAttachments * 2 + 1> attachments; std::array<VkImageView, kMaxColorAttachments * 2 + 1> attachments;
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
auto& attachmentInfo = renderPass->colorAttachments[i]; auto& attachmentInfo = renderPass->colorAttachments[i];
TextureView* view = ToBackend(attachmentInfo.view.Get()); TextureView* view = ToBackend(attachmentInfo.view.Get());
@ -266,7 +268,7 @@ namespace dawn_native { namespace vulkan {
attachmentCount++; attachmentCount++;
} }
if (renderPass->hasDepthStencilAttachment) { if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto& attachmentInfo = renderPass->depthStencilAttachment; auto& attachmentInfo = renderPass->depthStencilAttachment;
TextureView* view = ToBackend(attachmentInfo.view.Get()); TextureView* view = ToBackend(attachmentInfo.view.Get());
@ -278,7 +280,8 @@ namespace dawn_native { namespace vulkan {
attachmentCount++; attachmentCount++;
} }
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
if (renderPass->colorAttachments[i].resolveTarget.Get() != nullptr) { if (renderPass->colorAttachments[i].resolveTarget.Get() != nullptr) {
TextureView* view = TextureView* view =
ToBackend(renderPass->colorAttachments[i].resolveTarget.Get()); ToBackend(renderPass->colorAttachments[i].resolveTarget.Get());