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:
parent
e69627f35e
commit
b98f0faa4d
2
BUILD.gn
2
BUILD.gn
|
@ -104,6 +104,8 @@ source_set("libdawn_native_sources") {
|
|||
sources += [
|
||||
"src/dawn_native/Adapter.cpp",
|
||||
"src/dawn_native/Adapter.h",
|
||||
"src/dawn_native/AttachmentState.cpp",
|
||||
"src/dawn_native/AttachmentState.h",
|
||||
"src/dawn_native/BackendConnection.cpp",
|
||||
"src/dawn_native/BackendConnection.h",
|
||||
"src/dawn_native/BindGroup.cpp",
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -678,22 +678,19 @@ namespace dawn_native {
|
|||
BeginRenderPassCmd* cmd =
|
||||
allocator->Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);
|
||||
|
||||
for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
|
||||
if (descriptor->colorAttachments[i] != nullptr) {
|
||||
cmd->colorAttachmentsSet.set(i);
|
||||
cmd->colorAttachments[i].view = descriptor->colorAttachments[i]->attachment;
|
||||
cmd->colorAttachments[i].resolveTarget =
|
||||
descriptor->colorAttachments[i]->resolveTarget;
|
||||
cmd->colorAttachments[i].loadOp = descriptor->colorAttachments[i]->loadOp;
|
||||
cmd->colorAttachments[i].storeOp = descriptor->colorAttachments[i]->storeOp;
|
||||
cmd->colorAttachments[i].clearColor =
|
||||
descriptor->colorAttachments[i]->clearColor;
|
||||
}
|
||||
cmd->attachmentState = device->GetOrCreateAttachmentState(descriptor);
|
||||
|
||||
for (uint32_t i : IterateBitSet(cmd->attachmentState->GetColorAttachmentsMask())) {
|
||||
cmd->colorAttachments[i].view = descriptor->colorAttachments[i]->attachment;
|
||||
cmd->colorAttachments[i].resolveTarget =
|
||||
descriptor->colorAttachments[i]->resolveTarget;
|
||||
cmd->colorAttachments[i].loadOp = descriptor->colorAttachments[i]->loadOp;
|
||||
cmd->colorAttachments[i].storeOp = descriptor->colorAttachments[i]->storeOp;
|
||||
cmd->colorAttachments[i].clearColor =
|
||||
descriptor->colorAttachments[i]->clearColor;
|
||||
}
|
||||
|
||||
cmd->hasDepthStencilAttachment = descriptor->depthStencilAttachment != nullptr;
|
||||
if (cmd->hasDepthStencilAttachment) {
|
||||
cmd->hasDepthStencilAttachment = true;
|
||||
if (cmd->attachmentState->HasDepthStencilAttachment()) {
|
||||
cmd->depthStencilAttachment.view =
|
||||
descriptor->depthStencilAttachment->attachment;
|
||||
cmd->depthStencilAttachment.clearDepth =
|
||||
|
@ -712,7 +709,6 @@ namespace dawn_native {
|
|||
|
||||
cmd->width = width;
|
||||
cmd->height = height;
|
||||
cmd->sampleCount = sampleCount;
|
||||
|
||||
return {};
|
||||
});
|
||||
|
@ -1071,7 +1067,7 @@ namespace dawn_native {
|
|||
CommandBufferStateTracker persistentState;
|
||||
|
||||
// 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];
|
||||
TextureBase* texture = colorAttachment->view->GetTexture();
|
||||
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();
|
||||
usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "common/Constants.h"
|
||||
|
||||
#include "dawn_native/AttachmentState.h"
|
||||
#include "dawn_native/Texture.h"
|
||||
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
@ -80,15 +81,13 @@ namespace dawn_native {
|
|||
};
|
||||
|
||||
struct BeginRenderPassCmd {
|
||||
std::bitset<kMaxColorAttachments> colorAttachmentsSet;
|
||||
Ref<AttachmentState> attachmentState;
|
||||
RenderPassColorAttachmentInfo colorAttachments[kMaxColorAttachments];
|
||||
bool hasDepthStencilAttachment;
|
||||
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 height;
|
||||
uint32_t sampleCount;
|
||||
};
|
||||
|
||||
struct BufferCopy {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "dawn_native/Device.h"
|
||||
|
||||
#include "dawn_native/Adapter.h"
|
||||
#include "dawn_native/AttachmentState.h"
|
||||
#include "dawn_native/BindGroup.h"
|
||||
#include "dawn_native/BindGroupLayout.h"
|
||||
#include "dawn_native/Buffer.h"
|
||||
|
@ -47,6 +48,7 @@ namespace dawn_native {
|
|||
std::unordered_set<Object*, typename Object::HashFunc, typename Object::EqualityFunc>;
|
||||
|
||||
struct DeviceBase::Caches {
|
||||
ContentLessObjectCache<AttachmentStateBlueprint> attachmentStates;
|
||||
ContentLessObjectCache<BindGroupLayoutBase> bindGroupLayouts;
|
||||
ContentLessObjectCache<ComputePipelineBase> computePipelines;
|
||||
ContentLessObjectCache<PipelineLayoutBase> pipelineLayouts;
|
||||
|
@ -249,6 +251,43 @@ namespace dawn_native {
|
|||
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
|
||||
|
||||
BindGroupBase* DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor) {
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace dawn_native {
|
|||
using ErrorCallback = void (*)(const char* errorMessage, void* userData);
|
||||
|
||||
class AdapterBase;
|
||||
class AttachmentState;
|
||||
class FenceSignalTracker;
|
||||
class DynamicUploader;
|
||||
class StagingBufferBase;
|
||||
|
@ -113,6 +114,10 @@ namespace dawn_native {
|
|||
const ShaderModuleDescriptor* descriptor);
|
||||
void UncacheShaderModule(ShaderModuleBase* obj);
|
||||
|
||||
AttachmentState* GetOrCreateAttachmentState(const RenderPipelineDescriptor* descriptor);
|
||||
AttachmentState* GetOrCreateAttachmentState(const RenderPassDescriptor* descriptor);
|
||||
void UncacheAttachmentState(AttachmentState* obj);
|
||||
|
||||
// Dawn API
|
||||
BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor);
|
||||
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
|
||||
|
|
|
@ -349,9 +349,8 @@ namespace dawn_native {
|
|||
descriptor->layout,
|
||||
dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment),
|
||||
mVertexInput(*descriptor->vertexInput),
|
||||
mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr),
|
||||
mAttachmentState(device->GetOrCreateAttachmentState(descriptor)),
|
||||
mPrimitiveTopology(descriptor->primitiveTopology),
|
||||
mSampleCount(descriptor->sampleCount),
|
||||
mSampleMask(descriptor->sampleMask),
|
||||
mAlphaToCoverageEnabled(descriptor->alphaToCoverageEnabled),
|
||||
mVertexModule(descriptor->vertexStage->module),
|
||||
|
@ -385,7 +384,7 @@ namespace dawn_native {
|
|||
mRasterizationState = RasterizationStateDescriptor();
|
||||
}
|
||||
|
||||
if (mHasDepthStencilAttachment) {
|
||||
if (mAttachmentState->HasDepthStencilAttachment()) {
|
||||
mDepthStencilState = *descriptor->depthStencilState;
|
||||
} else {
|
||||
// These default values below are useful for backends to fill information.
|
||||
|
@ -406,8 +405,7 @@ namespace dawn_native {
|
|||
mDepthStencilState.stencilWriteMask = 0xff;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) {
|
||||
mColorAttachmentsSet.set(i);
|
||||
for (uint32_t i : IterateBitSet(mAttachmentState->GetColorAttachmentsMask())) {
|
||||
mColorStates[i] = *descriptor->colorStates[i];
|
||||
}
|
||||
|
||||
|
@ -487,12 +485,12 @@ namespace dawn_native {
|
|||
|
||||
std::bitset<kMaxColorAttachments> RenderPipelineBase::GetColorAttachmentsMask() const {
|
||||
ASSERT(!IsError());
|
||||
return mColorAttachmentsSet;
|
||||
return mAttachmentState->GetColorAttachmentsMask();
|
||||
}
|
||||
|
||||
bool RenderPipelineBase::HasDepthStencilAttachment() const {
|
||||
ASSERT(!IsError());
|
||||
return mHasDepthStencilAttachment;
|
||||
return mAttachmentState->HasDepthStencilAttachment();
|
||||
}
|
||||
|
||||
dawn::TextureFormat RenderPipelineBase::GetColorAttachmentFormat(uint32_t attachment) const {
|
||||
|
@ -502,49 +500,22 @@ namespace dawn_native {
|
|||
|
||||
dawn::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const {
|
||||
ASSERT(!IsError());
|
||||
ASSERT(mHasDepthStencilAttachment);
|
||||
ASSERT(mAttachmentState->HasDepthStencilAttachment());
|
||||
return mDepthStencilState.format;
|
||||
}
|
||||
|
||||
uint32_t RenderPipelineBase::GetSampleCount() const {
|
||||
ASSERT(!IsError());
|
||||
return mSampleCount;
|
||||
return mAttachmentState->GetSampleCount();
|
||||
}
|
||||
|
||||
MaybeError RenderPipelineBase::ValidateCompatibleWith(
|
||||
const BeginRenderPassCmd* renderPass) const {
|
||||
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(
|
||||
"Pipeline doesn't have same color attachments set as renderPass");
|
||||
}
|
||||
|
||||
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");
|
||||
"Pipeline attachment state is not compatible with render pass");
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -564,20 +535,23 @@ namespace dawn_native {
|
|||
HashCombine(&hash, pipeline->mVertexModule.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
|
||||
HashCombine(&hash, pipeline->mColorAttachmentsSet);
|
||||
for (uint32_t i : IterateBitSet(pipeline->mColorAttachmentsSet)) {
|
||||
for (uint32_t i : IterateBitSet(pipeline->mAttachmentState->GetColorAttachmentsMask())) {
|
||||
const ColorStateDescriptor& desc = *pipeline->GetColorStateDescriptor(i);
|
||||
HashCombine(&hash, desc.format, desc.writeMask);
|
||||
HashCombine(&hash, desc.writeMask);
|
||||
HashCombine(&hash, desc.colorBlend.operation, desc.colorBlend.srcFactor,
|
||||
desc.colorBlend.dstFactor);
|
||||
HashCombine(&hash, desc.alphaBlend.operation, desc.alphaBlend.srcFactor,
|
||||
desc.alphaBlend.dstFactor);
|
||||
}
|
||||
|
||||
if (pipeline->mHasDepthStencilAttachment) {
|
||||
if (pipeline->mAttachmentState->HasDepthStencilAttachment()) {
|
||||
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.stencilFront.compare, desc.stencilFront.failOp,
|
||||
desc.stencilFront.depthFailOp, desc.stencilFront.passOp);
|
||||
|
@ -608,8 +582,8 @@ namespace dawn_native {
|
|||
}
|
||||
|
||||
// Hash other state
|
||||
HashCombine(&hash, pipeline->mSampleCount, pipeline->mPrimitiveTopology,
|
||||
pipeline->mSampleMask, pipeline->mAlphaToCoverageEnabled);
|
||||
HashCombine(&hash, pipeline->mPrimitiveTopology, pipeline->mSampleMask,
|
||||
pipeline->mAlphaToCoverageEnabled);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
@ -624,16 +598,16 @@ namespace dawn_native {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check attachments
|
||||
if (a->mColorAttachmentsSet != b->mColorAttachmentsSet ||
|
||||
a->mHasDepthStencilAttachment != b->mHasDepthStencilAttachment) {
|
||||
// Check the attachment state.
|
||||
// It contains the attachments set, texture formats, and sample count.
|
||||
if (a->mAttachmentState.Get() != b->mAttachmentState.Get()) {
|
||||
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& descB = *b->GetColorStateDescriptor(i);
|
||||
if (descA.format != descB.format || descA.writeMask != descB.writeMask) {
|
||||
if (descA.writeMask != descB.writeMask) {
|
||||
return false;
|
||||
}
|
||||
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& descB = b->mDepthStencilState;
|
||||
if (descA.format != descB.format ||
|
||||
descA.depthWriteEnabled != descB.depthWriteEnabled ||
|
||||
if (descA.depthWriteEnabled != descB.depthWriteEnabled ||
|
||||
descA.depthCompare != descB.depthCompare) {
|
||||
return false;
|
||||
}
|
||||
|
@ -720,8 +693,7 @@ namespace dawn_native {
|
|||
}
|
||||
|
||||
// Check other state
|
||||
if (a->mSampleCount != b->mSampleCount || a->mPrimitiveTopology != b->mPrimitiveTopology ||
|
||||
a->mSampleMask != b->mSampleMask ||
|
||||
if (a->mPrimitiveTopology != b->mPrimitiveTopology || a->mSampleMask != b->mSampleMask ||
|
||||
a->mAlphaToCoverageEnabled != b->mAlphaToCoverageEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef DAWNNATIVE_RENDERPIPELINE_H_
|
||||
#define DAWNNATIVE_RENDERPIPELINE_H_
|
||||
|
||||
#include "dawn_native/AttachmentState.h"
|
||||
#include "dawn_native/Pipeline.h"
|
||||
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
@ -102,15 +103,13 @@ namespace dawn_native {
|
|||
std::array<VertexBufferInfo, kMaxVertexBuffers> mInputInfos;
|
||||
|
||||
// Attachments
|
||||
bool mHasDepthStencilAttachment = false;
|
||||
Ref<AttachmentState> mAttachmentState;
|
||||
DepthStencilStateDescriptor mDepthStencilState;
|
||||
std::bitset<kMaxColorAttachments> mColorAttachmentsSet;
|
||||
std::array<ColorStateDescriptor, kMaxColorAttachments> mColorStates;
|
||||
|
||||
// Other state
|
||||
dawn::PrimitiveTopology mPrimitiveTopology;
|
||||
RasterizationStateDescriptor mRasterizationState;
|
||||
uint32_t mSampleCount;
|
||||
uint32_t mSampleMask;
|
||||
bool mAlphaToCoverageEnabled;
|
||||
|
||||
|
|
|
@ -249,8 +249,9 @@ namespace dawn_native { namespace d3d12 {
|
|||
void TrackRenderPass(const BeginRenderPassCmd* renderPass) {
|
||||
DAWN_ASSERT(mRTVHeap.Get() == nullptr && mDSVHeap.Get() == nullptr);
|
||||
|
||||
mNumRTVs += static_cast<uint32_t>(renderPass->colorAttachmentsSet.count());
|
||||
if (renderPass->hasDepthStencilAttachment) {
|
||||
mNumRTVs += static_cast<uint32_t>(
|
||||
renderPass->attachmentState->GetColorAttachmentsMask().count());
|
||||
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
|
||||
++mNumDSVs;
|
||||
}
|
||||
}
|
||||
|
@ -273,9 +274,11 @@ namespace dawn_native { namespace d3d12 {
|
|||
OMSetRenderTargetArgs args = {};
|
||||
|
||||
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);
|
||||
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
|
||||
for (uint32_t i :
|
||||
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
||||
TextureView* view = ToBackend(renderPass->colorAttachments[i].view).Get();
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRTVHeap.GetCPUHandle(mAllocatedRTVs);
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = view->GetRTVDescriptor();
|
||||
|
@ -288,7 +291,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
}
|
||||
args.numRTVs = rtvIndex;
|
||||
|
||||
if (renderPass->hasDepthStencilAttachment) {
|
||||
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
|
||||
DAWN_ASSERT(mAllocatedDSVs < mNumDSVs);
|
||||
TextureView* view = ToBackend(renderPass->depthStencilAttachment.view).Get();
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDSVHeap.GetCPUHandle(mAllocatedDSVs);
|
||||
|
@ -372,7 +375,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
BeginRenderPassCmd* renderPass) {
|
||||
ASSERT(renderPass != nullptr);
|
||||
|
||||
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
|
||||
for (uint32_t i :
|
||||
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
||||
TextureViewBase* resolveTarget =
|
||||
renderPass->colorAttachments[i].resolveTarget.Get();
|
||||
if (resolveTarget == nullptr) {
|
||||
|
@ -759,7 +763,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
// 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];
|
||||
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;
|
||||
Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture());
|
||||
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
|
||||
// resolve in D3D12 render pass on the platforms that support this feature.
|
||||
if (renderPass->sampleCount > 1) {
|
||||
if (renderPass->attachmentState->GetSampleCount() > 1) {
|
||||
ResolveMultisampledRenderPass(commandList, renderPass);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -50,7 +50,8 @@ namespace dawn_native { namespace metal {
|
|||
MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(BeginRenderPassCmd* renderPass) {
|
||||
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
|
||||
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
|
||||
for (uint32_t i :
|
||||
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
||||
auto& attachmentInfo = renderPass->colorAttachments[i];
|
||||
|
||||
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;
|
||||
|
||||
// TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.
|
||||
|
|
|
@ -283,7 +283,8 @@ namespace dawn_native { namespace opengl {
|
|||
GLuint readFbo = 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 (readFbo == 0) {
|
||||
ASSERT(writeFbo == 0);
|
||||
|
@ -590,7 +591,8 @@ namespace dawn_native { namespace opengl {
|
|||
// Construct GL framebuffer
|
||||
|
||||
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();
|
||||
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
|
||||
|
||||
|
@ -617,7 +619,7 @@ namespace dawn_native { namespace opengl {
|
|||
}
|
||||
gl.DrawBuffers(attachmentCount, drawBuffers.data());
|
||||
|
||||
if (renderPass->hasDepthStencilAttachment) {
|
||||
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
|
||||
TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get();
|
||||
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
|
||||
const Format& format = textureView->GetTexture()->GetFormat();
|
||||
|
@ -660,7 +662,8 @@ namespace dawn_native { namespace opengl {
|
|||
|
||||
// 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];
|
||||
|
||||
// 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 Format& attachmentFormat = attachmentInfo.view->GetTexture()->GetFormat();
|
||||
|
||||
|
@ -710,7 +713,7 @@ namespace dawn_native { namespace opengl {
|
|||
case Command::EndRenderPass: {
|
||||
mCommands.NextCommand<EndRenderPassCmd>();
|
||||
|
||||
if (renderPass->sampleCount > 1) {
|
||||
if (renderPass->attachmentState->GetSampleCount() > 1) {
|
||||
ResolveMultisampledRenderTargets(gl, renderPass);
|
||||
}
|
||||
gl.DeleteFramebuffers(1, &fbo);
|
||||
|
|
|
@ -197,7 +197,8 @@ namespace dawn_native { namespace vulkan {
|
|||
{
|
||||
RenderPassCacheQuery query;
|
||||
|
||||
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
|
||||
for (uint32_t i :
|
||||
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
||||
auto& attachmentInfo = renderPass->colorAttachments[i];
|
||||
TextureView* view = ToBackend(attachmentInfo.view.Get());
|
||||
bool hasResolveTarget = attachmentInfo.resolveTarget.Get() != nullptr;
|
||||
|
@ -223,7 +224,7 @@ namespace dawn_native { namespace vulkan {
|
|||
hasResolveTarget);
|
||||
}
|
||||
|
||||
if (renderPass->hasDepthStencilAttachment) {
|
||||
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
|
||||
auto& attachmentInfo = renderPass->depthStencilAttachment;
|
||||
query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat().format,
|
||||
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);
|
||||
}
|
||||
|
@ -252,7 +253,8 @@ namespace dawn_native { namespace vulkan {
|
|||
// Fill in the attachment info that will be chained in the framebuffer create info.
|
||||
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];
|
||||
TextureView* view = ToBackend(attachmentInfo.view.Get());
|
||||
|
||||
|
@ -266,7 +268,7 @@ namespace dawn_native { namespace vulkan {
|
|||
attachmentCount++;
|
||||
}
|
||||
|
||||
if (renderPass->hasDepthStencilAttachment) {
|
||||
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
|
||||
auto& attachmentInfo = renderPass->depthStencilAttachment;
|
||||
TextureView* view = ToBackend(attachmentInfo.view.Get());
|
||||
|
||||
|
@ -278,7 +280,8 @@ namespace dawn_native { namespace vulkan {
|
|||
attachmentCount++;
|
||||
}
|
||||
|
||||
for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
|
||||
for (uint32_t i :
|
||||
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
||||
if (renderPass->colorAttachments[i].resolveTarget.Get() != nullptr) {
|
||||
TextureView* view =
|
||||
ToBackend(renderPass->colorAttachments[i].resolveTarget.Get());
|
||||
|
|
Loading…
Reference in New Issue