21 # define SYSTEM_WINDOWS
22 # define GLFW_EXPOSE_NATIVE_WIN32
23 # define WIN32_LEAN_AND_MEAN
25 #elif defined(__linux__)
27 # define GLFW_EXPOSE_NATIVE_X11
28 #elif defined(__APPLE__)
29 # ifndef SYSTEM_DARWIN
30 # define SYSTEM_DARWIN
32 # define GLFW_EXPOSE_NATIVE_COCOA
36 #include <GLFW/glfw3.h>
37 #include <GLFW/glfw3native.h>
38 #include <opencv2/imgcodecs.hpp>
39 #include <opencv2/imgproc.hpp>
53 #define WEBGPU_DEMO_LOG(msg) std::cout << (msg) << std::endl
55 #define WEBGPU_DEMO_CHECK(condition, errorMsg) \
58 std::cerr << (errorMsg) << std::endl; \
121 static_assert(
sizeof(
ShaderUniformData) % 16 == 0,
"uniform data size must be a multiple of 16");
161 WGPUSurfaceTexture surfaceTexture;
162 wgpuSurfaceGetCurrentTexture(app.
surface, &surfaceTexture);
167 switch (surfaceTexture.status)
169 case WGPUSurfaceGetCurrentTextureStatus_Success:
171 if (surfaceTexture.suboptimal)
173 WEBGPU_DEMO_LOG(
"[WebGPU] Re-configuring currently suboptimal surface");
175 wgpuSurfaceGetCurrentTexture(app.
surface, &surfaceTexture);
180 case WGPUSurfaceGetCurrentTextureStatus_Timeout:
181 case WGPUSurfaceGetCurrentTextureStatus_Outdated:
182 case WGPUSurfaceGetCurrentTextureStatus_Lost:
185 wgpuSurfaceGetCurrentTexture(app.
surface, &surfaceTexture);
188 case WGPUSurfaceGetCurrentTextureStatus_OutOfMemory:
189 case WGPUSurfaceGetCurrentTextureStatus_DeviceLost:
194 case WGPUSurfaceGetCurrentTextureStatus_Force32:
202 WGPUTextureView view = wgpuTextureCreateView(surfaceTexture.texture,
nullptr);
210 projectionMatrix.
perspective(70.0f, aspectRatio, 0.1, 1000.0f);
228 WGPUCommandEncoderDescriptor cmdEncoderDesc = {};
229 cmdEncoderDesc.label =
"Demo Command Encoder";
231 WGPUCommandEncoder cmdEncoder = wgpuDeviceCreateCommandEncoder(app.
device, &cmdEncoderDesc);
240 WGPURenderPassColorAttachment colorAttachment = {};
241 colorAttachment.view = view;
242 colorAttachment.loadOp = WGPULoadOp_Clear;
243 colorAttachment.storeOp = WGPUStoreOp_Store;
244 colorAttachment.clearValue.r = 0.3;
245 colorAttachment.clearValue.g = 0.0;
246 colorAttachment.clearValue.b = 0.2;
247 colorAttachment.clearValue.a = 1.0;
249 WGPURenderPassDepthStencilAttachment depthStencilAttachment = {};
251 depthStencilAttachment.depthLoadOp = WGPULoadOp_Clear;
252 depthStencilAttachment.depthStoreOp = WGPUStoreOp_Store;
253 depthStencilAttachment.depthClearValue = 1.0f;
254 depthStencilAttachment.depthReadOnly =
false;
255 depthStencilAttachment.stencilLoadOp = WGPULoadOp_Clear;
256 depthStencilAttachment.stencilStoreOp = WGPUStoreOp_Store;
257 depthStencilAttachment.stencilClearValue = 0.0f;
258 depthStencilAttachment.stencilReadOnly =
true;
260 WGPURenderPassDescriptor renderPassDesc = {};
261 renderPassDesc.label =
"Demo Render Pass";
262 renderPassDesc.colorAttachmentCount = 1;
263 renderPassDesc.colorAttachments = &colorAttachment;
264 renderPassDesc.depthStencilAttachment = &depthStencilAttachment;
270 WGPURenderPassEncoder renderPassEncoder = wgpuCommandEncoderBeginRenderPass(cmdEncoder, &renderPassDesc);
271 wgpuRenderPassEncoderSetPipeline(renderPassEncoder, app.
pipeline);
273 wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, app.
indexBuffer, WGPUIndexFormat_Uint16, 0, app.
indexDataSize);
274 wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, app.
bindGroup, 0,
nullptr);
275 wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, app.
indexCount, 1, 0, 0, 0);
276 wgpuRenderPassEncoderEnd(renderPassEncoder);
281 WGPUCommandBufferDescriptor cmdBufferDesc = {};
282 cmdBufferDesc.label =
"Demo Command Buffer";
284 WGPUCommandBuffer cmdBuffer = wgpuCommandEncoderFinish(cmdEncoder, &cmdBufferDesc);
288 wgpuQueueSubmit(app.
queue, 1, &cmdBuffer);
292 wgpuSurfacePresent(app.
surface);
295 wgpuCommandBufferRelease(cmdBuffer);
296 wgpuRenderPassEncoderRelease(renderPassEncoder);
297 wgpuCommandEncoderRelease(cmdEncoder);
298 wgpuTextureViewRelease(view);
299 wgpuTextureRelease(surfaceTexture.texture);
319 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
321 app.
window = glfwCreateWindow(1280, 720,
"WebGPU Demo",
nullptr,
nullptr);
325 glfwSetWindowUserPointer(app.
window, &app);
335 "[WebGPU] Failed to acquire adapter: " + std::string(message));
338 WGPUAdapter* outAdapter = (WGPUAdapter*)userdata;
339 *outAdapter = adapter;
348 "[WebGPU] Failed to acquire device: " + std::string(message));
351 WGPUDevice* outDevice = (WGPUDevice*)userdata;
361 app.
instance = wgpuCreateInstance(
nullptr);
368 WGPURequestAdapterOptions adapterOptions = {};
370 wgpuInstanceRequestAdapter(app.
instance,
377 WGPUSupportedLimits adapterLimits = {};
378 wgpuAdapterGetLimits(app.
adapter, &adapterLimits);
386 WGPURequiredLimits requiredLimits = {};
387 requiredLimits.limits.maxVertexAttributes = 3u;
388 requiredLimits.limits.maxVertexBuffers = 1u;
389 requiredLimits.limits.maxBufferSize = 2048ull;
390 requiredLimits.limits.maxVertexBufferArrayStride =
sizeof(
VertexData);
391 requiredLimits.limits.maxInterStageShaderComponents = 5u;
392 requiredLimits.limits.maxBindGroups = 1u;
393 requiredLimits.limits.maxBindingsPerBindGroup = 3u;
394 requiredLimits.limits.maxUniformBuffersPerShaderStage = 1u;
395 requiredLimits.limits.maxUniformBufferBindingSize = 512ull;
396 requiredLimits.limits.maxSampledTexturesPerShaderStage = 1u;
397 requiredLimits.limits.maxSamplersPerShaderStage = 1u;
398 requiredLimits.limits.maxTextureDimension1D = 4096;
399 requiredLimits.limits.maxTextureDimension2D = 4096;
400 requiredLimits.limits.maxTextureArrayLayers = 1;
401 requiredLimits.limits.minStorageBufferOffsetAlignment = adapterLimits.limits.minStorageBufferOffsetAlignment;
402 requiredLimits.limits.minUniformBufferOffsetAlignment = adapterLimits.limits.minUniformBufferOffsetAlignment;
404 WGPUDeviceDescriptor deviceDesc = {};
405 deviceDesc.label =
"Demo Device";
406 deviceDesc.requiredLimits = &requiredLimits;
407 deviceDesc.defaultQueue.label =
"Demo Queue";
409 wgpuAdapterRequestDevice(app.
adapter,
425 #if defined(SYSTEM_WINDOWS)
426 WGPUSurfaceDescriptorFromWindowsHWND nativeSurfaceDesc = {};
427 nativeSurfaceDesc.chain.sType = WGPUSType_SurfaceDescriptorFromWindowsHWND;
428 nativeSurfaceDesc.hinstance = GetModuleHandle(
nullptr);
429 nativeSurfaceDesc.hwnd = glfwGetWin32Window(app.
window);
430 #elif defined(SYSTEM_LINUX)
431 WGPUSurfaceDescriptorFromXlibWindow nativeSurfaceDesc = {};
432 nativeSurfaceDesc.chain.sType = WGPUSType_SurfaceDescriptorFromXlibWindow;
433 nativeSurfaceDesc.display = glfwGetX11Display();
434 nativeSurfaceDesc.window = glfwGetX11Window(app.
window);
435 #elif defined(SYSTEM_DARWIN)
436 WGPUSurfaceDescriptorFromMetalLayer nativeSurfaceDesc = {};
437 nativeSurfaceDesc.chain.sType = WGPUSType_SurfaceDescriptorFromMetalLayer;
441 WGPUSurfaceDescriptor surfaceDesc = {};
442 surfaceDesc.label =
"Demo Surface";
443 surfaceDesc.nextInChain = (
const WGPUChainedStruct*)&nativeSurfaceDesc;
453 WGPUSurfaceCapabilities surfaceCapabilities;
454 wgpuSurfaceGetCapabilities(app.
surface,
456 &surfaceCapabilities);
459 glfwGetFramebufferSize(app.
window,
468 app.
surfaceConfig.alphaMode = surfaceCapabilities.alphaModes[0];
478 std::vector<VertexData> vertexData =
481 {-0.5, 0.5, -0.5, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
482 {-0.5, -0.5, -0.5, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f},
483 {-0.5, 0.5, 0.5, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f},
484 {-0.5, -0.5, 0.5, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f},
487 { 0.5, 0.5, 0.5, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
488 { 0.5, -0.5, 0.5, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f},
489 { 0.5, 0.5, -0.5, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f},
490 { 0.5, -0.5, -0.5, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f},
493 {-0.5, -0.5, 0.5, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f},
494 {-0.5, -0.5, -0.5, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f},
495 { 0.5, -0.5, 0.5, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f},
496 { 0.5, -0.5, -0.5, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f},
499 {-0.5, 0.5, -0.5, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
500 {-0.5, 0.5, 0.5, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
501 { 0.5, 0.5, -0.5, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f},
502 { 0.5, 0.5, 0.5, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f},
505 { 0.5, 0.5, -0.5, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
506 { 0.5, -0.5, -0.5, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f},
507 {-0.5, 0.5, -0.5, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f},
508 {-0.5, -0.5, -0.5, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f},
511 {-0.5, 0.5, 0.5, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
512 {-0.5, -0.5, 0.5, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
513 { 0.5, 0.5, 0.5, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f},
514 { 0.5, -0.5, 0.5, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f},
518 unsigned vertexCount = vertexData.size();
521 WGPUBufferDescriptor vertexBufferDesc = {};
522 vertexBufferDesc.label =
"Demo Vertex Buffer";
524 vertexBufferDesc.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex;
531 wgpuQueueWriteBuffer(app.
queue,
540 std::vector<std::uint16_t> indexData =
545 12, 13, 14, 14, 13, 15,
546 16, 17, 18, 18, 17, 19,
547 20, 21, 22, 22, 21, 23,
552 app.
indexDataSize = indexData.size() *
sizeof(std::uint16_t);
554 WGPUBufferDescriptor indexBufferDesc = {};
555 indexBufferDesc.label =
"Demo Index Buffer";
557 indexBufferDesc.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index;
563 wgpuQueueWriteBuffer(app.
queue,
571 WGPUBufferDescriptor uniformBufferDesc = {};
572 uniformBufferDesc.label =
"Demo Uniform Buffer";
574 uniformBufferDesc.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
581 wgpuQueueWriteBuffer(app.
queue,
622 cv::Mat image = cv::imread(std::string(SL_PROJECT_ROOT) +
"/data/images/textures/brickwall0512_C.jpg");
623 cv::cvtColor(image, image, cv::COLOR_BGR2RGBA);
625 unsigned imageWidth = image.cols;
626 unsigned imageHeight = image.rows;
627 unsigned pixelDataSize = 4 * imageWidth * imageHeight;
629 WGPUTextureDescriptor textureDesc = {};
630 textureDesc.label =
"Demo Texture";
631 textureDesc.usage = WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding;
632 textureDesc.dimension = WGPUTextureDimension_2D;
633 textureDesc.size.width = imageWidth;
634 textureDesc.size.height = imageHeight;
635 textureDesc.size.depthOrArrayLayers = 1;
636 textureDesc.format = WGPUTextureFormat_RGBA8UnormSrgb;
637 textureDesc.mipLevelCount = 4;
638 textureDesc.sampleCount = 1;
640 app.
texture = wgpuDeviceCreateTexture(app.
device, &textureDesc);
645 WGPUImageCopyTexture destination = {};
646 destination.texture = app.
texture;
647 destination.mipLevel = 0;
648 destination.origin.x = 0;
649 destination.origin.y = 0;
650 destination.origin.z = 0;
651 destination.aspect = WGPUTextureAspect_All;
654 WGPUTextureDataLayout pixelDataLayout = {};
655 pixelDataLayout.offset = 0;
656 pixelDataLayout.bytesPerRow = 4 * textureDesc.size.width;
657 pixelDataLayout.rowsPerImage = textureDesc.size.height;
661 WGPUExtent3D mipLevelSize;
662 mipLevelSize.width = textureDesc.size.width;
663 mipLevelSize.height = textureDesc.size.height;
664 mipLevelSize.depthOrArrayLayers = 1;
666 for (
unsigned mipLevel = 0; mipLevel < textureDesc.mipLevelCount; mipLevel++)
668 cv::Mat mipLevelImage;
669 cv::Size cvSize(
static_cast<int>(mipLevelSize.width),
670 static_cast<int>(mipLevelSize.height));
671 cv::resize(image, mipLevelImage, cvSize);
673 std::size_t mipLevelBytes = 4ull * mipLevelSize.width * mipLevelSize.height;
675 destination.mipLevel = mipLevel;
676 pixelDataLayout.bytesPerRow = 4 * mipLevelSize.width;
677 pixelDataLayout.rowsPerImage = mipLevelSize.height;
680 wgpuQueueWriteTexture(app.
queue,
688 mipLevelSize.width /= 2;
689 mipLevelSize.height /= 2;
693 WGPUTextureViewDescriptor textureViewDesc = {};
694 textureViewDesc.aspect = WGPUTextureAspect_All;
695 textureViewDesc.baseArrayLayer = 0;
696 textureViewDesc.arrayLayerCount = 1;
697 textureViewDesc.baseMipLevel = 0;
698 textureViewDesc.mipLevelCount = textureDesc.mipLevelCount;
699 textureViewDesc.dimension = WGPUTextureViewDimension_2D;
700 textureViewDesc.format = textureDesc.format;
711 WGPUSamplerDescriptor samplerDesc = {};
712 samplerDesc.addressModeU = WGPUAddressMode_ClampToEdge;
713 samplerDesc.addressModeV = WGPUAddressMode_ClampToEdge;
714 samplerDesc.addressModeW = WGPUAddressMode_ClampToEdge;
715 samplerDesc.magFilter = WGPUFilterMode_Linear;
716 samplerDesc.minFilter = WGPUFilterMode_Linear;
717 samplerDesc.mipmapFilter = WGPUMipmapFilterMode_Linear;
718 samplerDesc.lodMinClamp = 0.0f;
719 samplerDesc.lodMaxClamp =
static_cast<float>(textureDesc.mipLevelCount);
720 samplerDesc.compare = WGPUCompareFunction_Undefined;
721 samplerDesc.maxAnisotropy = 1.0f;
723 app.
sampler = wgpuDeviceCreateSampler(app.
device, &samplerDesc);
732 const char* shaderSource = R
"(
734 @location(0) position: vec3f,
735 @location(1) normal: vec3f,
736 @location(2) uv: vec2f,
740 projectionMatrix: mat4x4f,
742 modelMatrix: mat4x4f,
745 struct VertexOutput {
746 @builtin(position) position: vec4f,
747 @location(0) worldNormal: vec3f,
748 @location(1) uv: vec2f,
751 const LIGHT_DIR = vec3f(4.0, -8.0, 1.0);
753 @group(0) @binding(0) var<uniform> uniforms: Uniforms;
754 @group(0) @binding(1) var texture: texture_2d<f32>;
755 @group(0) @binding(2) var textureSampler: sampler;
758 fn vs_main(in: VertexInput) -> VertexOutput {
759 var localPos = vec4f(in.position, 1.0);
760 var worldPos = uniforms.modelMatrix * localPos;
762 var out: VertexOutput;
763 out.position = uniforms.projectionMatrix * uniforms.viewMatrix * worldPos;
764 out.worldNormal = in.normal;
770 fn fs_main(in: VertexOutput) -> @location(0) vec4f {
771 var baseColor = textureSample(texture, textureSampler, in.uv);
773 var diffuse = dot(-normalize(in.worldNormal), normalize(LIGHT_DIR));
774 diffuse = diffuse * 0.5 + 0.5;
776 return vec4(baseColor.rgb * diffuse, baseColor.a);
780 WGPUShaderModuleWGSLDescriptor shaderModuleWGSLDesc = {};
781 shaderModuleWGSLDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
782 shaderModuleWGSLDesc.code = shaderSource;
784 WGPUShaderModuleDescriptor shaderModuleDesc = {};
785 shaderModuleDesc.label = "Demo Shader";
786 shaderModuleDesc.nextInChain = (
const WGPUChainedStruct*)&shaderModuleWGSLDesc;
796 WGPUBindGroupLayoutEntry uniformBindLayout = {};
797 uniformBindLayout.binding = 0;
798 uniformBindLayout.visibility = WGPUShaderStage_Vertex;
799 uniformBindLayout.buffer.type = WGPUBufferBindingType_Uniform;
803 WGPUBindGroupLayoutEntry textureBindLayout = {};
804 textureBindLayout.binding = 1;
805 textureBindLayout.visibility = WGPUShaderStage_Fragment;
806 textureBindLayout.texture.sampleType = WGPUTextureSampleType_Float;
807 textureBindLayout.texture.viewDimension = WGPUTextureViewDimension_2D;
810 WGPUBindGroupLayoutEntry samplerBindLayout = {};
811 samplerBindLayout.binding = 2;
812 samplerBindLayout.visibility = WGPUShaderStage_Fragment;
813 samplerBindLayout.sampler.type = WGPUSamplerBindingType_Filtering;
815 std::vector<WGPUBindGroupLayoutEntry> bindGroupLayoutEntries = {uniformBindLayout,
819 WGPUBindGroupLayoutDescriptor bindGroupLayoutDesc = {};
820 bindGroupLayoutDesc.label =
"Demo Bind Group Layout";
821 bindGroupLayoutDesc.entryCount = bindGroupLayoutEntries.size();
822 bindGroupLayoutDesc.entries = bindGroupLayoutEntries.data();
825 &bindGroupLayoutDesc);
832 WGPUBindGroupEntry uniformBinding = {};
833 uniformBinding.binding = 0;
835 uniformBinding.offset = 0;
838 WGPUBindGroupEntry textureBinding = {};
839 textureBinding.binding = 1;
842 WGPUBindGroupEntry samplerBinding = {};
843 samplerBinding.binding = 2;
844 samplerBinding.sampler = app.
sampler;
846 std::vector<WGPUBindGroupEntry> bindGroupEntries = {uniformBinding,
850 WGPUBindGroupDescriptor bindGroupDesc = {};
852 bindGroupDesc.entryCount = bindGroupEntries.size();
853 bindGroupDesc.entries = bindGroupEntries.data();
861 WGPUPipelineLayoutDescriptor pipelineLayoutDesc = {};
862 pipelineLayoutDesc.label =
"Demo Pipeline Layout";
863 pipelineLayoutDesc.bindGroupLayoutCount = 1;
875 WGPUVertexAttribute positionAttribute = {};
876 positionAttribute.format = WGPUVertexFormat_Float32x3;
877 positionAttribute.offset = 0;
878 positionAttribute.shaderLocation = 0;
880 WGPUVertexAttribute normalAttribute = {};
881 normalAttribute.format = WGPUVertexFormat_Float32x3;
882 normalAttribute.offset = 3 *
sizeof(float);
883 normalAttribute.shaderLocation = 1;
885 WGPUVertexAttribute uvAttribute = {};
886 uvAttribute.format = WGPUVertexFormat_Float32x2;
887 uvAttribute.offset = 6 *
sizeof(float);
888 uvAttribute.shaderLocation = 2;
890 std::vector<WGPUVertexAttribute> vertexAttributes = {positionAttribute,
895 WGPUVertexBufferLayout vertexBufferLayout = {};
896 vertexBufferLayout.arrayStride =
sizeof(
VertexData);
897 vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex;
898 vertexBufferLayout.attributeCount = vertexAttributes.size();
899 vertexBufferLayout.attributes = vertexAttributes.data();
902 WGPUVertexState vertexState = {};
904 vertexState.entryPoint =
"vs_main";
905 vertexState.bufferCount = 1;
906 vertexState.buffers = &vertexBufferLayout;
909 WGPUPrimitiveState primitiveState = {};
910 primitiveState.topology = WGPUPrimitiveTopology_TriangleList;
911 primitiveState.stripIndexFormat = WGPUIndexFormat_Undefined;
912 primitiveState.frontFace = WGPUFrontFace_CCW;
913 primitiveState.cullMode = WGPUCullMode_Back;
916 WGPUDepthStencilState depthStencilState = {};
918 depthStencilState.depthWriteEnabled =
true;
919 depthStencilState.depthCompare = WGPUCompareFunction_Less;
920 depthStencilState.stencilReadMask = 0;
921 depthStencilState.stencilWriteMask = 0;
922 depthStencilState.stencilFront.compare = WGPUCompareFunction_Always;
923 depthStencilState.stencilFront.failOp = WGPUStencilOperation_Keep;
924 depthStencilState.stencilFront.depthFailOp = WGPUStencilOperation_Keep;
925 depthStencilState.stencilFront.passOp = WGPUStencilOperation_Keep;
926 depthStencilState.stencilBack.compare = WGPUCompareFunction_Always;
927 depthStencilState.stencilBack.failOp = WGPUStencilOperation_Keep;
928 depthStencilState.stencilBack.depthFailOp = WGPUStencilOperation_Keep;
929 depthStencilState.stencilBack.passOp = WGPUStencilOperation_Keep;
932 WGPUMultisampleState multisampleState = {};
933 multisampleState.count = 1;
934 multisampleState.mask = WGPUColorWriteMask_All;
937 WGPUColorTargetState colorTargetState = {};
938 colorTargetState.format = surfaceCapabilities.formats[0];
939 colorTargetState.writeMask = WGPUColorWriteMask_All;
940 WGPUFragmentState fragmentState = {};
942 fragmentState.entryPoint =
"fs_main";
943 fragmentState.targetCount = 1;
944 fragmentState.targets = &colorTargetState;
947 WGPURenderPipelineDescriptor pipelineDesc = {};
948 pipelineDesc.label =
"Demo Pipeline";
950 pipelineDesc.vertex = vertexState;
951 pipelineDesc.primitive = primitiveState;
952 pipelineDesc.depthStencil = &depthStencilState;
953 pipelineDesc.multisample = multisampleState;
954 pipelineDesc.fragment = &fragmentState;
956 app.
pipeline = wgpuDeviceCreateRenderPipeline(app.
device, &pipelineDesc);
965 wgpuRenderPipelineRelease(app.
pipeline);
970 wgpuSamplerRelease(app.
sampler);
972 wgpuTextureDestroy(app.
texture);
973 wgpuTextureRelease(app.
texture);
983 wgpuSurfaceRelease(app.
surface);
984 wgpuQueueRelease(app.
queue);
985 wgpuDeviceRelease(app.
device);
986 wgpuAdapterRelease(app.
adapter);
996 glfwDestroyWindow(app.
window);
1001 int main(
int argc,
const char* argv[])
1008 double lastCursorX = 0.0f;
1009 double lastCursorY = 0.0f;
1013 while (!glfwWindowShouldClose(app.
window))
1019 glfwGetCursorPos(app.
window, &cursorX, &cursorY);
1021 if (glfwGetMouseButton(app.
window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS)
1023 app.
camRotX -= 0.25f *
static_cast<float>(cursorY - lastCursorY);
1024 app.
camRotY -= 0.25f *
static_cast<float>(cursorX - lastCursorX);
1027 lastCursorX = cursorX;
1028 lastCursorY = cursorY;
void deinitGLFW(WebGPUDemoApp &app)
void initGLFW(WebGPUDemoApp &app)
#define WEBGPU_DEMO_LOG(msg)
void handleDeviceRequest(WGPURequestDeviceStatus status, WGPUDevice device, char const *message, void *userdata)
void onResize(GLFWwindow *window, int width, int height)
void handleAdapterRequest(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const *message, void *userdata)
void onPaint(WebGPUDemoApp &app)
void deinitWebGPU(WebGPUDemoApp &app)
void reconfigureSurface(WebGPUDemoApp &app)
int main(int argc, const char *argv[])
#define WEBGPU_DEMO_CHECK(condition, errorMsg)
void initWebGPU(WebGPUDemoApp &app)
static GLFWwindow * window
The global glfw window handle.
void invert()
Inverts the matrix.
void rotate(T degAng, T axisx, T axisy, T axisz)
void perspective(T fov, T aspect, T n, T f)
Defines a perspective projection matrix with a field of view angle.
void translate(T tx, T ty, T tz=0)
Application struct WebGPUDemoApp with all global variables.
WGPUBindGroupLayout bindGroupLayout
WGPUPipelineLayout pipelineLayout
WGPUTextureView textureView
WGPUSurfaceConfiguration surfaceConfig
WGPUTextureFormat depthTextureFormat
WGPURenderPipeline pipeline
WGPUTextureView depthTextureView
WGPUTextureViewDescriptor depthTextureViewDesc
WGPUTextureDescriptor depthTextureDesc
WGPUShaderModule shaderModule