aboutsummaryrefslogtreecommitdiff
path: root/vcpkg/scripts/test_ports/vcpkg-ci-dawn/project/main.cpp
diff options
context:
space:
mode:
authorEthan Morgan <ethan@gweithio.com>2026-02-14 16:44:06 +0000
committerEthan Morgan <ethan@gweithio.com>2026-02-14 16:44:06 +0000
commit54409423f767d8b1cf30cb7d0efca6b4ca138823 (patch)
treed915ac7828703ce4b963efdd9728a1777ba18c1e /vcpkg/scripts/test_ports/vcpkg-ci-dawn/project/main.cpp
move to own git serverHEADmaster
Diffstat (limited to 'vcpkg/scripts/test_ports/vcpkg-ci-dawn/project/main.cpp')
-rwxr-xr-xvcpkg/scripts/test_ports/vcpkg-ci-dawn/project/main.cpp391
1 files changed, 391 insertions, 0 deletions
diff --git a/vcpkg/scripts/test_ports/vcpkg-ci-dawn/project/main.cpp b/vcpkg/scripts/test_ports/vcpkg-ci-dawn/project/main.cpp
new file mode 100755
index 0000000..74bf086
--- /dev/null
+++ b/vcpkg/scripts/test_ports/vcpkg-ci-dawn/project/main.cpp
@@ -0,0 +1,391 @@
+//
+// Copyright (c) 2024 xiaozhuai
+//
+
+#define GLFW_INCLUDE_NONE
+
+#include <cstdio>
+#include <string>
+#include <vector>
+
+#include "GLFW/glfw3.h"
+#include "webgpu/webgpu_cpp.h"
+
+#if defined(__EMSCRIPTEN__)
+#include "emscripten/emscripten.h"
+#endif
+
+#define LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
+
+#if !defined(__PRETTY_FUNCTION__) && !defined(__GNUC__)
+#define MY_PRETTY_FUNCTION __FUNCSIG__
+#else
+#define MY_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#endif
+
+#define ASSERT(expr, fmt, ...) \
+ do { \
+ if (!(expr)) { \
+ LOG("Assertion failed: %s:%d, func: \"%s\", expr: \"%s\", message: " /**/ \
+ fmt, /**/ \
+ __FILE__, __LINE__, MY_PRETTY_FUNCTION, #expr, /**/ \
+ ##__VA_ARGS__); \
+ abort(); \
+ } \
+ } while (0)
+
+wgpu::Instance create_instance() {
+ wgpu::InstanceDescriptor instance_desc;
+ std::vector<wgpu::InstanceFeatureName> required_features = {
+ wgpu::InstanceFeatureName::TimedWaitAny,
+ };
+ instance_desc.requiredFeatureCount = required_features.size();
+ instance_desc.requiredFeatures = required_features.data();
+ return wgpu::CreateInstance(&instance_desc);
+}
+
+wgpu::Surface create_surface(const wgpu::Instance &instance, GLFWwindow *window);
+
+wgpu::Adapter request_adapter(const wgpu::Instance &instance, const wgpu::Surface &surface) {
+ wgpu::RequestAdapterOptions adapter_options;
+ adapter_options.compatibleSurface = surface;
+ adapter_options.powerPreference = wgpu::PowerPreference::HighPerformance;
+
+ wgpu::Adapter adapter;
+ auto adapter_future = instance.RequestAdapter(
+ &adapter_options, wgpu::CallbackMode::WaitAnyOnly,
+ [&adapter](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter_ret, wgpu::StringView message) {
+ ASSERT(status == wgpu::RequestAdapterStatus::Success && adapter_ret != nullptr, "Failed to get adapter: %s",
+ message.data);
+ adapter = std::move(adapter_ret);
+ });
+ ASSERT(instance.WaitAny(adapter_future, wgpu::kLimitU64Undefined) == wgpu::WaitStatus::Success,
+ "Failed to wait for adapter request");
+
+ return adapter;
+}
+
+void device_lost_callback(const wgpu::Device &, wgpu::DeviceLostReason, wgpu::StringView message) {
+ LOG("Device lost: %s", message.data);
+}
+
+void device_uncaptured_error_callback(const wgpu::Device &, wgpu::ErrorType type, wgpu::StringView message) {
+ const char *error_type;
+ switch (type) {
+ case wgpu::ErrorType::Validation:
+ error_type = "Validation";
+ break;
+ case wgpu::ErrorType::OutOfMemory:
+ error_type = "Out of memory";
+ break;
+ case wgpu::ErrorType::Internal:
+ error_type = "Internal";
+ break;
+ case wgpu::ErrorType::Unknown:
+ error_type = "Unknown";
+ break;
+ default:
+ ASSERT(false, "Unknown ErrorType");
+ }
+ LOG("Uncaptured Error %s: %s", error_type, message.data);
+}
+
+wgpu::Device request_device(const wgpu::Instance &instance, const wgpu::Adapter &adapter) {
+ wgpu::DeviceDescriptor device_desc;
+
+ device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous, device_lost_callback);
+ device_desc.SetUncapturedErrorCallback(device_uncaptured_error_callback);
+
+ wgpu::Device device;
+ auto device_future = adapter.RequestDevice(
+ &device_desc, wgpu::CallbackMode::WaitAnyOnly,
+ [&device](wgpu::RequestDeviceStatus status, wgpu::Device device_ret, wgpu::StringView message) {
+ ASSERT(status == wgpu::RequestDeviceStatus::Success && device_ret != nullptr, "Failed to get device: %s",
+ message.data);
+ device = std::move(device_ret);
+ });
+ ASSERT(instance.WaitAny(device_future, wgpu::kLimitU64Undefined) == wgpu::WaitStatus::Success,
+ "Failed to wait for device request");
+
+ return device;
+}
+
+wgpu::ShaderModule create_shader(const wgpu::Device &device, const std::string &shader_code) {
+ wgpu::ShaderSourceWGSL shader_code_desc;
+ shader_code_desc.sType = wgpu::SType::ShaderSourceWGSL;
+ shader_code_desc.code = shader_code.c_str();
+ wgpu::ShaderModuleDescriptor shader_desc;
+ shader_desc.nextInChain = &shader_code_desc;
+ return device.CreateShaderModule(&shader_desc);
+}
+
+struct alignas(16) Uniforms {
+ struct {
+ float width = 0.0f;
+ float height = 0.0f;
+ } resolution;
+ float time = 0.0f;
+};
+
+void glfw_error_callback(int error, const char *description) { LOG("GLFW error, %d, %s", error, description); }
+
+struct AppState {
+ wgpu::Instance instance;
+ wgpu::Surface surface;
+ wgpu::Adapter adapter;
+ wgpu::Device device;
+ wgpu::Queue queue;
+ wgpu::SurfaceConfiguration surface_config;
+ int surface_width = 0;
+ int surface_height = 0;
+};
+
+int main() {
+ glfwSetErrorCallback(glfw_error_callback);
+ ASSERT(glfwInit(), "GLFW init failed");
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+ auto *window = glfwCreateWindow(1024, 1024, "vcpkg-ci-dawn", nullptr, nullptr);
+
+ AppState state;
+ state.instance = create_instance();
+ state.surface = create_surface(state.instance, window);
+ state.adapter = request_adapter(state.instance, state.surface);
+ state.device = request_device(state.instance, state.adapter);
+ state.queue = state.device.GetQueue();
+
+ wgpu::SurfaceCapabilities surface_capabilities;
+ state.surface.GetCapabilities(state.adapter, &surface_capabilities);
+ glfwGetFramebufferSize(window, &state.surface_width, &state.surface_height);
+
+ state.surface_config.device = state.device;
+ state.surface_config.usage = wgpu::TextureUsage::RenderAttachment;
+ state.surface_config.format = surface_capabilities.formats[0];
+ state.surface_config.presentMode = surface_capabilities.presentModes[0];
+ state.surface_config.alphaMode = surface_capabilities.alphaModes[0];
+ state.surface_config.width = state.surface_width;
+ state.surface_config.height = state.surface_height;
+ state.surface.Configure(&state.surface_config);
+
+ glfwSetWindowUserPointer(window, &state);
+
+ glfwSetKeyCallback(window, [](GLFWwindow *window, int key, int scancode, int action, int mods) {
+ if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ }
+ });
+ glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) {
+ auto &state = *static_cast<AppState *>(glfwGetWindowUserPointer(window));
+ state.surface_width = width;
+ state.surface_height = height;
+ state.surface_config.width = width;
+ state.surface_config.height = height;
+ state.surface.Configure(&state.surface_config);
+ });
+
+ std::string shader_source = R"(
+struct Uniforms {
+ resolution: vec2f,
+ time: f32,
+};
+
+@group(0)
+@binding(0)
+var<uniform> uniforms: Uniforms;
+
+struct VertexInput {
+ @location(0)
+ pos: vec2f,
+};
+
+struct VertexOutput {
+ @builtin(position)
+ pos: vec4f,
+};
+
+@vertex
+fn vs_main(input: VertexInput) -> VertexOutput {
+ var output: VertexOutput;
+ output.pos = vec4f(input.pos, 0.0, 1.0);
+ return output;
+}
+
+struct FragmentInput {
+ @builtin(position)
+ coord: vec4f,
+};
+
+struct FragmentOutput {
+ @location(0)
+ color: vec4f,
+};
+
+fn palette(t: f32) -> vec3f{
+ let a = vec3f(0.5, 0.5, 0.5);
+ let b = vec3f(0.5, 0.5, 0.5);
+ let c = vec3f(1.0, 1.0, 1.0);
+ let d = vec3f(0.263, 0.416, 0.557);
+ return a + b * cos(6.28318 * (c * t + d));
+}
+
+@fragment
+fn fs_main(input: FragmentInput) -> FragmentOutput {
+ var uv = (input.coord.xy * 2.0 - uniforms.resolution) / min(uniforms.resolution.x, uniforms.resolution.y);
+ let uv0 = uv;
+ var color = vec3f(0.0);
+ for (var i: f32 = 0.0; i < 4.0; i += 1.0) {
+ uv = fract(uv * 1.5) - 0.5;
+ var d = length(uv) * exp(-length(uv0));
+ let col = palette(length(uv0) + i * 0.4 + uniforms.time * 0.4);
+ d = sin(d * 8.0 + uniforms.time) / 8.0;
+ d = abs(d);
+ d = pow(0.01 / d, 1.2);
+ color += col * d;
+ }
+ var output: FragmentOutput;
+ output.color = vec4f(color, 1.0);
+ return output;
+}
+)";
+ auto shader_module = create_shader(state.device, shader_source);
+
+ constexpr float vertices[12] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
+ constexpr int vertex_count = std::size(vertices) / 2;
+ wgpu::BufferDescriptor vertex_buffer_desc;
+ vertex_buffer_desc.size = sizeof(vertices);
+ vertex_buffer_desc.usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst;
+ wgpu::Buffer vertex_buffer = state.device.CreateBuffer(&vertex_buffer_desc);
+ state.queue.WriteBuffer(vertex_buffer, 0, vertices, sizeof(vertices));
+
+ Uniforms uniforms;
+ wgpu::BufferDescriptor uniform_buffer_desc;
+ uniform_buffer_desc.size = sizeof(uniforms);
+ uniform_buffer_desc.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst;
+ wgpu::Buffer uniform_buffer = state.device.CreateBuffer(&uniform_buffer_desc);
+ state.queue.WriteBuffer(uniform_buffer, 0, &uniforms, sizeof(uniforms));
+
+ wgpu::RenderPipelineDescriptor pipeline_desc;
+
+ std::vector<wgpu::VertexAttribute> vertex_attributes(1);
+ vertex_attributes[0].format = wgpu::VertexFormat::Float32x2;
+ vertex_attributes[0].offset = 0;
+ vertex_attributes[0].shaderLocation = 0;
+ std::vector<wgpu::VertexBufferLayout> vertex_layouts(1);
+ vertex_layouts[0].arrayStride = 2 * sizeof(float);
+ vertex_layouts[0].attributeCount = vertex_attributes.size();
+ vertex_layouts[0].attributes = vertex_attributes.data();
+ vertex_layouts[0].stepMode = wgpu::VertexStepMode::Vertex;
+
+ pipeline_desc.vertex.bufferCount = vertex_layouts.size();
+ pipeline_desc.vertex.buffers = vertex_layouts.data();
+
+ pipeline_desc.vertex.module = shader_module;
+ pipeline_desc.vertex.entryPoint = "vs_main";
+ pipeline_desc.vertex.constantCount = 0;
+ pipeline_desc.vertex.constants = nullptr;
+
+ pipeline_desc.primitive.topology = wgpu::PrimitiveTopology::TriangleList;
+ pipeline_desc.primitive.stripIndexFormat = wgpu::IndexFormat::Undefined;
+ pipeline_desc.primitive.frontFace = wgpu::FrontFace::CCW;
+ pipeline_desc.primitive.cullMode = wgpu::CullMode::None;
+
+ wgpu::FragmentState fragment_state;
+ fragment_state.module = shader_module;
+ fragment_state.entryPoint = "fs_main";
+ fragment_state.constantCount = 0;
+ fragment_state.constants = nullptr;
+
+ wgpu::BlendState blend_state;
+ blend_state.color.srcFactor = wgpu::BlendFactor::SrcAlpha;
+ blend_state.color.dstFactor = wgpu::BlendFactor::OneMinusSrcAlpha;
+ blend_state.color.operation = wgpu::BlendOperation::Add;
+ blend_state.alpha.srcFactor = wgpu::BlendFactor::Zero;
+ blend_state.alpha.dstFactor = wgpu::BlendFactor::One;
+ blend_state.alpha.operation = wgpu::BlendOperation::Add;
+
+ wgpu::ColorTargetState color_target;
+ color_target.format = state.surface_config.format;
+ color_target.blend = &blend_state;
+ color_target.writeMask = wgpu::ColorWriteMask::All;
+
+ fragment_state.targetCount = 1;
+ fragment_state.targets = &color_target;
+ pipeline_desc.fragment = &fragment_state;
+
+ pipeline_desc.depthStencil = nullptr;
+ pipeline_desc.multisample.count = 1;
+ pipeline_desc.multisample.mask = ~0u;
+
+ pipeline_desc.multisample.alphaToCoverageEnabled = false;
+ pipeline_desc.layout = nullptr;
+
+ wgpu::RenderPipeline pipeline = state.device.CreateRenderPipeline(&pipeline_desc);
+
+ std::vector<wgpu::BindGroupEntry> bind_group_entries(1);
+ bind_group_entries[0].binding = 0;
+ bind_group_entries[0].buffer = uniform_buffer;
+ bind_group_entries[0].size = uniform_buffer.GetSize();
+
+ wgpu::BindGroupDescriptor bind_group_desc;
+ bind_group_desc.layout = pipeline.GetBindGroupLayout(0);
+ bind_group_desc.entryCount = bind_group_entries.size();
+ bind_group_desc.entries = bind_group_entries.data();
+ wgpu::BindGroup bind_group = state.device.CreateBindGroup(&bind_group_desc);
+
+ const double start_time = glfwGetTime();
+ while (!glfwWindowShouldClose(window)) {
+ glfwPollEvents();
+#if defined(__EMSCRIPTEN__)
+ emscripten_sleep(0);
+#endif
+
+ const double time = glfwGetTime() - start_time;
+
+ wgpu::SurfaceTexture surface_texture;
+ state.surface.GetCurrentTexture(&surface_texture);
+ ASSERT(surface_texture.status == wgpu::SurfaceGetCurrentTextureStatus::SuccessOptimal ||
+ surface_texture.status == wgpu::SurfaceGetCurrentTextureStatus::SuccessSuboptimal,
+ "Failed to get current texture");
+ if (surface_texture.status == wgpu::SurfaceGetCurrentTextureStatus::SuccessSuboptimal) {
+ LOG("Surface texture is suboptimal");
+ }
+
+ wgpu::Texture texture = surface_texture.texture;
+ wgpu::TextureView frame = texture.CreateView();
+
+ uniforms.resolution.width = static_cast<float>(texture.GetWidth());
+ uniforms.resolution.height = static_cast<float>(texture.GetHeight());
+ uniforms.time = static_cast<float>(time);
+ state.queue.WriteBuffer(uniform_buffer, 0, &uniforms, sizeof(uniforms));
+
+ auto encoder = state.device.CreateCommandEncoder();
+
+ wgpu::RenderPassColorAttachment color_attachment;
+ color_attachment.view = frame;
+ color_attachment.loadOp = wgpu::LoadOp::Clear;
+ color_attachment.storeOp = wgpu::StoreOp::Store;
+ color_attachment.clearValue = {0.1f, 0.2f, 0.3f, 1.0f};
+ wgpu::RenderPassDescriptor pass_desc;
+ pass_desc.colorAttachmentCount = 1;
+ pass_desc.colorAttachments = &color_attachment;
+ pass_desc.depthStencilAttachment = nullptr;
+
+ auto pass = encoder.BeginRenderPass(&pass_desc);
+ pass.SetPipeline(pipeline);
+ pass.SetVertexBuffer(0, vertex_buffer, 0, vertex_buffer.GetSize());
+ pass.SetBindGroup(0, bind_group, 0, nullptr);
+ pass.Draw(vertex_count);
+ pass.End();
+
+ wgpu::CommandBuffer command_buffer = encoder.Finish();
+ state.queue.Submit(1, &command_buffer);
+
+#if !defined(__EMSCRIPTEN__)
+ ASSERT(state.surface.Present(), "Failed to present the surface");
+ state.device.Tick();
+#endif
+ }
+
+ glfwDestroyWindow(window);
+ glfwTerminate();
+ return 0;
+}