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);
void handleDeviceRequest(WGPURequestDeviceStatus status, WGPUDevice device, char const *message, void *userdata)
void handleAdapterRequest(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const *message, void *userdata)
WGPUSurfaceConfiguration surfaceConfig
WGPUTextureFormat depthTextureFormat
WGPUTextureViewDescriptor depthTextureViewDesc
WGPUTextureDescriptor depthTextureDesc