Skip to content

Commit

Permalink
Add clear_screen sample.
Browse files Browse the repository at this point in the history
  • Loading branch information
juj committed Jan 28, 2021
1 parent cfa85e3 commit 4c2600b
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 9 deletions.
85 changes: 85 additions & 0 deletions clear_screen/clear_screen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include <assert.h>
#include <stdio.h>
#include <emscripten/em_math.h>
#include "lib_webgpu.h"

WGpuAdapter adapter;
WGpuSwapChain swapChain;
WGpuDevice device;
WGpuQueue defaultQueue;

double hue2rgb(double v1, double v2, double vh)
{
if (vh < 0.0) vh += 1.0;
if (vh > 1.0) vh -= 1.0;
if (vh < 1.0 / 6.0) return v1 + (v2 - v1) * 6.0 * vh;
if (vh < 1.0 / 2.0) return v2;
if (vh < 2.0 / 3.0) return v1 + (v2 - v1) * (2.0 / 3.0 - vh) * 6.0;
return v1;
}

void hsl2rgb(double hue, double saturation, double luminance, double *outRed, double *outGreen, double *outBlue)
{
if (saturation < 1e-4)
{
*outRed = *outGreen = *outBlue = luminance;
return;
}

double v2 = (luminance < 0.5) ? (luminance * (1.0 + saturation)) : (luminance + saturation - saturation * luminance);
double v1 = 2.0 * luminance - v2;

*outRed = hue2rgb(v1, v2, hue + 1.0 / 3.0);
*outGreen = hue2rgb(v1, v2, hue);
*outBlue = hue2rgb(v1, v2, hue - 1.0 / 3.0);
}

EM_BOOL raf(double time, void *userData)
{
WGpuCommandEncoder encoder = wgpu_device_create_command_encoder(device, 0);

WGpuRenderPassColorAttachment colorAttachment = {};
colorAttachment.view = wgpu_texture_create_view(wgpu_swap_chain_get_current_texture(swapChain), 0);

double hue = emscripten_math_fmod(time * 0.00005, 1.0);
hsl2rgb(hue, 1.0, 0.5, &colorAttachment.loadColor[0], &colorAttachment.loadColor[1], &colorAttachment.loadColor[2]);
colorAttachment.loadColor[3] = 0.05;

WGpuRenderPassDescriptor passDesc = {};
passDesc.numColorAttachments = 1;
passDesc.colorAttachments = &colorAttachment;

wgpu_render_pass_encoder_end_pass(wgpu_command_encoder_begin_render_pass(encoder, &passDesc));
wgpu_queue_submit_one_and_destroy(defaultQueue, wgpu_command_encoder_finish(encoder));

return EM_TRUE;
}

void ObtainedWebGpuDevice(WGpuDevice result, void *userData)
{
device = result;
defaultQueue = wgpu_device_get_default_queue(device);

WGpuCanvasContext canvasContext = wgpu_canvas_get_canvas_context("canvas");

WGpuSwapChainDescriptor swapChainDesc = WGPU_SWAP_CHAIN_DESCRIPTOR_DEFAULT_INITIALIZER;
swapChainDesc.device = device;
swapChainDesc.format = wgpu_canvas_context_get_swap_chain_preferred_format(canvasContext, adapter);
swapChain = wgpu_canvascontext_configure_swap_chain(canvasContext, &swapChainDesc);

emscripten_request_animation_frame_loop(raf, 0);
}

void ObtainedWebGpuAdapter(WGpuAdapter result, void *userData)
{
adapter = result;

WGpuDeviceDescriptor deviceDesc = WGPU_DEVICE_DESCRIPTOR_DEFAULT_INITIALIZER;
wgpu_adapter_request_device_async(adapter, &deviceDesc, ObtainedWebGpuDevice, 0);
}

int main(int argc, char **argv)
{
WGpuRequestAdapterOptions options = {};
navigator_gpu_request_adapter_async(&options, ObtainedWebGpuAdapter, 0);
}
3 changes: 1 addition & 2 deletions hello_triangle/hello_triangle_minimal.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ void ObtainedWebGpuDevice(WGpuDevice result, void *userData)

WGpuCanvasContext canvasContext = wgpu_canvas_get_canvas_context("canvas");

WGpuSwapChainDescriptor swapChainDesc = {};
WGpuSwapChainDescriptor swapChainDesc = WGPU_SWAP_CHAIN_DESCRIPTOR_DEFAULT_INITIALIZER;
swapChainDesc.device = device;
swapChainDesc.format = wgpu_canvas_context_get_swap_chain_preferred_format(canvasContext, adapter);
swapChainDesc.usage = WGPU_TEXTURE_USAGE_RENDER_ATTACHMENT;

swapChain = wgpu_canvascontext_configure_swap_chain(canvasContext, &swapChainDesc);

Expand Down
3 changes: 1 addition & 2 deletions hello_triangle/hello_triangle_verbose.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,10 @@ void ObtainedWebGpuDevice(WGpuDevice result, void *userData)
assert(canvasContext);
assert(wgpu_is_canvas_context(canvasContext));

WGpuSwapChainDescriptor swapChainDesc = {};
WGpuSwapChainDescriptor swapChainDesc = WGPU_SWAP_CHAIN_DESCRIPTOR_DEFAULT_INITIALIZER;
swapChainDesc.device = device;
swapChainDesc.format = wgpu_canvas_context_get_swap_chain_preferred_format(canvasContext, adapter);
printf("Preferred swap chain format: %s\n", wgpu_enum_to_string(swapChainDesc.format));
swapChainDesc.usage = WGPU_TEXTURE_USAGE_RENDER_ATTACHMENT;

swapChain = wgpu_canvascontext_configure_swap_chain(canvasContext, &swapChainDesc);
assert(wgpu_is_swap_chain(swapChain));
Expand Down
7 changes: 7 additions & 0 deletions lib/lib_webgpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ const char *wgpu_enum_to_string(int enumValue)
return (enumValue >= 0 && enumValue < sizeof(wgpuStrings)/sizeof(wgpuStrings[0])) ? wgpuStrings[enumValue] : "(invalid WebGPU enum)";
}

const WGpuDeviceDescriptor WGPU_DEVICE_DESCRIPTOR_DEFAULT_INITIALIZER = {
};

const WGpuSwapChainDescriptor WGPU_SWAP_CHAIN_DESCRIPTOR_DEFAULT_INITIALIZER = {
.usage = WGPU_TEXTURE_USAGE_RENDER_ATTACHMENT
};

const WGpuColorTargetState WGPU_COLOR_TARGET_STATE_DEFAULT_INITIALIZER = {
.blend = (WGpuBlendState) {
.color = (WGpuBlendComponent) {
Expand Down
4 changes: 4 additions & 0 deletions lib/lib_webgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,13 +393,15 @@ typedef struct WGpuDeviceDescriptor
uint32_t maxVertexAttributes;
uint32_t maxVertexBufferArrayStride;
} WGpuDeviceDescriptor;
extern const WGpuDeviceDescriptor WGPU_DEVICE_DESCRIPTOR_DEFAULT_INITIALIZER;

typedef struct WGpuSwapChainDescriptor
{
WGpuDevice device;
WGPU_TEXTURE_FORMAT format;
WGPU_TEXTURE_USAGE_FLAGS usage;
} WGpuSwapChainDescriptor;
extern const WGpuSwapChainDescriptor WGPU_SWAP_CHAIN_DESCRIPTOR_DEFAULT_INITIALIZER;

typedef struct WGpuShaderModuleDescriptor
{
Expand Down Expand Up @@ -565,10 +567,12 @@ typedef struct WGpuRenderPassDescriptor
WGpuQuerySet occlusionQuerySet;
} WGpuRenderPassDescriptor;

/*
typedef struct WGpuSamplerDescriptor
{
// TODO https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerdescriptor
} WGpuSamplerDescriptor;
*/

const char *wgpu_enum_to_string(int enumValue);

Expand Down
4 changes: 2 additions & 2 deletions lib/lib_webgpu.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ mergeInto(LibraryManager.library, {
{{{ wdebugdir('adapter'); }}}
wgpu[id] = adapter;
adapter.wid = id;
dynCall('vii', adapterCallback, [id, userData]);
{{{ makeDynCall('vii', 'adapterCallback') }}}(id, userData);
});
return id;
}
Expand Down Expand Up @@ -312,7 +312,7 @@ mergeInto(LibraryManager.library, {
// Register an ID for the defaultQueue of this newly created device
wgpuStore(device['defaultQueue']);

dynCall('vii', deviceCallback, [id, userData]);
{{{ makeDynCall('vii', 'deviceCallback') }}}(id, userData);
});
},

Expand Down
12 changes: 9 additions & 3 deletions make.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
@mkdir out >NUL 2>&1
@set ARGS=--js-library lib\lib_webgpu.js lib\lib_webgpu.cpp -Ilib -s MINIMAL_RUNTIME=2 -O3 -s ENVIRONMENT=web -s DYNCALLS=1 -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=["$dynCall"] -s TEXTDECODER=2 -s SUPPORT_ERRNO=0

call emcc hello_triangle\hello_triangle_verbose.c -o out\hello_triangle_verbose.html %ARGS% -g2 -s ASSERTIONS=1
call emcc hello_triangle\hello_triangle_minimal.c -o out\hello_triangle_minimal.html %ARGS% -DNDEBUG --closure 1 --closure-args "--externs lib/webgpu_closure_externs.js"
@set ARGS_DEBUG_DEEP=-O0 -g2 -s ASSERTIONS=1
@set ARGS_DEBUG_OPTIMIZED=-DNDEBUG -O3 -g2 -s WASM=0
@set ARGS_RELEASE=-DNDEBUG --closure 0 --closure-args "--externs lib/webgpu_closure_externs.js" -O3

@set ARGS=--js-library lib\lib_webgpu.js lib\lib_webgpu.cpp -Ilib -s MINIMAL_RUNTIME=2 -s ENVIRONMENT=web -s TEXTDECODER=2 -s SUPPORT_ERRNO=0 --shell-file shell.html -s TOTAL_STACK=16KB -s INITIAL_MEMORY=128KB

call emcc hello_triangle\hello_triangle_verbose.c -o out\hello_triangle_verbose.html %ARGS% %ARGS_DEBUG%
call emcc hello_triangle\hello_triangle_minimal.c -o out\hello_triangle_minimal.html %ARGS% %ARGS_RELEASE%
call emcc clear_screen\clear_screen.c -o out\clear_screen.html %ARGS% %ARGS_DEBUG_OPTIMIZED%
45 changes: 45 additions & 0 deletions shell.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!doctype html><html lang="en-us"><head><meta charset="utf-8"></head>
<body style='margin:0'>
<canvas style='display:block; margin:auto;'></canvas>
<script>
#if !MODULARIZE
var Module = {
#if USE_PTHREADS
worker: '{{{ PTHREAD_WORKER_FILE }}}'
#endif
};
#endif

function resizeCanvas() {
var c = document.querySelector('canvas');
c.style.width = window.innerWidth + 'px';
c.style.height = window.innerHeight + 'px';
c.width = Math.round(window.innerWidth * window.devicePixelRatio);
c.height = Math.round(window.innerHeight * window.devicePixelRatio);
}
resizeCanvas();
onresize = resizeCanvas;

#if WASM == 2
var supportsWasm = window.WebAssembly && location.search.indexOf('_rwasm=0') < 0;
#endif

// Depending on the build flags that one uses, different files need to be downloaded
// to load the compiled page. The right set of files will be expanded to be downloaded
// via the directive below.
{{{ DOWNLOAD_JS_AND_WASM_FILES }}}

#if SINGLE_FILE
// If we are doing a SINGLE_FILE=1 build, inlined JS runtime code follows here:
{{{ JS_CONTENTS_IN_SINGLE_FILE_BUILD }}}

#if MODULARIZE
// Launch the MODULARIZEd build.
{{{ EXPORT_NAME }}}({});
#endif

#endif

</script>
</body>
</html>

0 comments on commit 4c2600b

Please sign in to comment.