Repository navigation
Expand file tree
/
Copy pathmain_webgpu_indirect.cpp
More file actions
56 lines (55 loc) · 2.88 KB
/
Copy pathmain_webgpu_indirect.cpp
File metadata and controls
56 lines (55 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "webgpu_feature_test.h"
#include <cstdint>
namespace {
auto run()->void {
auto module{gpu_test::shader(R"(
struct Vertex { @builtin(position) position: vec4f, @location(0) @interpolate(flat) instance: u32 }
@vertex fn vertex(@builtin(vertex_index) i: u32, @builtin(instance_index) instance: u32) -> Vertex {
let positions = array(vec2f(-1, -1), vec2f(3, -1), vec2f(-1, 3));
return Vertex(vec4f(positions[i], 0, 1), instance);
}
@fragment fn fragment(input: Vertex) -> @location(0) vec4f {
if (input.instance == 7u) { return vec4f(22.0 / 255.0, 130.0 / 255.0, 73.0 / 255.0, 1); }
return vec4f(1, 0, 0, 1);
}
)")};
wgpu::ColorTargetState colour{.format = wgpu::TextureFormat::RGBA8Unorm};
wgpu::FragmentState fragment{.module = module, .entryPoint = "fragment", .targetCount = 1, .targets = &colour};
wgpu::RenderPipelineDescriptor pipeline_descriptor{
.vertex{.module = module, .entryPoint = "vertex"},
.primitive{.topology = wgpu::PrimitiveTopology::TriangleList}, .fragment = &fragment
};
auto pipeline{gpu_test::device.CreateRenderPipeline(&pipeline_descriptor)};
wgpu::TextureDescriptor texture_descriptor{
.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc,
.dimension = wgpu::TextureDimension::e2D, .size{1, 1, 1}, .format = wgpu::TextureFormat::RGBA8Unorm
};
auto texture{gpu_test::device.CreateTexture(&texture_descriptor)};
auto indirect{gpu_test::buffer(16, wgpu::BufferUsage::Indirect | wgpu::BufferUsage::CopyDst)};
std::uint32_t const arguments[]{3, 1, 0, 7}; // vertex count, instance count, first vertex, first instance
gpu_test::device.GetQueue().WriteBuffer(indirect, 0, arguments, sizeof(arguments));
wgpu::RenderPassColorAttachment attachment{
.view = texture.CreateView(), .loadOp = wgpu::LoadOp::Clear, .storeOp = wgpu::StoreOp::Store,
.clearValue{1, 0, 0, 1}
};
wgpu::RenderPassDescriptor pass_descriptor{.colorAttachmentCount = 1, .colorAttachments = &attachment};
auto encoder{gpu_test::device.CreateCommandEncoder()};
auto pass{encoder.BeginRenderPass(&pass_descriptor)};
pass.SetPipeline(pipeline);
pass.DrawIndirect(indirect, 0);
pass.End();
auto output{gpu_test::buffer(256, wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc)};
wgpu::TexelCopyTextureInfo source{.texture = texture};
wgpu::TexelCopyBufferInfo destination{.layout{.bytesPerRow = 256, .rowsPerImage = 1}, .buffer = output};
wgpu::Extent3D extent{1, 1, 1};
encoder.CopyTextureToBuffer(&source, &destination, &extent);
gpu_test::submit(encoder);
gpu_test::verify(output, 256, [](void const *data) {
auto const *pixel{static_cast<std::uint8_t const *>(data)};
return pixel[0] == 22 && pixel[1] == 130 && pixel[2] == 73 && pixel[3] == 255;
}, "Indirect draw · first instance verified");
}
}
auto main()->int {
return gpu_test::start(wgpu::FeatureName::IndirectFirstInstance, run);
}