dawn-cmake/src/backend/Framebuffer.cpp

185 lines
6.6 KiB
C++

// Copyright 2017 The NXT 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 "backend/Framebuffer.h"
#include "backend/Buffer.h"
#include "backend/Device.h"
#include "backend/RenderPass.h"
#include "backend/Texture.h"
#include "common/Assert.h"
namespace backend {
// Framebuffer
FramebufferBase::FramebufferBase(FramebufferBuilder* builder)
: mDevice(builder->mDevice),
mRenderPass(std::move(builder->mRenderPass)),
mWidth(builder->mWidth),
mHeight(builder->mHeight),
mTextureViews(std::move(builder->mTextureViews)),
mClearColors(mTextureViews.size()),
mClearDepthStencils(mTextureViews.size()) {
}
DeviceBase* FramebufferBase::GetDevice() {
return mDevice;
}
RenderPassBase* FramebufferBase::GetRenderPass() {
return mRenderPass.Get();
}
TextureViewBase* FramebufferBase::GetTextureView(uint32_t attachmentSlot) {
ASSERT(attachmentSlot < mTextureViews.size());
return mTextureViews[attachmentSlot].Get();
}
FramebufferBase::ClearColor FramebufferBase::GetClearColor(uint32_t attachmentSlot) {
ASSERT(attachmentSlot < mClearColors.size());
return mClearColors[attachmentSlot];
}
FramebufferBase::ClearDepthStencil FramebufferBase::GetClearDepthStencil(
uint32_t attachmentSlot) {
ASSERT(attachmentSlot < mClearDepthStencils.size());
return mClearDepthStencils[attachmentSlot];
}
uint32_t FramebufferBase::GetWidth() const {
return mWidth;
}
uint32_t FramebufferBase::GetHeight() const {
return mHeight;
}
void FramebufferBase::AttachmentSetClearColor(uint32_t attachmentSlot,
float clearR,
float clearG,
float clearB,
float clearA) {
if (attachmentSlot >= mRenderPass->GetAttachmentCount()) {
mDevice->HandleError("Framebuffer attachment out of bounds");
return;
}
ASSERT(attachmentSlot < mClearColors.size());
auto& c = mClearColors[attachmentSlot];
c.color[0] = clearR;
c.color[1] = clearG;
c.color[2] = clearB;
c.color[3] = clearA;
}
void FramebufferBase::AttachmentSetClearDepthStencil(uint32_t attachmentSlot,
float clearDepth,
uint32_t clearStencil) {
if (attachmentSlot >= mRenderPass->GetAttachmentCount()) {
mDevice->HandleError("Framebuffer attachment out of bounds");
return;
}
ASSERT(attachmentSlot < mClearDepthStencils.size());
auto& c = mClearDepthStencils[attachmentSlot];
c.depth = clearDepth;
c.stencil = clearStencil;
}
// FramebufferBuilder
enum FramebufferSetProperties {
FRAMEBUFFER_PROPERTY_RENDER_PASS = 0x1,
FRAMEBUFFER_PROPERTY_DIMENSIONS = 0x2,
};
FramebufferBuilder::FramebufferBuilder(DeviceBase* device) : Builder(device) {
}
FramebufferBase* FramebufferBuilder::GetResultImpl() {
constexpr int requiredProperties =
FRAMEBUFFER_PROPERTY_RENDER_PASS | FRAMEBUFFER_PROPERTY_DIMENSIONS;
if ((mPropertiesSet & requiredProperties) != requiredProperties) {
HandleError("Framebuffer missing properties");
return nullptr;
}
for (auto& textureView : mTextureViews) {
if (!textureView) {
HandleError("Framebuffer attachment not set");
return nullptr;
}
// TODO(cwallez@chromium.org): Adjust for the mip-level once that is supported.
if (textureView->GetTexture()->GetWidth() != mWidth ||
textureView->GetTexture()->GetHeight() != mHeight) {
HandleError("Framebuffer size doesn't match attachment size");
return nullptr;
}
}
return mDevice->CreateFramebuffer(this);
}
void FramebufferBuilder::SetRenderPass(RenderPassBase* renderPass) {
if ((mPropertiesSet & FRAMEBUFFER_PROPERTY_RENDER_PASS) != 0) {
HandleError("Framebuffer render pass property set multiple times");
return;
}
// TODO(kainino@chromium.org): null checks should not be necessary
if (renderPass == nullptr) {
HandleError("Render pass invalid");
return;
}
mRenderPass = renderPass;
mTextureViews.resize(renderPass->GetAttachmentCount());
mPropertiesSet |= FRAMEBUFFER_PROPERTY_RENDER_PASS;
}
void FramebufferBuilder::SetDimensions(uint32_t width, uint32_t height) {
if ((mPropertiesSet & FRAMEBUFFER_PROPERTY_DIMENSIONS) != 0) {
HandleError("Framebuffer dimensions property set multiple times");
return;
}
mWidth = width;
mHeight = height;
mPropertiesSet |= FRAMEBUFFER_PROPERTY_DIMENSIONS;
}
void FramebufferBuilder::SetAttachment(uint32_t attachmentSlot, TextureViewBase* textureView) {
if ((mPropertiesSet & FRAMEBUFFER_PROPERTY_RENDER_PASS) == 0) {
HandleError("Render pass must be set before framebuffer attachments");
return;
}
if (attachmentSlot >= mTextureViews.size()) {
HandleError("Attachment slot out of bounds");
return;
}
if (mTextureViews[attachmentSlot]) {
HandleError("Framebuffer attachment[i] set multiple times");
return;
}
const auto& attachmentInfo = mRenderPass->GetAttachmentInfo(attachmentSlot);
const auto* texture = textureView->GetTexture();
if (attachmentInfo.format != texture->GetFormat()) {
HandleError("Texture format does not match attachment format");
return;
}
// TODO(kainino@chromium.org): also check attachment samples, etc.
mTextureViews[attachmentSlot] = textureView;
}
} // namespace backend