Skip to content

Commit

Permalink
Fix maxAnisotropy default value in sampler creation. Add new function…
Browse files Browse the repository at this point in the history
… wgpu_destroy_all_objects(). Implement wgpu_pipeline_get_bind_group_layout(). Add helper function wgpu_load_image_bitmap_from_url_async(). Add a texture rendering sample.
  • Loading branch information
juj committed Jul 5, 2021
1 parent e4c2f13 commit 710c545
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 20 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,6 @@ target_link_libraries(vertex_buffer webgpu)

add_executable(gpu_oom gpu_oom/gpu_oom.c)
target_link_libraries(gpu_oom webgpu)

add_executable(texture texture/texture.c)
target_link_libraries(texture webgpu)
4 changes: 3 additions & 1 deletion lib/lib_webgpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ const WGpuSamplerDescriptor WGPU_SAMPLER_DESCRIPTOR_DEFAULT_INITIALIZER = {
.minFilter = WGPU_FILTER_MODE_NEAREST,
.mipmapFilter = WGPU_FILTER_MODE_NEAREST,
.lodMinClamp = 0,
.lodMaxClamp = 65536 // TODO change this after spec is fixed
.lodMaxClamp = 65535, // TODO change this after spec is fixed
.maxAnisotropy = 1

};

const WGpuBindGroupLayoutEntry WGPU_BUFFER_BINDING_LAYOUT_ENTRY_DEFAULT_INITIALIZER = {
Expand Down
40 changes: 28 additions & 12 deletions lib/lib_webgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ uint32_t wgpu_get_num_live_objects(void);
// do excess "if (wgpuObject) wgpu_object_destroy(wgpuObject);")
void wgpu_object_destroy(WGpuObjectBase wgpuObject);

// Deinitializes all initialized WebGPU objects.
void wgpu_destroy_all_objects(void);

// Acquires a canvas context from a canvas by calling canvas.getCanvasContext().
WGpuPresentationContext wgpu_canvas_get_gpupresent_context(const char *canvasSelector);

Expand Down Expand Up @@ -733,16 +736,16 @@ dictionary GPUSamplerDescriptor : GPUObjectDescriptorBase {
*/
typedef struct WGpuSamplerDescriptor
{
WGPU_ADDRESS_MODE addressModeU;
WGPU_ADDRESS_MODE addressModeV;
WGPU_ADDRESS_MODE addressModeW;
WGPU_FILTER_MODE magFilter;
WGPU_FILTER_MODE minFilter;
WGPU_FILTER_MODE mipmapFilter;
float lodMinClamp;
float lodMaxClamp;
WGPU_COMPARE_FUNCTION compare;
uint32_t maxAnisotropy; // N.b. this is 32-bit wide in the bindings implementation for simplicity, unlike in the IDL which specifies a unsigned short.
WGPU_ADDRESS_MODE addressModeU; // default = WGPU_ADDRESS_MODE_CLAMP_TO_EDGE
WGPU_ADDRESS_MODE addressModeV; // default = WGPU_ADDRESS_MODE_CLAMP_TO_EDGE
WGPU_ADDRESS_MODE addressModeW; // default = WGPU_ADDRESS_MODE_CLAMP_TO_EDGE
WGPU_FILTER_MODE magFilter; // default = WGPU_FILTER_MODE_NEAREST
WGPU_FILTER_MODE minFilter; // default = WGPU_FILTER_MODE_NEAREST
WGPU_FILTER_MODE mipmapFilter; // default = WGPU_FILTER_MODE_NEAREST
float lodMinClamp; // default = 0
float lodMaxClamp; // default = ?
WGPU_COMPARE_FUNCTION compare; // default = WGPU_COMPARE_FUNCTION_INVALID (not used)
uint32_t maxAnisotropy; // default = 1. N.b. this is 32-bit wide in the bindings implementation for simplicity, unlike in the IDL which specifies a unsigned short.
} WGpuSamplerDescriptor;
extern const WGpuSamplerDescriptor WGPU_SAMPLER_DESCRIPTOR_DEFAULT_INITIALIZER;

Expand Down Expand Up @@ -1097,7 +1100,9 @@ interface mixin GPUPipelineBase {
GPUBindGroupLayout getBindGroupLayout(unsigned long index);
};
*/
// TODO: implement
WGpuBindGroupLayout wgpu_pipeline_get_bind_group_layout(WGpuObjectBase pipelineBase, uint32_t index);
#define wgpu_render_pipeline_get_bind_group_layout wgpu_pipeline_get_bind_group_layout
#define wgpu_compute_pipeline_get_bind_group_layout wgpu_pipeline_get_bind_group_layout

/*
dictionary GPUProgrammableStage {
Expand Down Expand Up @@ -2339,7 +2344,7 @@ typedef struct WGpuRenderPassColorAttachment

typedef struct WGpuImageCopyExternalImage
{
WGpuObjectBase source; // TODO add wgpu_acquire_dom_element_using_css_selector(const char *cssSelector); and wgpu_release_dom_element_using_css_selector(WGpuObjectBase object);
WGpuObjectBase source; // must point to a WGpuImageBitmap (could also point to a HTMLCanvasElement or OffscreenCanvas, but those are currently unimplemented)
WGpuOrigin2D origin;
} WGpuImageCopyExternalImage;
extern const WGpuImageCopyExternalImage WGPU_IMAGE_COPY_EXTERNAL_IMAGE_DEFAULT_INITIALIZER;
Expand Down Expand Up @@ -2431,6 +2436,17 @@ typedef struct WGpuBindGroupLayoutEntry
} WGpuBindGroupLayoutEntry;
extern const WGpuBindGroupLayoutEntry WGPU_BUFFER_BINDING_LAYOUT_ENTRY_DEFAULT_INITIALIZER;

////////////////////////////////////////////////////////////////
// Extensions to the WebGPU specification:

typedef int WGpuImageBitmap;

// Called when the ImageBitmap finishes loading. If loading fails, this callback will be called with width==height==0.
typedef void (*WGpuLoadImageBitmapCallback)(WGpuImageBitmap bitmap, int width, int height, void *userData);

WGpuImageBitmap wgpu_load_image_bitmap_from_url_async(const char *url, EM_BOOL flipY, WGpuLoadImageBitmapCallback callback, void *userData);


#ifdef __cplusplus
} // ~extern "C"
#endif
53 changes: 46 additions & 7 deletions lib/lib_webgpu.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ mergeInto(LibraryManager.library, {
{{{ wassert(`!(object in wgpu), 'wgpu dictionary should not be storing nulls/undefineds/zeroes!'`); }}}
},

wgpu_destroy_all_objects__deps: ['$wgpu'],
wgpu_destroy_all_objects: function() {
wgpu.forEach((o) => { if (o['destroy']) o['destroy'](); });
wgpu = {};
},

wgpu_is_valid_object: function(o) { return !!wgpu[o]; }, // Tests if this ID references anything (not just a GPUObjectBase)
wgpu_is_adapter: function(o) { return wgpu[o] instanceof GPUAdapter; },
wgpu_is_device: function(o) { return wgpu[o] instanceof GPUDevice; },
Expand All @@ -92,7 +98,7 @@ mergeInto(LibraryManager.library, {
wgpu_is_render_pipeline: function(o) { return wgpu[o] instanceof GPURenderPipeline; },
wgpu_is_command_buffer: function(o) { return wgpu[o] instanceof GPUCommandBuffer; },
wgpu_is_command_encoder: function(o) { return wgpu[o] instanceof GPUCommandEncoder; },
wgpu_is_programmable_pass_encoder: function(o) { return wgpu[o] instanceof GPUProgrammablePassEncoder; },
wgpu_is_programmable_pass_encoder: function(o) { return wgpu[o] instanceof GPUComputePassEncoder || wgpu[o] instanceof GPURenderPassEncoder || wgpu[o] instanceof GPURenderBundleEncoder; },
// TODO: Should 'GPURenderEncoderBase' exist as a type?
wgpu_is_render_encoder_base: function(o) { return wgpu[o] instanceof GPURenderPassEncoder || wgpu[o] instanceof GPURenderBundleEncoder; },
wgpu_is_render_pass_encoder: function(o) { return wgpu[o] instanceof GPURenderPassEncoder; },
Expand Down Expand Up @@ -975,6 +981,17 @@ mergeInto(LibraryManager.library, {
return wgpuStoreAndSetParent(view, t);
},

wgpu_pipeline_get_bind_group_layout: function(pipelineBase, index) {
{{{ wdebuglog('`wgpu_pipeline_get_bind_group_layout(pipelineBase=${pipelineBase}, index=${index})`'); }}}
{{{ wassert('wgpu[pipelineBase] instanceof GPURenderPipeline || wgpu[pipelineBase] instanceof GPUComputePipeline'); }}}

var id = wgpuAllocId();
wgpu[id] = wgpu[pipelineBase]['getBindGroupLayout'](index);
{{{ wdebuglog('`returned:`'); }}}
{{{ wdebugdir('wgpu[id]'); }}}
return id;
},

wgpu_command_encoder_begin_render_pass: function(commandEncoder, descriptor) {
{{{ wdebuglog('`wgpu_command_encoder_begin_render_pass(commandEncoder=${commandEncoder}, descriptor=${descriptor})`'); }}}
{{{ wassert('wgpu[commandEncoder] instanceof GPUCommandEncoder'); }}}
Expand Down Expand Up @@ -1102,27 +1119,27 @@ mergeInto(LibraryManager.library, {

wgpu_encoder_push_debug_group: function(encoder, groupLabel) { // TODO: this function is untested. Write a test case
{{{ wdebuglog('`wgpu_command_encoder_push_debug_group(encoder=${encoder}, groupLabel=${groupLabel})`'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUProgrammablePassEncoder'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUComputePassEncoder || wgpu[encoder] instanceof GPURenderPassEncoder || wgpu[encoder] instanceof GPURenderBundleEncoder'); }}}
{{{ wassert('wgpu[groupLabel]'); }}}
wgpu[encoder]['pushDebugGroup'](UTF8ToString(groupLabel));
},

wgpu_encoder_pop_debug_group: function(encoder) { // TODO: this function is untested. Write a test case
{{{ wdebuglog('`wgpu_command_encoder_pop_debug_group(encoder=${encoder})`'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUProgrammablePassEncoder'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUComputePassEncoder || wgpu[encoder] instanceof GPURenderPassEncoder || wgpu[encoder] instanceof GPURenderBundleEncoder'); }}}
wgpu[encoder]['popDebugGroup']();
},

wgpu_encoder_insert_debug_marker: function(encoder, markerLabel) { // TODO: this function is untested. Write a test case
{{{ wdebuglog('`wgpu_command_encoder_insert_debug_marker(encoder=${encoder}, markerLabel=${markerLabel})`'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUProgrammablePassEncoder'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUComputePassEncoder || wgpu[encoder] instanceof GPURenderPassEncoder || wgpu[encoder] instanceof GPURenderBundleEncoder'); }}}
{{{ wassert('wgpu[markerLabel]'); }}}
wgpu[encoder]['insertDebugMarker'](UTF8ToString(markerLabel));
},

wgpu_encoder_write_timestamp: function(encoder, querySet, queryIndex) { // TODO: this function is untested. Write a test case
{{{ wdebuglog('`wgpu_encoder_write_timestamp(commandEncoder=${commandEncoder}, querySet=${querySet}, queryIndex=${queryIndex})`'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUProgrammablePassEncoder || wgpu[encoder] instanceof GPURenderPassEncoder'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUComputePassEncoder || wgpu[encoder] instanceof GPURenderPassEncoder || wgpu[encoder] instanceof GPURenderBundleEncoder'); }}}
{{{ wassert('wgpu[querySet]'); }}}
wgpu[encoder]['writeTimestamp'](wgpu[querySet], queryIndex);
},
Expand Down Expand Up @@ -1231,7 +1248,7 @@ mergeInto(LibraryManager.library, {

wgpu_programmable_pass_encoder_set_bind_group: function(encoder, index, bindGroup, dynamicOffsets, numDynamicOffsets) { // TODO: this function is untested. Write a test case
{{{ wdebuglog('`wgpu_programmable_pass_encoder_set_bind_group(encoder=${encoder}, index=${index}, bindGroup=${bindGroup}, dynamicOffsets=${dynamicOffsets}, numDynamicOffsets=${numDynamicOffsets})`'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUProgrammablePassEncoder'); }}}
{{{ wassert('wgpu[encoder] instanceof GPUCommandEncoder || wgpu[encoder] instanceof GPUComputePassEncoder || wgpu[encoder] instanceof GPURenderPassEncoder || wgpu[encoder] instanceof GPURenderBundleEncoder'); }}}
{{{ wassert('wgpu[bindGroup] instanceof GPUBindGroup'); }}}
{{{ wassert('dynamicOffsets != 0 || numDynamicOffsets == 0'); }}}
{{{ wassert('dynamicOffsets % 4 == 0'); }}}
Expand Down Expand Up @@ -1402,12 +1419,34 @@ mergeInto(LibraryManager.library, {
source >>= 2;
var dest = wgpuReadGpuImageCopyTexture(destination);
destination >>= 2;
dest['colorSpace'] = wgpuStrings[HEAP32[destination+6]];
dest['colorSpace'] = _wgpuStrings[HEAP32[destination+6]];
dest['premultipliedAlpha'] = !!HEAP32[destination+7];

wgpu[queue]['copyExternalImageToTexture']({
'source': wgpu[HEAPU32[source]],
'origin': [HEAP32[source+1], HEAP32[source+2]]
}, dest, [copyWidth, copyHeight, copyDepthOrArrayLayers]);
},

wgpu_load_image_bitmap_from_url_async: function(url, flipY, callback, userData) {
{{{ wdebuglog('`wgpu_load_image_bitmap_from_url_async(url=\"${UTF8ToString(url)}\" (${url}), callback=${callback}, userData=${userData})`'); }}}
var img = new Image();
img.src = UTF8ToString(url);
var id = wgpuAllocId();

function dispatchCallback(imageBitmapOrError) {
{{{ wdebuglog('`createImageBitmap(img) loaded:`'); }}}
{{{ wdebugdir('imageBitmapOrError'); }}}
{{{ wdebuglog('`from:`'); }}}
{{{ wdebugdir('img'); }}}
if (imageBitmapOrError.width) wgpu[id] = imageBitmapOrError;
{{{ makeDynCall('viiii', 'callback') }}}(id, imageBitmapOrError.width, imageBitmapOrError.height, userData);
}

img.decode().then(() => {
return createImageBitmap(img, flipY ? { 'imageOrientation': 'flipY' } : {});
}).then(dispatchCallback).catch(dispatchCallback);

return id;
}
});
Binary file added texture/fish.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions texture/license.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fish.png downloaded from http://clipart-library.com/clipart/fish-clip-art-38.htm
Loading

0 comments on commit 710c545

Please sign in to comment.