31 using CS = SampleComputeShader;
32 auto context = GetContext();
34 context->GetIdleWaiter());
36 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
40 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
41 ASSERT_TRUE(pipeline_desc.has_value());
42 auto compute_pipeline =
43 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
44 ASSERT_TRUE(compute_pipeline);
46 auto cmd_buffer = context->CreateCommandBuffer();
47 auto pass = cmd_buffer->CreateComputePass();
48 ASSERT_TRUE(pass && pass->IsValid());
50 static constexpr size_t kCount = 5;
52 pass->SetPipeline(compute_pipeline);
54 CS::Info info{.count = kCount};
55 CS::Input0<kCount> input_0;
56 CS::Input1<kCount> input_1;
57 for (
size_t i = 0;
i < kCount;
i++) {
58 input_0.elements[
i] =
Vector4(2.0 +
i, 3.0 +
i, 4.0 +
i, 5.0 *
i);
59 input_1.elements[
i] =
Vector4(6.0, 7.0, 8.0, 9.0);
62 input_0.fixed_array[1] =
IPoint32(2, 2);
65 input_1.some_struct = CS::SomeStruct{.vf =
Point(3, 4), .i = 42};
67 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
68 context,
"Output Buffer");
70 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
71 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
72 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
75 ASSERT_TRUE(pass->Compute(
ISize(kCount, 1)).ok());
76 ASSERT_TRUE(pass->EncodeCommands());
80 context->GetCommandQueue()
83 [&latch, output_buffer, &input_0,
85 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
87 auto view = DeviceBuffer::AsBufferView(output_buffer);
88 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
90 CS::Output<kCount>* output =
91 reinterpret_cast<CS::Output<kCount>*>(
92 output_buffer->OnGetContents());
94 for (size_t i = 0; i < kCount; i++) {
95 Vector4 vector = output->elements[i];
96 Vector4 computed = input_0.elements[i] * input_1.elements[i];
98 Vector4(computed.x + 2 + input_1.some_struct.i,
99 computed.y + 3 + input_1.some_struct.vf.x,
100 computed.z + 5 + input_1.some_struct.vf.y,
111 using CS = PrefixSumTestComputeShader;
112 auto context = GetContext();
114 context->GetIdleWaiter());
115 ASSERT_TRUE(context);
116 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
120 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
121 ASSERT_TRUE(pipeline_desc.has_value());
122 auto compute_pipeline =
123 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
124 ASSERT_TRUE(compute_pipeline);
126 auto cmd_buffer = context->CreateCommandBuffer();
127 auto pass = cmd_buffer->CreateComputePass();
128 ASSERT_TRUE(pass && pass->IsValid());
130 static constexpr size_t kCount = 5;
132 pass->SetPipeline(compute_pipeline);
134 CS::InputData<kCount> input_data;
135 input_data.count = kCount;
136 for (
size_t i = 0;
i < kCount;
i++) {
137 input_data.data[
i] = 1 +
i;
140 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
141 context,
"Output Buffer");
143 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
146 ASSERT_TRUE(pass->Compute(
ISize(kCount, 1)).ok());
147 ASSERT_TRUE(pass->EncodeCommands());
151 context->GetCommandQueue()
152 ->Submit({cmd_buffer},
154 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
156 auto view = DeviceBuffer::AsBufferView(output_buffer);
157 EXPECT_EQ(view.GetRange().length,
158 sizeof(CS::OutputData<kCount>));
160 CS::OutputData<kCount>* output =
161 reinterpret_cast<CS::OutputData<kCount>*>(
162 output_buffer->OnGetContents());
165 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
166 for (
size_t i = 0;
i < kCount;
i++) {
167 auto computed_sum = output->data[
i];
168 EXPECT_EQ(computed_sum, expected[
i]);
178 using CS = ThreadgroupSizingTestComputeShader;
179 auto context = GetContext();
180 ASSERT_TRUE(context);
181 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
185 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
186 ASSERT_TRUE(pipeline_desc.has_value());
187 auto compute_pipeline =
188 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
189 ASSERT_TRUE(compute_pipeline);
191 auto cmd_buffer = context->CreateCommandBuffer();
192 auto pass = cmd_buffer->CreateComputePass();
193 ASSERT_TRUE(pass && pass->IsValid());
195 static constexpr size_t kCount = 2048;
197 pass->SetPipeline(compute_pipeline);
199 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
200 context,
"Output Buffer");
202 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
204 ASSERT_TRUE(pass->Compute(
ISize(kCount, 1)).ok());
205 ASSERT_TRUE(pass->EncodeCommands());
209 context->GetCommandQueue()
210 ->Submit({cmd_buffer},
212 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
214 auto view = DeviceBuffer::AsBufferView(output_buffer);
215 EXPECT_EQ(view.GetRange().length,
216 sizeof(CS::OutputData<kCount>));
218 CS::OutputData<kCount>* output =
219 reinterpret_cast<CS::OutputData<kCount>*>(
220 output_buffer->OnGetContents());
222 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
231 using CS = PrefixSumTestComputeShader;
233 auto context = GetContext();
234 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
235 context->GetIdleWaiter());
237 ASSERT_TRUE(context);
238 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
243 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
244 auto compute_pipeline =
245 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
247 auto cmd_buffer = context->CreateCommandBuffer();
248 auto pass = cmd_buffer->CreateComputePass();
250 static constexpr size_t kCount = 1023;
252 pass->SetPipeline(compute_pipeline);
254 CS::InputData<kCount> input_data;
255 input_data.count = kCount;
256 for (
size_t i = 0;
i < kCount;
i++) {
257 input_data.data[
i] = 1 +
i;
260 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
261 context,
"Output Buffer");
263 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
264 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
266 pass->Compute(
ISize(kCount, 1));
267 pass->EncodeCommands();
268 host_buffer->Reset();
269 return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
271 ASSERT_TRUE(OpenPlaygroundHere(
callback));
275 using CS1 = Stage1ComputeShader;
277 using CS2 = Stage2ComputeShader;
280 auto context = GetContext();
281 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
282 context->GetIdleWaiter());
283 ASSERT_TRUE(context);
284 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
286 auto pipeline_desc_1 =
287 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
288 ASSERT_TRUE(pipeline_desc_1.has_value());
289 auto compute_pipeline_1 =
290 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
291 ASSERT_TRUE(compute_pipeline_1);
293 auto pipeline_desc_2 =
294 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
295 ASSERT_TRUE(pipeline_desc_2.has_value());
296 auto compute_pipeline_2 =
297 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
298 ASSERT_TRUE(compute_pipeline_2);
300 auto cmd_buffer = context->CreateCommandBuffer();
301 auto pass = cmd_buffer->CreateComputePass();
302 ASSERT_TRUE(pass && pass->IsValid());
304 static constexpr size_t kCount1 = 5;
305 static constexpr size_t kCount2 =
kCount1 * 2;
307 CS1::Input<kCount1> input_1;
310 input_1.elements[
i] =
i;
313 CS2::Input<kCount2> input_2;
314 input_2.count = kCount2;
315 for (
size_t i = 0;
i < kCount2;
i++) {
316 input_2.elements[
i] =
i;
319 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
320 context,
"Output Buffer Stage 1");
321 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
322 context,
"Output Buffer Stage 2");
325 pass->SetPipeline(compute_pipeline_1);
327 CS1::BindInput(*pass, host_buffer->EmplaceStorageBuffer(input_1));
328 CS1::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
330 ASSERT_TRUE(pass->Compute(
ISize(512, 1)).ok());
331 pass->AddBufferMemoryBarrier();
335 pass->SetPipeline(compute_pipeline_2);
337 CS1::BindInput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
338 CS2::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_2));
339 ASSERT_TRUE(pass->Compute(
ISize(512, 1)).ok());
342 ASSERT_TRUE(pass->EncodeCommands());
346 context->GetCommandQueue()
347 ->Submit({cmd_buffer},
348 [&latch, &output_buffer_1,
350 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
352 CS1::Output<kCount2>* output_1 =
353 reinterpret_cast<CS1::Output<kCount2>*>(
354 output_buffer_1->OnGetContents());
355 EXPECT_TRUE(output_1);
356 EXPECT_EQ(output_1->count, 10u);
359 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
361 CS2::Output<kCount2>* output_2 =
362 reinterpret_cast<CS2::Output<kCount2>*>(
363 output_buffer_2->OnGetContents());
364 EXPECT_TRUE(output_2);
365 EXPECT_EQ(output_2->count, 10u);
366 EXPECT_THAT(output_2->elements,
367 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12,
378 using CS = SampleComputeShader;
379 auto context = GetContext();
380 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
381 context->GetIdleWaiter());
382 ASSERT_TRUE(context);
383 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
387 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
388 ASSERT_TRUE(pipeline_desc.has_value());
389 auto compute_pipeline =
390 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
391 ASSERT_TRUE(compute_pipeline);
393 auto cmd_buffer = context->CreateCommandBuffer();
394 auto pass = cmd_buffer->CreateComputePass();
395 ASSERT_TRUE(pass && pass->IsValid());
397 static constexpr size_t kCount = 5;
399 pass->SetPipeline(compute_pipeline);
401 CS::Info info{.count = kCount};
402 CS::Input0<kCount> input_0;
403 CS::Input1<kCount> input_1;
404 for (
size_t i = 0;
i < kCount;
i++) {
405 input_0.elements[
i] =
Vector4(2.0 +
i, 3.0 +
i, 4.0 +
i, 5.0 *
i);
406 input_1.elements[
i] =
Vector4(6.0, 7.0, 8.0, 9.0);
409 input_0.fixed_array[1] =
IPoint32(2, 2);
411 input_0.some_int = 5;
412 input_1.some_struct = CS::SomeStruct{.vf =
Point(3, 4), .i = 42};
414 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
415 context,
"Output Buffer");
417 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
418 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
419 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
420 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
422 ASSERT_TRUE(pass->Compute(
ISize(kCount, 1)).ok());
423 ASSERT_TRUE(pass->EncodeCommands());
427 context->GetCommandQueue()
430 [&latch, output_buffer, &input_0,
432 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
434 auto view = DeviceBuffer::AsBufferView(output_buffer);
435 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
437 CS::Output<kCount>* output =
438 reinterpret_cast<CS::Output<kCount>*>(
439 output_buffer->OnGetContents());
441 for (size_t i = 0; i < kCount; i++) {
442 Vector4 vector = output->elements[i];
443 Vector4 computed = input_0.elements[i] * input_1.elements[i];
445 Vector4(computed.x + 2 + input_1.some_struct.i,
446 computed.y + 3 + input_1.some_struct.vf.x,
447 computed.z + 5 + input_1.some_struct.vf.y,
458 using CS = SampleComputeShader;
459 auto context = GetContext();
460 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
461 context->GetIdleWaiter());
462 ASSERT_TRUE(context);
463 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
467 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
468 ASSERT_TRUE(pipeline_desc.has_value());
469 auto compute_pipeline =
470 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
471 ASSERT_TRUE(compute_pipeline);
473 auto cmd_buffer = context->CreateCommandBuffer();
474 auto pass = cmd_buffer->CreateComputePass();
475 ASSERT_TRUE(pass && pass->IsValid());
477 static constexpr size_t kCount = 5;
479 pass->SetPipeline(compute_pipeline);
481 CS::Info info{.count = kCount};
482 CS::Input0<kCount> input_0;
483 CS::Input1<kCount> input_1;
484 for (
size_t i = 0;
i < kCount;
i++) {
485 input_0.elements[
i] =
Vector4(2.0 +
i, 3.0 +
i, 4.0 +
i, 5.0 *
i);
486 input_1.elements[
i] =
Vector4(6.0, 7.0, 8.0, 9.0);
489 input_0.fixed_array[1] =
IPoint32(2, 2);
491 input_0.some_int = 5;
492 input_1.some_struct = CS::SomeStruct{.vf =
Point(3, 4), .i = 42};
494 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
495 context,
"Output Buffer");
497 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
498 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
499 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
500 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
504 EXPECT_FALSE(pass->Compute(
ISize(0, 1)).ok());
505 pass->EncodeCommands();