40 using CS = SampleComputeShader;
41 auto context = GetContext();
42 auto host_buffer = CreateHostBufferFromContext(context);
44 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
48 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
49 ASSERT_TRUE(pipeline_desc.has_value());
50 auto compute_pipeline =
51 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
52 ASSERT_TRUE(compute_pipeline);
54 auto cmd_buffer = context->CreateCommandBuffer();
55 auto pass = cmd_buffer->CreateComputePass();
56 ASSERT_TRUE(pass && pass->IsValid());
58 static constexpr size_t kCount = 5;
60 pass->SetPipeline(compute_pipeline);
62 CS::Info info{.count = kCount};
63 CS::Input0<kCount> input_0;
64 CS::Input1<kCount> input_1;
65 for (
size_t i = 0;
i < kCount;
i++) {
66 input_0.elements[
i] =
Vector4(2.0 +
i, 3.0 +
i, 4.0 +
i, 5.0 *
i);
67 input_1.elements[
i] =
Vector4(6.0, 7.0, 8.0, 9.0);
70 input_0.fixed_array[1] =
IPoint32(2, 2);
73 input_1.some_struct = CS::SomeStruct{.vf =
Point(3, 4), .i = 42};
75 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
76 context,
"Output Buffer");
78 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
79 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
80 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
83 ASSERT_TRUE(pass->Compute(
ISize(kCount, 1)).ok());
84 ASSERT_TRUE(pass->EncodeCommands());
88 context->GetCommandQueue()
91 [&latch, output_buffer, &input_0,
93 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
95 auto view = DeviceBuffer::AsBufferView(output_buffer);
96 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
98 CS::Output<kCount>* output =
99 reinterpret_cast<CS::Output<kCount>*>(
100 output_buffer->OnGetContents());
102 for (size_t i = 0; i < kCount; i++) {
103 Vector4 vector = output->elements[i];
104 Vector4 computed = input_0.elements[i] * input_1.elements[i];
106 Vector4(computed.x + 2 + input_1.some_struct.i,
107 computed.y + 3 + input_1.some_struct.vf.x,
108 computed.z + 5 + input_1.some_struct.vf.y,
119 using CS = PrefixSumTestComputeShader;
120 auto context = GetContext();
121 auto host_buffer = CreateHostBufferFromContext(context);
122 ASSERT_TRUE(context);
123 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
127 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
128 ASSERT_TRUE(pipeline_desc.has_value());
129 auto compute_pipeline =
130 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
131 ASSERT_TRUE(compute_pipeline);
133 auto cmd_buffer = context->CreateCommandBuffer();
134 auto pass = cmd_buffer->CreateComputePass();
135 ASSERT_TRUE(pass && pass->IsValid());
137 static constexpr size_t kCount = 5;
139 pass->SetPipeline(compute_pipeline);
141 CS::InputData<kCount> input_data;
142 input_data.count = kCount;
143 for (
size_t i = 0;
i < kCount;
i++) {
144 input_data.data[
i] = 1 +
i;
147 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
148 context,
"Output Buffer");
150 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
153 ASSERT_TRUE(pass->Compute(
ISize(kCount, 1)).ok());
154 ASSERT_TRUE(pass->EncodeCommands());
158 context->GetCommandQueue()
159 ->Submit({cmd_buffer},
161 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
163 auto view = DeviceBuffer::AsBufferView(output_buffer);
164 EXPECT_EQ(view.GetRange().length,
165 sizeof(CS::OutputData<kCount>));
167 CS::OutputData<kCount>* output =
168 reinterpret_cast<CS::OutputData<kCount>*>(
169 output_buffer->OnGetContents());
172 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
173 for (
size_t i = 0;
i < kCount;
i++) {
174 auto computed_sum = output->data[
i];
175 EXPECT_EQ(computed_sum, expected[
i]);
185 using CS = ThreadgroupSizingTestComputeShader;
186 auto context = GetContext();
187 ASSERT_TRUE(context);
188 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
192 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
193 ASSERT_TRUE(pipeline_desc.has_value());
194 auto compute_pipeline =
195 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
196 ASSERT_TRUE(compute_pipeline);
198 auto cmd_buffer = context->CreateCommandBuffer();
199 auto pass = cmd_buffer->CreateComputePass();
200 ASSERT_TRUE(pass && pass->IsValid());
202 static constexpr size_t kCount = 2048;
204 pass->SetPipeline(compute_pipeline);
206 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
207 context,
"Output Buffer");
209 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
211 ASSERT_TRUE(pass->Compute(
ISize(kCount, 1)).ok());
212 ASSERT_TRUE(pass->EncodeCommands());
216 context->GetCommandQueue()
217 ->Submit({cmd_buffer},
219 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
221 auto view = DeviceBuffer::AsBufferView(output_buffer);
222 EXPECT_EQ(view.GetRange().length,
223 sizeof(CS::OutputData<kCount>));
225 CS::OutputData<kCount>* output =
226 reinterpret_cast<CS::OutputData<kCount>*>(
227 output_buffer->OnGetContents());
229 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
238 using CS = PrefixSumTestComputeShader;
240 auto context = GetContext();
241 auto host_buffer = CreateHostBufferFromContext(context);
243 ASSERT_TRUE(context);
244 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
249 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
250 auto compute_pipeline =
251 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
253 auto cmd_buffer = context->CreateCommandBuffer();
254 auto pass = cmd_buffer->CreateComputePass();
256 static constexpr size_t kCount = 1023;
258 pass->SetPipeline(compute_pipeline);
260 CS::InputData<kCount> input_data;
261 input_data.count = kCount;
262 for (
size_t i = 0;
i < kCount;
i++) {
263 input_data.data[
i] = 1 +
i;
266 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
267 context,
"Output Buffer");
269 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
270 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
272 pass->Compute(
ISize(kCount, 1));
273 pass->EncodeCommands();
274 host_buffer->Reset();
275 return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
277 ASSERT_TRUE(OpenPlaygroundHere(
callback));
281 using CS1 = Stage1ComputeShader;
283 using CS2 = Stage2ComputeShader;
286 auto context = GetContext();
287 auto host_buffer = CreateHostBufferFromContext(context);
288 ASSERT_TRUE(context);
289 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
291 auto pipeline_desc_1 =
292 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
293 ASSERT_TRUE(pipeline_desc_1.has_value());
294 auto compute_pipeline_1 =
295 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
296 ASSERT_TRUE(compute_pipeline_1);
298 auto pipeline_desc_2 =
299 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
300 ASSERT_TRUE(pipeline_desc_2.has_value());
301 auto compute_pipeline_2 =
302 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
303 ASSERT_TRUE(compute_pipeline_2);
305 auto cmd_buffer = context->CreateCommandBuffer();
306 auto pass = cmd_buffer->CreateComputePass();
307 ASSERT_TRUE(pass && pass->IsValid());
309 static constexpr size_t kCount1 = 5;
310 static constexpr size_t kCount2 =
kCount1 * 2;
312 CS1::Input<kCount1> input_1;
315 input_1.elements[
i] =
i;
318 CS2::Input<kCount2> input_2;
319 input_2.count = kCount2;
320 for (
size_t i = 0;
i < kCount2;
i++) {
321 input_2.elements[
i] =
i;
324 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
325 context,
"Output Buffer Stage 1");
326 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
327 context,
"Output Buffer Stage 2");
330 pass->SetPipeline(compute_pipeline_1);
332 CS1::BindInput(*pass, host_buffer->EmplaceStorageBuffer(input_1));
333 CS1::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
335 ASSERT_TRUE(pass->Compute(
ISize(512, 1)).ok());
336 pass->AddBufferMemoryBarrier();
340 pass->SetPipeline(compute_pipeline_2);
342 CS1::BindInput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
343 CS2::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_2));
344 ASSERT_TRUE(pass->Compute(
ISize(512, 1)).ok());
347 ASSERT_TRUE(pass->EncodeCommands());
351 context->GetCommandQueue()
352 ->Submit({cmd_buffer},
353 [&latch, &output_buffer_1,
355 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
357 CS1::Output<kCount2>* output_1 =
358 reinterpret_cast<CS1::Output<kCount2>*>(
359 output_buffer_1->OnGetContents());
360 EXPECT_TRUE(output_1);
361 EXPECT_EQ(output_1->count, 10u);
364 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
366 CS2::Output<kCount2>* output_2 =
367 reinterpret_cast<CS2::Output<kCount2>*>(
368 output_buffer_2->OnGetContents());
369 EXPECT_TRUE(output_2);
370 EXPECT_EQ(output_2->count, 10u);
371 EXPECT_THAT(output_2->elements,
372 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12,
383 using CS = SampleComputeShader;
384 auto context = GetContext();
385 auto host_buffer = CreateHostBufferFromContext(context);
386 ASSERT_TRUE(context);
387 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
391 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
392 ASSERT_TRUE(pipeline_desc.has_value());
393 auto compute_pipeline =
394 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
395 ASSERT_TRUE(compute_pipeline);
397 auto cmd_buffer = context->CreateCommandBuffer();
398 auto pass = cmd_buffer->CreateComputePass();
399 ASSERT_TRUE(pass && pass->IsValid());
401 static constexpr size_t kCount = 5;
403 pass->SetPipeline(compute_pipeline);
405 CS::Info info{.count = kCount};
406 CS::Input0<kCount> input_0;
407 CS::Input1<kCount> input_1;
408 for (
size_t i = 0;
i < kCount;
i++) {
409 input_0.elements[
i] =
Vector4(2.0 +
i, 3.0 +
i, 4.0 +
i, 5.0 *
i);
410 input_1.elements[
i] =
Vector4(6.0, 7.0, 8.0, 9.0);
413 input_0.fixed_array[1] =
IPoint32(2, 2);
415 input_0.some_int = 5;
416 input_1.some_struct = CS::SomeStruct{.vf =
Point(3, 4), .i = 42};
418 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
419 context,
"Output Buffer");
421 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
422 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
423 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
424 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
426 ASSERT_TRUE(pass->Compute(
ISize(kCount, 1)).ok());
427 ASSERT_TRUE(pass->EncodeCommands());
431 context->GetCommandQueue()
434 [&latch, output_buffer, &input_0,
436 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
438 auto view = DeviceBuffer::AsBufferView(output_buffer);
439 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
441 CS::Output<kCount>* output =
442 reinterpret_cast<CS::Output<kCount>*>(
443 output_buffer->OnGetContents());
445 for (size_t i = 0; i < kCount; i++) {
446 Vector4 vector = output->elements[i];
447 Vector4 computed = input_0.elements[i] * input_1.elements[i];
449 Vector4(computed.x + 2 + input_1.some_struct.i,
450 computed.y + 3 + input_1.some_struct.vf.x,
451 computed.z + 5 + input_1.some_struct.vf.y,
462 using CS = SampleComputeShader;
463 auto context = GetContext();
464 auto host_buffer = CreateHostBufferFromContext(context);
465 ASSERT_TRUE(context);
466 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
470 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
471 ASSERT_TRUE(pipeline_desc.has_value());
472 auto compute_pipeline =
473 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
474 ASSERT_TRUE(compute_pipeline);
476 auto cmd_buffer = context->CreateCommandBuffer();
477 auto pass = cmd_buffer->CreateComputePass();
478 ASSERT_TRUE(pass && pass->IsValid());
480 static constexpr size_t kCount = 5;
482 pass->SetPipeline(compute_pipeline);
484 CS::Info info{.count = kCount};
485 CS::Input0<kCount> input_0;
486 CS::Input1<kCount> input_1;
487 for (
size_t i = 0;
i < kCount;
i++) {
488 input_0.elements[
i] =
Vector4(2.0 +
i, 3.0 +
i, 4.0 +
i, 5.0 *
i);
489 input_1.elements[
i] =
Vector4(6.0, 7.0, 8.0, 9.0);
492 input_0.fixed_array[1] =
IPoint32(2, 2);
494 input_0.some_int = 5;
495 input_1.some_struct = CS::SomeStruct{.vf =
Point(3, 4), .i = 42};
497 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
498 context,
"Output Buffer");
500 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
501 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
502 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
503 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
507 EXPECT_FALSE(pass->Compute(
ISize(0, 1)).ok());
508 pass->EncodeCommands();