blob: f07c48c7ae7ab94a06fc56c82396162924115fff [file] [log] [blame]
Austin Eng0c66bcd2020-01-15 18:22:53 +00001// Copyright 2020 The Dawn Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "dawn_native/metal/CommandRecordingContext.h"
16
17#include "common/Assert.h"
18
19namespace dawn_native { namespace metal {
20
21 CommandRecordingContext::CommandRecordingContext() = default;
22
Austin Eng0c66bcd2020-01-15 18:22:53 +000023 CommandRecordingContext::~CommandRecordingContext() {
24 // Commands must be acquired.
Corentin Wallez0055d952020-11-16 23:07:56 +000025 ASSERT(mCommands == nullptr);
Austin Eng0c66bcd2020-01-15 18:22:53 +000026 }
27
28 id<MTLCommandBuffer> CommandRecordingContext::GetCommands() {
Corentin Wallez0055d952020-11-16 23:07:56 +000029 return mCommands.Get();
Austin Eng0c66bcd2020-01-15 18:22:53 +000030 }
31
Dawn Autoroller18f63b42021-07-21 15:41:29 +000032 void CommandRecordingContext::MarkUsed() {
33 mUsed = true;
34 }
35 bool CommandRecordingContext::WasUsed() const {
36 return mUsed;
37 }
38
39 MaybeError CommandRecordingContext::PrepareNextCommandBuffer(id<MTLCommandQueue> queue) {
40 ASSERT(mCommands == nil);
41 ASSERT(!mUsed);
42
43 // The MTLCommandBuffer will be autoreleased by default.
44 // The autorelease pool may drain before the command buffer is submitted. Retain so it stays
45 // alive.
46 mCommands = AcquireNSPRef([[queue commandBuffer] retain]);
47 if (mCommands == nil) {
48 return DAWN_INTERNAL_ERROR("Failed to allocate an MTLCommandBuffer");
49 }
50
51 return {};
52 }
53
Corentin Wallez0055d952020-11-16 23:07:56 +000054 NSPRef<id<MTLCommandBuffer>> CommandRecordingContext::AcquireCommands() {
55 // A blit encoder can be left open from WriteBuffer, make sure we close it.
56 if (mCommands != nullptr) {
57 EndBlit();
Corentin Wallezd3bbcc32020-04-16 09:51:26 +000058 }
Austin Eng0c66bcd2020-01-15 18:22:53 +000059
Corentin Wallezd3bbcc32020-04-16 09:51:26 +000060 ASSERT(!mInEncoder);
Dawn Autoroller18f63b42021-07-21 15:41:29 +000061 mUsed = false;
Corentin Wallez0055d952020-11-16 23:07:56 +000062 return std::move(mCommands);
Austin Eng0c66bcd2020-01-15 18:22:53 +000063 }
64
65 id<MTLBlitCommandEncoder> CommandRecordingContext::EnsureBlit() {
Corentin Wallez0055d952020-11-16 23:07:56 +000066 ASSERT(mCommands != nullptr);
Austin Eng0c66bcd2020-01-15 18:22:53 +000067
Corentin Wallez0055d952020-11-16 23:07:56 +000068 if (mBlit == nullptr) {
Austin Eng0c66bcd2020-01-15 18:22:53 +000069 ASSERT(!mInEncoder);
70 mInEncoder = true;
Corentin Wallez0055d952020-11-16 23:07:56 +000071
72 // The encoder is created autoreleased. Retain it to avoid the autoreleasepool from
73 // draining from under us.
Austin Eng700a5fb2021-06-24 19:21:31 +000074 mBlit.Acquire([[*mCommands blitCommandEncoder] retain]);
Austin Eng0c66bcd2020-01-15 18:22:53 +000075 }
Corentin Wallez0055d952020-11-16 23:07:56 +000076 return mBlit.Get();
Austin Eng0c66bcd2020-01-15 18:22:53 +000077 }
78
79 void CommandRecordingContext::EndBlit() {
Corentin Wallez0055d952020-11-16 23:07:56 +000080 ASSERT(mCommands != nullptr);
Austin Eng0c66bcd2020-01-15 18:22:53 +000081
Corentin Wallez0055d952020-11-16 23:07:56 +000082 if (mBlit != nullptr) {
83 [*mBlit endEncoding];
84 mBlit = nullptr;
Austin Eng0c66bcd2020-01-15 18:22:53 +000085 mInEncoder = false;
86 }
87 }
88
89 id<MTLComputeCommandEncoder> CommandRecordingContext::BeginCompute() {
Corentin Wallez0055d952020-11-16 23:07:56 +000090 ASSERT(mCommands != nullptr);
91 ASSERT(mCompute == nullptr);
Austin Eng0c66bcd2020-01-15 18:22:53 +000092 ASSERT(!mInEncoder);
93
94 mInEncoder = true;
Austin Eng700a5fb2021-06-24 19:21:31 +000095 // The encoder is created autoreleased. Retain it to avoid the autoreleasepool from
96 // draining from under us.
97 mCompute.Acquire([[*mCommands computeCommandEncoder] retain]);
Corentin Wallez0055d952020-11-16 23:07:56 +000098 return mCompute.Get();
Austin Eng0c66bcd2020-01-15 18:22:53 +000099 }
100
101 void CommandRecordingContext::EndCompute() {
Corentin Wallez0055d952020-11-16 23:07:56 +0000102 ASSERT(mCommands != nullptr);
103 ASSERT(mCompute != nullptr);
Austin Eng0c66bcd2020-01-15 18:22:53 +0000104
Corentin Wallez0055d952020-11-16 23:07:56 +0000105 [*mCompute endEncoding];
106 mCompute = nullptr;
Austin Eng0c66bcd2020-01-15 18:22:53 +0000107 mInEncoder = false;
108 }
109
110 id<MTLRenderCommandEncoder> CommandRecordingContext::BeginRender(
111 MTLRenderPassDescriptor* descriptor) {
Corentin Wallez0055d952020-11-16 23:07:56 +0000112 ASSERT(mCommands != nullptr);
113 ASSERT(mRender == nullptr);
Austin Eng0c66bcd2020-01-15 18:22:53 +0000114 ASSERT(!mInEncoder);
115
116 mInEncoder = true;
Austin Eng700a5fb2021-06-24 19:21:31 +0000117 // The encoder is created autoreleased. Retain it to avoid the autoreleasepool from
118 // draining from under us.
119 mRender.Acquire([[*mCommands renderCommandEncoderWithDescriptor:descriptor] retain]);
Corentin Wallez0055d952020-11-16 23:07:56 +0000120 return mRender.Get();
Austin Eng0c66bcd2020-01-15 18:22:53 +0000121 }
122
123 void CommandRecordingContext::EndRender() {
Corentin Wallez0055d952020-11-16 23:07:56 +0000124 ASSERT(mCommands != nullptr);
125 ASSERT(mRender != nullptr);
Austin Eng0c66bcd2020-01-15 18:22:53 +0000126
Corentin Wallez0055d952020-11-16 23:07:56 +0000127 [*mRender endEncoding];
128 mRender = nullptr;
Austin Eng0c66bcd2020-01-15 18:22:53 +0000129 mInEncoder = false;
130 }
131
132}} // namespace dawn_native::metal