xref: /aosp_15_r20/external/libgav1/src/threading_strategy_test.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop // Copyright 2021 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop //      http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop 
15*09537850SAkhilesh Sanikop #include "src/threading_strategy.h"
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop #include <memory>
18*09537850SAkhilesh Sanikop #include <utility>
19*09537850SAkhilesh Sanikop #include <vector>
20*09537850SAkhilesh Sanikop 
21*09537850SAkhilesh Sanikop #include "absl/strings/str_cat.h"
22*09537850SAkhilesh Sanikop #include "gtest/gtest.h"
23*09537850SAkhilesh Sanikop #include "src/frame_scratch_buffer.h"
24*09537850SAkhilesh Sanikop #include "src/obu_parser.h"
25*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
26*09537850SAkhilesh Sanikop #include "src/utils/threadpool.h"
27*09537850SAkhilesh Sanikop #include "src/utils/types.h"
28*09537850SAkhilesh Sanikop 
29*09537850SAkhilesh Sanikop namespace libgav1 {
30*09537850SAkhilesh Sanikop namespace {
31*09537850SAkhilesh Sanikop 
32*09537850SAkhilesh Sanikop class ThreadingStrategyTest : public testing::Test {
33*09537850SAkhilesh Sanikop  protected:
34*09537850SAkhilesh Sanikop   ThreadingStrategy strategy_;
35*09537850SAkhilesh Sanikop   ObuFrameHeader frame_header_ = {};
36*09537850SAkhilesh Sanikop };
37*09537850SAkhilesh Sanikop 
TEST_F(ThreadingStrategyTest,MaxThreadEnforced)38*09537850SAkhilesh Sanikop TEST_F(ThreadingStrategyTest, MaxThreadEnforced) {
39*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 32;
40*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 32));
41*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
42*09537850SAkhilesh Sanikop   for (int i = 0; i < 32; ++i) {
43*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr);
44*09537850SAkhilesh Sanikop   }
45*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
46*09537850SAkhilesh Sanikop }
47*09537850SAkhilesh Sanikop 
TEST_F(ThreadingStrategyTest,UseAllThreadsForTiles)48*09537850SAkhilesh Sanikop TEST_F(ThreadingStrategyTest, UseAllThreadsForTiles) {
49*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 8;
50*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 8));
51*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
52*09537850SAkhilesh Sanikop   for (int i = 0; i < 8; ++i) {
53*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr);
54*09537850SAkhilesh Sanikop   }
55*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
56*09537850SAkhilesh Sanikop }
57*09537850SAkhilesh Sanikop 
TEST_F(ThreadingStrategyTest,RowThreads)58*09537850SAkhilesh Sanikop TEST_F(ThreadingStrategyTest, RowThreads) {
59*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 2;
60*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 8));
61*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
62*09537850SAkhilesh Sanikop   // Each tile should get 3 threads each.
63*09537850SAkhilesh Sanikop   for (int i = 0; i < 2; ++i) {
64*09537850SAkhilesh Sanikop     EXPECT_NE(strategy_.row_thread_pool(i), nullptr);
65*09537850SAkhilesh Sanikop   }
66*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
67*09537850SAkhilesh Sanikop }
68*09537850SAkhilesh Sanikop 
TEST_F(ThreadingStrategyTest,RowThreadsUnequal)69*09537850SAkhilesh Sanikop TEST_F(ThreadingStrategyTest, RowThreadsUnequal) {
70*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 2;
71*09537850SAkhilesh Sanikop 
72*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 9));
73*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
74*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.row_thread_pool(0), nullptr);
75*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.row_thread_pool(1), nullptr);
76*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
77*09537850SAkhilesh Sanikop }
78*09537850SAkhilesh Sanikop 
79*09537850SAkhilesh Sanikop // Test a random combination of tile_count and thread_count.
TEST_F(ThreadingStrategyTest,MultipleCalls)80*09537850SAkhilesh Sanikop TEST_F(ThreadingStrategyTest, MultipleCalls) {
81*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 2;
82*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 8));
83*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
84*09537850SAkhilesh Sanikop   for (int i = 0; i < 2; ++i) {
85*09537850SAkhilesh Sanikop     EXPECT_NE(strategy_.row_thread_pool(i), nullptr);
86*09537850SAkhilesh Sanikop   }
87*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
88*09537850SAkhilesh Sanikop 
89*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 8;
90*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 8));
91*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
92*09537850SAkhilesh Sanikop   // Row threads must have been reset.
93*09537850SAkhilesh Sanikop   for (int i = 0; i < 8; ++i) {
94*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr);
95*09537850SAkhilesh Sanikop   }
96*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
97*09537850SAkhilesh Sanikop 
98*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 8;
99*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 16));
100*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
101*09537850SAkhilesh Sanikop   for (int i = 0; i < 8; ++i) {
102*09537850SAkhilesh Sanikop     // See ThreadingStrategy::Reset().
103*09537850SAkhilesh Sanikop #if defined(__ANDROID__)
104*09537850SAkhilesh Sanikop     if (i >= 4) {
105*09537850SAkhilesh Sanikop       EXPECT_EQ(strategy_.row_thread_pool(i), nullptr) << "i = " << i;
106*09537850SAkhilesh Sanikop       continue;
107*09537850SAkhilesh Sanikop     }
108*09537850SAkhilesh Sanikop #endif
109*09537850SAkhilesh Sanikop     EXPECT_NE(strategy_.row_thread_pool(i), nullptr) << "i = " << i;
110*09537850SAkhilesh Sanikop   }
111*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
112*09537850SAkhilesh Sanikop 
113*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 4;
114*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 16));
115*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
116*09537850SAkhilesh Sanikop   for (int i = 0; i < 4; ++i) {
117*09537850SAkhilesh Sanikop     EXPECT_NE(strategy_.row_thread_pool(i), nullptr);
118*09537850SAkhilesh Sanikop   }
119*09537850SAkhilesh Sanikop   // All the other row threads must be reset.
120*09537850SAkhilesh Sanikop   for (int i = 4; i < 8; ++i) {
121*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr);
122*09537850SAkhilesh Sanikop   }
123*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
124*09537850SAkhilesh Sanikop 
125*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 4;
126*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 6));
127*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
128*09537850SAkhilesh Sanikop   // First two tiles will get 1 thread each.
129*09537850SAkhilesh Sanikop   for (int i = 0; i < 2; ++i) {
130*09537850SAkhilesh Sanikop     // See ThreadingStrategy::Reset().
131*09537850SAkhilesh Sanikop #if defined(__ANDROID__)
132*09537850SAkhilesh Sanikop     if (i == 1) {
133*09537850SAkhilesh Sanikop       EXPECT_EQ(strategy_.row_thread_pool(i), nullptr) << "i = " << i;
134*09537850SAkhilesh Sanikop       continue;
135*09537850SAkhilesh Sanikop     }
136*09537850SAkhilesh Sanikop #endif
137*09537850SAkhilesh Sanikop     EXPECT_NE(strategy_.row_thread_pool(i), nullptr) << "i = " << i;
138*09537850SAkhilesh Sanikop   }
139*09537850SAkhilesh Sanikop   // All the other row threads must be reset.
140*09537850SAkhilesh Sanikop   for (int i = 2; i < 8; ++i) {
141*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr) << "i = " << i;
142*09537850SAkhilesh Sanikop   }
143*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
144*09537850SAkhilesh Sanikop 
145*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 1));
146*09537850SAkhilesh Sanikop   EXPECT_EQ(strategy_.tile_thread_pool(), nullptr);
147*09537850SAkhilesh Sanikop   for (int i = 0; i < 8; ++i) {
148*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr);
149*09537850SAkhilesh Sanikop   }
150*09537850SAkhilesh Sanikop   EXPECT_EQ(strategy_.post_filter_thread_pool(), nullptr);
151*09537850SAkhilesh Sanikop }
152*09537850SAkhilesh Sanikop 
153*09537850SAkhilesh Sanikop // Tests the following order of calls (with thread count fixed at 4):
154*09537850SAkhilesh Sanikop //  * 1 Tile - 2 Tiles - 1 Tile.
TEST_F(ThreadingStrategyTest,MultipleCalls2)155*09537850SAkhilesh Sanikop TEST_F(ThreadingStrategyTest, MultipleCalls2) {
156*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 1;
157*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 4));
158*09537850SAkhilesh Sanikop   // When there is only one tile, tile thread pool must be nullptr.
159*09537850SAkhilesh Sanikop   EXPECT_EQ(strategy_.tile_thread_pool(), nullptr);
160*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.row_thread_pool(0), nullptr);
161*09537850SAkhilesh Sanikop   for (int i = 1; i < 8; ++i) {
162*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr);
163*09537850SAkhilesh Sanikop   }
164*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
165*09537850SAkhilesh Sanikop 
166*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 2;
167*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 4));
168*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.tile_thread_pool(), nullptr);
169*09537850SAkhilesh Sanikop   for (int i = 0; i < 2; ++i) {
170*09537850SAkhilesh Sanikop     // See ThreadingStrategy::Reset().
171*09537850SAkhilesh Sanikop #if defined(__ANDROID__)
172*09537850SAkhilesh Sanikop     if (i == 1) {
173*09537850SAkhilesh Sanikop       EXPECT_EQ(strategy_.row_thread_pool(i), nullptr) << "i = " << i;
174*09537850SAkhilesh Sanikop       continue;
175*09537850SAkhilesh Sanikop     }
176*09537850SAkhilesh Sanikop #endif
177*09537850SAkhilesh Sanikop     EXPECT_NE(strategy_.row_thread_pool(i), nullptr);
178*09537850SAkhilesh Sanikop   }
179*09537850SAkhilesh Sanikop   for (int i = 2; i < 8; ++i) {
180*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr);
181*09537850SAkhilesh Sanikop   }
182*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
183*09537850SAkhilesh Sanikop 
184*09537850SAkhilesh Sanikop   frame_header_.tile_info.tile_count = 1;
185*09537850SAkhilesh Sanikop   ASSERT_TRUE(strategy_.Reset(frame_header_, 4));
186*09537850SAkhilesh Sanikop   EXPECT_EQ(strategy_.tile_thread_pool(), nullptr);
187*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.row_thread_pool(0), nullptr);
188*09537850SAkhilesh Sanikop   for (int i = 1; i < 8; ++i) {
189*09537850SAkhilesh Sanikop     EXPECT_EQ(strategy_.row_thread_pool(i), nullptr);
190*09537850SAkhilesh Sanikop   }
191*09537850SAkhilesh Sanikop   EXPECT_NE(strategy_.post_filter_thread_pool(), nullptr);
192*09537850SAkhilesh Sanikop }
193*09537850SAkhilesh Sanikop 
VerifyFrameParallel(int thread_count,int tile_count,int tile_columns,int expected_frame_threads,const std::vector<int> & expected_tile_threads)194*09537850SAkhilesh Sanikop void VerifyFrameParallel(int thread_count, int tile_count, int tile_columns,
195*09537850SAkhilesh Sanikop                          int expected_frame_threads,
196*09537850SAkhilesh Sanikop                          const std::vector<int>& expected_tile_threads) {
197*09537850SAkhilesh Sanikop   ASSERT_EQ(expected_frame_threads, expected_tile_threads.size());
198*09537850SAkhilesh Sanikop   ASSERT_GT(thread_count, 1);
199*09537850SAkhilesh Sanikop   std::unique_ptr<ThreadPool> frame_thread_pool;
200*09537850SAkhilesh Sanikop   FrameScratchBufferPool frame_scratch_buffer_pool;
201*09537850SAkhilesh Sanikop   ASSERT_TRUE(InitializeThreadPoolsForFrameParallel(
202*09537850SAkhilesh Sanikop       thread_count, tile_count, tile_columns, &frame_thread_pool,
203*09537850SAkhilesh Sanikop       &frame_scratch_buffer_pool));
204*09537850SAkhilesh Sanikop   if (expected_frame_threads == 0) {
205*09537850SAkhilesh Sanikop     EXPECT_EQ(frame_thread_pool, nullptr);
206*09537850SAkhilesh Sanikop     return;
207*09537850SAkhilesh Sanikop   }
208*09537850SAkhilesh Sanikop   EXPECT_NE(frame_thread_pool.get(), nullptr);
209*09537850SAkhilesh Sanikop   EXPECT_EQ(frame_thread_pool->num_threads(), expected_frame_threads);
210*09537850SAkhilesh Sanikop   std::vector<std::unique_ptr<FrameScratchBuffer>> frame_scratch_buffers;
211*09537850SAkhilesh Sanikop   int actual_thread_count = frame_thread_pool->num_threads();
212*09537850SAkhilesh Sanikop   for (int i = 0; i < expected_frame_threads; ++i) {
213*09537850SAkhilesh Sanikop     SCOPED_TRACE(absl::StrCat("i: ", i));
214*09537850SAkhilesh Sanikop     frame_scratch_buffers.push_back(frame_scratch_buffer_pool.Get());
215*09537850SAkhilesh Sanikop     ThreadPool* const thread_pool =
216*09537850SAkhilesh Sanikop         frame_scratch_buffers.back()->threading_strategy.thread_pool();
217*09537850SAkhilesh Sanikop     if (expected_tile_threads[i] > 0) {
218*09537850SAkhilesh Sanikop       EXPECT_NE(thread_pool, nullptr);
219*09537850SAkhilesh Sanikop       EXPECT_EQ(thread_pool->num_threads(), expected_tile_threads[i]);
220*09537850SAkhilesh Sanikop       actual_thread_count += thread_pool->num_threads();
221*09537850SAkhilesh Sanikop     } else {
222*09537850SAkhilesh Sanikop       EXPECT_EQ(thread_pool, nullptr);
223*09537850SAkhilesh Sanikop     }
224*09537850SAkhilesh Sanikop   }
225*09537850SAkhilesh Sanikop   EXPECT_EQ(thread_count, actual_thread_count);
226*09537850SAkhilesh Sanikop   for (auto& frame_scratch_buffer : frame_scratch_buffers) {
227*09537850SAkhilesh Sanikop     frame_scratch_buffer_pool.Release(std::move(frame_scratch_buffer));
228*09537850SAkhilesh Sanikop   }
229*09537850SAkhilesh Sanikop }
230*09537850SAkhilesh Sanikop 
TEST(FrameParallelStrategyTest,FrameParallel)231*09537850SAkhilesh Sanikop TEST(FrameParallelStrategyTest, FrameParallel) {
232*09537850SAkhilesh Sanikop   // This loop has thread_count <= 3 * tile count. So there should be no frame
233*09537850SAkhilesh Sanikop   // threads irrespective of the number of tile columns.
234*09537850SAkhilesh Sanikop   for (int thread_count = 2; thread_count <= 6; ++thread_count) {
235*09537850SAkhilesh Sanikop     VerifyFrameParallel(thread_count, /*tile_count=*/2, /*tile_columns=*/1,
236*09537850SAkhilesh Sanikop                         /*expected_frame_threads=*/0,
237*09537850SAkhilesh Sanikop                         /*expected_tile_threads=*/{});
238*09537850SAkhilesh Sanikop     VerifyFrameParallel(thread_count, /*tile_count=*/2, /*tile_columns=*/2,
239*09537850SAkhilesh Sanikop                         /*expected_frame_threads=*/0,
240*09537850SAkhilesh Sanikop                         /*expected_tile_threads=*/{});
241*09537850SAkhilesh Sanikop   }
242*09537850SAkhilesh Sanikop 
243*09537850SAkhilesh Sanikop   // Equal number of tile threads for each frame thread.
244*09537850SAkhilesh Sanikop   VerifyFrameParallel(
245*09537850SAkhilesh Sanikop       /*thread_count=*/8, /*tile_count=*/1, /*tile_columns=*/1,
246*09537850SAkhilesh Sanikop       /*expected_frame_threads=*/4, /*expected_tile_threads=*/{1, 1, 1, 1});
247*09537850SAkhilesh Sanikop   VerifyFrameParallel(
248*09537850SAkhilesh Sanikop       /*thread_count=*/12, /*tile_count=*/2, /*tile_columns=*/2,
249*09537850SAkhilesh Sanikop       /*expected_frame_threads=*/4, /*expected_tile_threads=*/{2, 2, 2, 2});
250*09537850SAkhilesh Sanikop   VerifyFrameParallel(
251*09537850SAkhilesh Sanikop       /*thread_count=*/18, /*tile_count=*/2, /*tile_columns=*/2,
252*09537850SAkhilesh Sanikop       /*expected_frame_threads=*/6,
253*09537850SAkhilesh Sanikop       /*expected_tile_threads=*/{2, 2, 2, 2, 2, 2});
254*09537850SAkhilesh Sanikop   VerifyFrameParallel(
255*09537850SAkhilesh Sanikop       /*thread_count=*/16, /*tile_count=*/3, /*tile_columns=*/3,
256*09537850SAkhilesh Sanikop       /*expected_frame_threads=*/4, /*expected_tile_threads=*/{3, 3, 3, 3});
257*09537850SAkhilesh Sanikop 
258*09537850SAkhilesh Sanikop   // Unequal number of tile threads for each frame thread.
259*09537850SAkhilesh Sanikop   VerifyFrameParallel(
260*09537850SAkhilesh Sanikop       /*thread_count=*/7, /*tile_count=*/1, /*tile_columns=*/1,
261*09537850SAkhilesh Sanikop       /*expected_frame_threads=*/3, /*expected_tile_threads=*/{2, 1, 1});
262*09537850SAkhilesh Sanikop   VerifyFrameParallel(
263*09537850SAkhilesh Sanikop       /*thread_count=*/14, /*tile_count=*/2, /*tile_columns=*/2,
264*09537850SAkhilesh Sanikop       /*expected_frame_threads=*/4, /*expected_tile_threads=*/{3, 3, 2, 2});
265*09537850SAkhilesh Sanikop   VerifyFrameParallel(
266*09537850SAkhilesh Sanikop       /*thread_count=*/20, /*tile_count=*/2, /*tile_columns=*/2,
267*09537850SAkhilesh Sanikop       /*expected_frame_threads=*/6,
268*09537850SAkhilesh Sanikop       /*expected_tile_threads=*/{3, 3, 2, 2, 2, 2});
269*09537850SAkhilesh Sanikop   VerifyFrameParallel(
270*09537850SAkhilesh Sanikop       /*thread_count=*/17, /*tile_count=*/3, /*tile_columns=*/3,
271*09537850SAkhilesh Sanikop       /*expected_frame_threads=*/4, /*expected_tile_threads=*/{4, 3, 3, 3});
272*09537850SAkhilesh Sanikop }
273*09537850SAkhilesh Sanikop 
TEST(FrameParallelStrategyTest,ThreadCountDoesNotExceedkMaxThreads)274*09537850SAkhilesh Sanikop TEST(FrameParallelStrategyTest, ThreadCountDoesNotExceedkMaxThreads) {
275*09537850SAkhilesh Sanikop   std::unique_ptr<ThreadPool> frame_thread_pool;
276*09537850SAkhilesh Sanikop   FrameScratchBufferPool frame_scratch_buffer_pool;
277*09537850SAkhilesh Sanikop   ASSERT_TRUE(InitializeThreadPoolsForFrameParallel(
278*09537850SAkhilesh Sanikop       /*thread_count=*/kMaxThreads + 10, /*tile_count=*/2, /*tile_columns=*/2,
279*09537850SAkhilesh Sanikop       &frame_thread_pool, &frame_scratch_buffer_pool));
280*09537850SAkhilesh Sanikop   EXPECT_NE(frame_thread_pool.get(), nullptr);
281*09537850SAkhilesh Sanikop   std::vector<std::unique_ptr<FrameScratchBuffer>> frame_scratch_buffers;
282*09537850SAkhilesh Sanikop   int actual_thread_count = frame_thread_pool->num_threads();
283*09537850SAkhilesh Sanikop   for (int i = 0; i < frame_thread_pool->num_threads(); ++i) {
284*09537850SAkhilesh Sanikop     SCOPED_TRACE(absl::StrCat("i: ", i));
285*09537850SAkhilesh Sanikop     frame_scratch_buffers.push_back(frame_scratch_buffer_pool.Get());
286*09537850SAkhilesh Sanikop     ThreadPool* const thread_pool =
287*09537850SAkhilesh Sanikop         frame_scratch_buffers.back()->threading_strategy.thread_pool();
288*09537850SAkhilesh Sanikop     if (thread_pool != nullptr) {
289*09537850SAkhilesh Sanikop       actual_thread_count += thread_pool->num_threads();
290*09537850SAkhilesh Sanikop     }
291*09537850SAkhilesh Sanikop   }
292*09537850SAkhilesh Sanikop   // In this case, the exact number of frame threads and tile threads depend on
293*09537850SAkhilesh Sanikop   // the value of kMaxThreads. So simply ensure that the total number of threads
294*09537850SAkhilesh Sanikop   // does not exceed kMaxThreads.
295*09537850SAkhilesh Sanikop   EXPECT_LE(actual_thread_count, kMaxThreads);
296*09537850SAkhilesh Sanikop   for (auto& frame_scratch_buffer : frame_scratch_buffers) {
297*09537850SAkhilesh Sanikop     frame_scratch_buffer_pool.Release(std::move(frame_scratch_buffer));
298*09537850SAkhilesh Sanikop   }
299*09537850SAkhilesh Sanikop }
300*09537850SAkhilesh Sanikop 
301*09537850SAkhilesh Sanikop }  // namespace
302*09537850SAkhilesh Sanikop }  // namespace libgav1
303