| // Copyright 2017 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/CommandBuffer.h" |
| |
| #include "common/BitSetIterator.h" |
| #include "dawn_native/CommandEncoder.h" |
| #include "dawn_native/Commands.h" |
| #include "dawn_native/Format.h" |
| #include "dawn_native/Texture.h" |
| |
| namespace dawn_native { |
| |
| CommandBufferBase::CommandBufferBase(CommandEncoder* encoder, const CommandBufferDescriptor*) |
| : ObjectBase(encoder->GetDevice()), mResourceUsages(encoder->AcquireResourceUsages()) { |
| } |
| |
| CommandBufferBase::CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag) |
| : ObjectBase(device, tag) { |
| } |
| |
| // static |
| CommandBufferBase* CommandBufferBase::MakeError(DeviceBase* device) { |
| return new CommandBufferBase(device, ObjectBase::kError); |
| } |
| |
| const CommandBufferResourceUsage& CommandBufferBase::GetResourceUsages() const { |
| return mResourceUsages; |
| } |
| |
| bool IsCompleteSubresourceCopiedTo(const TextureBase* texture, |
| const Extent3D copySize, |
| const uint32_t mipLevel) { |
| Extent3D extent = texture->GetMipLevelPhysicalSize(mipLevel); |
| |
| if (extent.depth == copySize.depth && extent.width == copySize.width && |
| extent.height == copySize.height) { |
| return true; |
| } |
| return false; |
| } |
| |
| void LazyClearRenderPassAttachments(BeginRenderPassCmd* renderPass) { |
| for (uint32_t i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) { |
| auto& attachmentInfo = renderPass->colorAttachments[i]; |
| TextureViewBase* view = attachmentInfo.view.Get(); |
| bool hasResolveTarget = attachmentInfo.resolveTarget.Get() != nullptr; |
| |
| ASSERT(view->GetLayerCount() == 1); |
| ASSERT(view->GetLevelCount() == 1); |
| SubresourceRange range = view->GetSubresourceRange(); |
| |
| // If the loadOp is Load, but the subresource is not initialized, use Clear instead. |
| if (attachmentInfo.loadOp == wgpu::LoadOp::Load && |
| !view->GetTexture()->IsSubresourceContentInitialized(range)) { |
| attachmentInfo.loadOp = wgpu::LoadOp::Clear; |
| attachmentInfo.clearColor = {0.f, 0.f, 0.f, 0.f}; |
| } |
| |
| if (hasResolveTarget) { |
| // We need to set the resolve target to initialized so that it does not get |
| // cleared later in the pipeline. The texture will be resolved from the |
| // source color attachment, which will be correctly initialized. |
| TextureViewBase* resolveView = attachmentInfo.resolveTarget.Get(); |
| ASSERT(resolveView->GetLayerCount() == 1); |
| ASSERT(resolveView->GetLevelCount() == 1); |
| resolveView->GetTexture()->SetIsSubresourceContentInitialized( |
| true, resolveView->GetSubresourceRange()); |
| } |
| |
| switch (attachmentInfo.storeOp) { |
| case wgpu::StoreOp::Store: |
| view->GetTexture()->SetIsSubresourceContentInitialized(true, range); |
| break; |
| |
| case wgpu::StoreOp::Clear: |
| view->GetTexture()->SetIsSubresourceContentInitialized(false, range); |
| break; |
| |
| default: |
| UNREACHABLE(); |
| break; |
| } |
| } |
| |
| if (renderPass->attachmentState->HasDepthStencilAttachment()) { |
| auto& attachmentInfo = renderPass->depthStencilAttachment; |
| TextureViewBase* view = attachmentInfo.view.Get(); |
| ASSERT(view->GetLayerCount() == 1); |
| ASSERT(view->GetLevelCount() == 1); |
| SubresourceRange range = view->GetSubresourceRange(); |
| |
| // If the depth stencil texture has not been initialized, we want to use loadop |
| // clear to init the contents to 0's |
| if (!view->GetTexture()->IsSubresourceContentInitialized(range)) { |
| if (view->GetTexture()->GetFormat().HasDepth() && |
| attachmentInfo.depthLoadOp == wgpu::LoadOp::Load) { |
| attachmentInfo.clearDepth = 0.0f; |
| attachmentInfo.depthLoadOp = wgpu::LoadOp::Clear; |
| } |
| if (view->GetTexture()->GetFormat().HasStencil() && |
| attachmentInfo.stencilLoadOp == wgpu::LoadOp::Load) { |
| attachmentInfo.clearStencil = 0u; |
| attachmentInfo.stencilLoadOp = wgpu::LoadOp::Clear; |
| } |
| } |
| |
| // If these have different store ops, make them both Store because we can't track |
| // initialized state separately yet. TODO(crbug.com/dawn/145) |
| if (attachmentInfo.depthStoreOp != attachmentInfo.stencilStoreOp) { |
| attachmentInfo.depthStoreOp = wgpu::StoreOp::Store; |
| attachmentInfo.stencilStoreOp = wgpu::StoreOp::Store; |
| } |
| |
| if (attachmentInfo.depthStoreOp == wgpu::StoreOp::Store && |
| attachmentInfo.stencilStoreOp == wgpu::StoreOp::Store) { |
| view->GetTexture()->SetIsSubresourceContentInitialized(true, range); |
| } else { |
| ASSERT(attachmentInfo.depthStoreOp == wgpu::StoreOp::Clear && |
| attachmentInfo.stencilStoreOp == wgpu::StoreOp::Clear); |
| view->GetTexture()->SetIsSubresourceContentInitialized(false, range); |
| } |
| } |
| } |
| |
| } // namespace dawn_native |