1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911 |
- (function() {
- /**
- * Assumptions:
- * - Ability to allocate memory, set the context to allocate with using the global `wgpu.g_context`
- * - Exports a function table (for callbacks), added with `-extra-linker-flags:"--export-table"`
- */
- class WebGPUInterface {
- /**
- * @param {WasmMemoryInterface} mem
- */
- constructor(mem) {
- this.mem = mem;
- this.enums = {
- FeatureName: [undefined, "depth-clip-control", "depth32float-stencil8", "timestamp-query", "texture-compression-bc", "texture-compression-etc2", "texture-compression-astc", "indirect-first-instance", "shader-f16", "rg11b10ufloat-renderable", "bgra8unorm-storage", "float32-filterable", ],
- StoreOp: [undefined, "store", "discard", ],
- LoadOp: [undefined, "clear", "load", ],
- BufferBindingType: [undefined, "uniform", "storage", "read-only-storage", ],
- SamplerBindingType: [undefined, "filtering", "non-filtering", "comparison", ],
- TextureSampleType: [undefined, "float", "unfilterable-float", "depth", "sint", "uint", ],
- TextureViewDimension: [undefined, "1d", "2d", "2d-array", "cube", "cube-array", "3d", ],
- StorageTextureAccess: [undefined, "write-only", "read-only", "read-write", ],
- TextureFormat: [undefined, "r8unorm", "r8snorm", "r8uint", "r8sint", "r16uint", "r16sint", "r16float", "rg8unorm", "rg8snorm", "rg8uint", "rg8sint", "r32float", "r32uint", "r32sint", "rg16uint", "rg16sint", "rg16float", "rgba8unorm", "rgba8unorm-srgb", "rgba8snorm", "rgba8uint", "rgba8sint", "bgra8unorm", "bgra8unorm-srgb", "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rgb9e5ufloat", "rg32float", "rg32uint", "rg32sint", "rgba16uint", "rgba16sint", "rgba16float", "rgba32float", "rgba32uint", "rgba32sint", "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", "bc2-rgba-unorm-srgb", "bc3-rgba-unorm", "bc3-rgba-unorm-srgb", "bc4-r-unorm", "bc4-r-snorm", "bc5-rg-unorm", "bc5-rg-snorm", "bc6h-rgb-ufloat", "bc6h-rgb-float", "bc7-rgba-unorm", "bc7-rgba-unorm-srgb", "etc2-rgb8unorm", "etc2-rgb8unorm-srgb", "etc2-rgb8a1unorm", "etc2-rgb8a1unorm-srgb", "etc2-rgba8unorm", "etc2-rgba8unorm-srgb", "eac-r11unorm", "eac-r11snorm", "eac-rg11unorm", "eac-rg11snorm", "astc-4x4-unorm", "astc-4x4-unorm-srgb", "astc-5x4-unorm", "astc-5x4-unorm-srgb", "astc-5x5-unorm", "astc-5x5-unorm-srgb", "astc-6x5-unorm", "astc-6x5-unorm-srgb", "astc-6x6-unorm", "astc-6x6-unorm-srgb", "astc-8x5-unorm", "astc-8x5-unorm-srgb", "astc-8x6-unorm", "astc-8x6-unorm-srgb", "astc-8x8-unorm", "astc-8x8-unorm-srgb", "astc-10x5-unorm", "astc-10x5-unorm-srgb", "astc-10x6-unorm", "astc-10x6-unorm-srgb", "astc-10x8-unorm", "astc-10x8-unorm-srgb", "astc-10x10-unorm", "astc-10x10-unorm-srgb", "astc-12x10-unorm", "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb", ],
- QueryType: ["occlusion", "timestamp", ],
- VertexStepMode: ["vertex", "instance", "vertex-buffer-not-used", ],
- VertexFormat: [undefined, "uint8x2", "uint8x4", "sint8x2", "sint8x4", "unorm8x2", "unorm8x4", "snorm8x2", "snorm8x4", "uint16x2", "uint16x4", "sint16x2", "sint16x4", "unorm16x2", "unorm16x4", "snorm16x2", "snorm16x4", "float16x2", "float16x4", "float32", "float32x2", "float32x3", "float32x4", "uint32", "uint32x2", "uint32x3", "uint32x4", "sint32", "sint32x2", "sint32x3", "sint32x4", ],
- PrimitiveTopology: ["point-list", "line-list", "line-strip", "triangle-list", "triangle-strip", ],
- IndexFormat: [undefined, "uint16", "uint32", ],
- FrontFace: ["ccw", "cw", ],
- CullMode: ["none", "front", "back", ],
- AddressMode: ["repeat", "mirror-repeat", "clamp-to-edge", ],
- FilterMode: ["nearest", "linear", ],
- MipmapFilterMode: ["nearest", "linear", ],
- CompareFunction: [undefined, "never", "less", "less-equal", "greater", "greater-equal", "equal", "not-equal", "always", ],
- TextureDimension: ["1d", "2d", "3d", ],
- ErrorType: ["no-error", "validation", "out-of-memory", "internal", "unknown", "device-lost", ],
- WGSLFeatureName: [undefined, "readonly_and_readwrite_storage_textures", "packed_4x8_integer_dot_product", "unrestricted_pointer_parameters", "pointer_composite_access", ],
- PowerPreference: [undefined, "low-power", "high-performance", ],
- CompositeAlphaMode: ["auto", "opaque", "premultiplied", "unpremultiplied", "inherit", ],
- StencilOperation: ["keep", "zero", "replace", "invert", "increment-clamp", "decrement-clamp", "increment-wrap", "decrement-wrap", ],
- BlendOperation: ["add", "subtract", "reverse-subtract", "min", "max", ],
- BlendFactor: ["zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", ],
- PresentMode: ["fifo", "fifo-relaxed", "immediate", "mailbox", ],
- TextureAspect: ["all", "stencil-only", "depth-only"],
- DeviceLostReason: [undefined, "unknown", "destroyed"],
- };
- /** @type {WebGPUObjectManager<{}>} */
- this.instances = new WebGPUObjectManager("Instance", this.mem);
- /** @type {WebGPUObjectManager<GPUAdapter>} */
- this.adapters = new WebGPUObjectManager("Adapter", this.mem);
- /** @type {WebGPUObjectManager<GPUBindGroup>} */
- this.bindGroups = new WebGPUObjectManager("BindGroup", this.mem);
- /** @type {WebGPUObjectManager<GPUBindGroupLayout>} */
- this.bindGroupLayouts = new WebGPUObjectManager("BindGroupLayout", this.mem);
- /** @type {WebGPUObjectManager<{ buffer: GPUBuffer, mapping: ?{ range: ArrayBuffer, ptr: number, size: number } }>} */
- this.buffers = new WebGPUObjectManager("Buffer", this.mem);
- /** @type {WebGPUObjectManager<GPUDevice>} */
- this.devices = new WebGPUObjectManager("Device", this.mem);
- /** @type {WebGPUObjectManager<GPUCommandBuffer>} */
- this.commandBuffers = new WebGPUObjectManager("CommandBuffer", this.mem);
- /** @type {WebGPUObjectManager<GPUCommandEncoder>} */
- this.commandEncoders = new WebGPUObjectManager("CommandEncoder", this.mem);
- /** @type {WebGPUObjectManager<GPUComputePassEncoder>} */
- this.computePassEncoders = new WebGPUObjectManager("ComputePassEncoder", this.mem);
- /** @type {WebGPUObjectManager<GPURenderPassEncoder>} */
- this.renderPassEncoders = new WebGPUObjectManager("RenderPassEncoder", this.mem);
- /** @type {WebGPUObjectManager<GPUQuerySet>} */
- this.querySets = new WebGPUObjectManager("QuerySet", this.mem);
- /** @type {WebGPUObjectManager<GPUComputePipeline>} */
- this.computePipelines = new WebGPUObjectManager("ComputePipeline", this.mem);
- /** @type {WebGPUObjectManager<GPUPipelineLayout>} */
- this.pipelineLayouts = new WebGPUObjectManager("PipelineLayout", this.mem);
- /** @type {WebGPUObjectManager<GPUQueue>} */
- this.queues = new WebGPUObjectManager("Queue", this.mem);
- /** @type {WebGPUObjectManager<GPURenderBundle>} */
- this.renderBundles = new WebGPUObjectManager("RenderBundle", this.mem);
- /** @type {WebGPUObjectManager<GPURenderBundleEncoder>} */
- this.renderBundleEncoders = new WebGPUObjectManager("RenderBundleEncoder", this.mem);
- /** @type {WebGPUObjectManager<GPURenderPipeline>} */
- this.renderPipelines = new WebGPUObjectManager("RenderPipeline", this.mem);
- /** @type {WebGPUObjectManager<GPUSampler>} */
- this.samplers = new WebGPUObjectManager("Sampler", this.mem);
- /** @type {WebGPUObjectManager<GPUShaderModule>} */
- this.shaderModules = new WebGPUObjectManager("ShaderModule", this.mem);
- /** @type {WebGPUObjectManager<HTMLCanvasElement>} */
- this.surfaces = new WebGPUObjectManager("Surface", this.mem);
- /** @type {WebGPUObjectManager<GPUTexture>} */
- this.textures = new WebGPUObjectManager("Texture", this.mem);
- /** @type {WebGPUObjectManager<GPUTextureView>} */
- this.textureViews = new WebGPUObjectManager("TextureView", this.mem);
- }
- /**
- * @param {number|BigInt} src
- * @returns {number|BigInt}
- */
- uint(src) {
- if (this.mem.intSize == 8) {
- return BigInt(src);
- } else if (this.mem.intSize == 4) {
- return src;
- } else {
- throw new Error("unreachable");
- }
- }
- /**
- * @param {number|BigInt} src
- * @returns {number}
- */
- unwrapBigInt(src) {
- if (typeof src == "number") {
- return src;
- }
- const MAX_SAFE_INTEGER = 9007199254740991n;
- if (typeof src != "bigint") {
- throw new TypeError(`unwrapBigInt got invalid param of type ${typeof src}`);
- }
- if (src > MAX_SAFE_INTEGER) {
- throw new Error(`unwrapBigInt precision would be lost converting ${src}`);
- }
- return Number(src);
- }
- /**
- * @param {boolean} condition
- * @param {string} message
- */
- assert(condition, message = "assertion failure") {
- if (!condition) {
- throw new Error(message);
- }
- }
- /**
- * @template T
- *
- * @param {number} count
- * @param {number} start
- * @param {function(number): T} decoder
- * @param {number} stride
- * @returns {Array<T>}
- */
- array(count, start, decoder, stride) {
- if (count == 0) {
- return [];
- }
- this.assert(start != 0);
- const out = [];
- for (let i = 0; i < count; i += 1) {
- out.push(decoder.call(this, start));
- start += stride;
- }
- return out;
- }
- /**
- * @param {string} name
- * @param {number} ptr
- * @returns {`GPU${name}`}
- */
- enumeration(name, ptr) {
- const int = this.mem.loadI32(ptr);
- this.assert(this.enums[name], `Unknown enumeration "${name}"`);
- return this.enums[name][int];
- }
- /**
- * @param {GPUSupportedFeatures} features
- * @param {number} ptr
- * @returns {BigInt|number}
- */
- genericEnumerateFeatures(features, ptr) {
- const availableFeatures = [];
- this.enums.FeatureName.forEach((feature, value) => {
- if (!feature) {
- return;
- }
- if (features.has(feature)) {
- availableFeatures.push(value);
- }
- });
- if (ptr != 0) {
- for (let i = 0; i < availableFeatures.length; i += 1) {
- this.mem.storeI32(ptr + (i * 4), availableFeatures[i]);
- }
- }
- return this.uint(availableFeatures.length);
- }
- /**
- * @param {GPUSupportedLimits} limits
- * @param {number} ptr
- */
- genericGetLimits(limits, supportedLimitsPtr) {
- this.assert(supportedLimitsPtr != 0);
- const limitsPtr = supportedLimitsPtr + 8;
- this.mem.storeU32(limitsPtr + 0, limits.maxTextureDimension1D);
- this.mem.storeU32(limitsPtr + 4, limits.maxTextureDimension2D);
- this.mem.storeU32(limitsPtr + 8, limits.maxTextureDimension3D);
- this.mem.storeU32(limitsPtr + 12, limits.maxTextureArrayLayers);
- this.mem.storeU32(limitsPtr + 16, limits.maxBindGroups);
- this.mem.storeU32(limitsPtr + 20, limits.maxBindGroupsPlusVertexBuffers);
- this.mem.storeU32(limitsPtr + 24, limits.maxBindingsPerBindGroup);
- this.mem.storeU32(limitsPtr + 28, limits.maxDynamicUniformBuffersPerPipelineLayout);
- this.mem.storeU32(limitsPtr + 32, limits.maxDynamicStorageBuffersPerPipelineLayout);
- this.mem.storeU32(limitsPtr + 36, limits.maxSampledTexturesPerShaderStage);
- this.mem.storeU32(limitsPtr + 40, limits.maxSamplersPerShaderStage);
- this.mem.storeU32(limitsPtr + 44, limits.maxStorageBuffersPerShaderStage);
- this.mem.storeU32(limitsPtr + 48, limits.maxStorageTexturesPerShaderStage);
- this.mem.storeU32(limitsPtr + 52, limits.maxUniformBuffersPerShaderStage);
- this.mem.storeU64(limitsPtr + 56, limits.maxUniformBufferBindingSize);
- this.mem.storeU64(limitsPtr + 64, limits.maxStorageBufferBindingSize);
- this.mem.storeU32(limitsPtr + 72, limits.minUniformBufferOffsetAlignment);
- this.mem.storeU32(limitsPtr + 76, limits.minStorageBufferOffsetAlignment);
- this.mem.storeU32(limitsPtr + 80, limits.maxVertexBuffers);
- this.mem.storeU64(limitsPtr + 88, limits.maxBufferSize);
- this.mem.storeU32(limitsPtr + 96, limits.maxVertexAttributes);
- this.mem.storeU32(limitsPtr + 100, limits.maxVertexBufferArrayStride);
- this.mem.storeU32(limitsPtr + 104, limits.maxInterStageShaderComponents);
- this.mem.storeU32(limitsPtr + 108, limits.maxInterStageShaderVariables);
- this.mem.storeU32(limitsPtr + 112, limits.maxColorAttachments);
- this.mem.storeU32(limitsPtr + 116, limits.maxColorAttachmentBytesPerSample);
- this.mem.storeU32(limitsPtr + 120, limits.maxComputeWorkgroupStorageSize);
- this.mem.storeU32(limitsPtr + 124, limits.maxComputeInvocationsPerWorkgroup);
- this.mem.storeU32(limitsPtr + 128, limits.maxComputeWorkgroupSizeX);
- this.mem.storeU32(limitsPtr + 132, limits.maxComputeWorkgroupSizeY);
- this.mem.storeU32(limitsPtr + 136, limits.maxComputeWorkgroupSizeZ);
- this.mem.storeU32(limitsPtr + 140, limits.maxComputeWorkgroupsPerDimension);
- return true;
- }
- /**
- * @param {number} ptr
- * @returns {GPUFeatureName}
- */
- FeatureNamePtr(ptr) {
- return this.FeatureName(this.mem.loadI32(ptr));
- }
- /**
- * @param {number} featureInt
- * @returns {GPUFeatureName}
- */
- FeatureName(featureInt) {
- return this.enums.FeatureName[featureInt];
- }
- /**
- * @param {number} ptr
- * @returns {GPUSupportedLimits}
- */
- RequiredLimitsPtr(ptr) {
- const start = this.mem.loadPtr(ptr);
- if (start == 0) {
- return undefined;
- }
- return this.Limits(start + 8);
- }
- /**
- * @param {number} start
- * @return {GPUSupportedLimits}
- */
- Limits(start) {
- const limitU32 = (ptr) => {
- const value = this.mem.loadU32(ptr);
- if (value == 0xFFFFFFFF) { // LIMIT_32_UNDEFINED.
- return undefined;
- }
- return value;
- };
- const limitU64 = (ptr) => {
- const part1 = this.mem.loadU32(ptr);
- const part2 = this.mem.loadU32(ptr + 4);
- if (part1 != 0xFFFFFFFF || part2 != 0xFFFFFFFF) { // LIMIT_64_UNDEFINED.
- return this.mem.loadU64(ptr);
- }
- return undefined;
- };
- return {
- maxTextureDimension1D: limitU32(start + 0),
- maxTextureDimension2D: limitU32(start + 4),
- maxTextureDimension3D: limitU32(start + 8),
- maxTextureArrayLayers: limitU32(start + 12),
- maxBindGroups: limitU32(start + 16),
- maxBindGroupsPlusVertexBuffers: limitU32(start + 20),
- maxBindingsPerBindGroup: limitU32(start + 24),
- maxDynamicUniformBuffersPerPipelineLayout: limitU32(start + 28),
- maxDynamicStorageBuffersPerPipelineLayout: limitU32(start + 32),
- maxSampledTexturesPerShaderStage: limitU32(start + 36),
- maxSamplersPerShaderStage: limitU32(start + 40),
- maxStorageBuffersPerShaderStage: limitU32(start + 44),
- maxStorageTexturesPerShaderStage: limitU32(start + 48),
- maxUniformBuffersPerShaderStage: limitU32(start + 52),
- maxUniformBufferBindingSize: limitU64(start + 56),
- maxStorageBufferBindingSize: limitU64(start + 64),
- minUniformBufferOffsetAlignment: limitU32(start + 72),
- minStorageBufferOffsetAlignment: limitU32(start + 76),
- maxVertexBuffers: limitU32(start + 80),
- maxBufferSize: limitU64(start + 88),
- maxVertexAttributes: limitU32(start + 96),
- maxVertexBufferArrayStride: limitU32(start + 100),
- maxInterStageShaderComponents: limitU32(start + 104),
- maxInterStageShaderVariables: limitU32(start + 108),
- maxColorAttachments: limitU32(start + 112),
- maxColorAttachmentBytesPerSample: limitU32(start + 116),
- maxComputeWorkgroupStorageSize: limitU32(start + 120),
- maxComputeInvocationsPerWorkgroup: limitU32(start + 124),
- maxComputeWorkgroupSizeX: limitU32(start + 128),
- maxComputeWorkgroupSizeY: limitU32(start + 132),
- maxComputeWorkgroupSizeZ: limitU32(start + 136),
- maxComputeWorkgroupsPerDimension: limitU32(start + 140),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUQueueDescriptor}
- */
- QueueDescriptor(start) {
- return {
- label: this.mem.loadCstring(start + 4),
- };
- }
- /**
- * @param {number} ptr
- * @returns {GPUComputePassTimestampWrites}
- */
- ComputePassTimestampWritesPtr(ptr) {
- const start = this.mem.loadPtr(ptr);
- if (start == 0) {
- return undefined;
- }
- return {
- querySet: this.querySets.get(this.mem.loadPtr(start + 0)),
- beginningOfPassWriteIndex: this.mem.loadU32(start + 4),
- endOfPassWriteIndex: this.mem.loadU32(start + 8),
- };
- }
- /**
- * @param {number} start
- * @returns {GPURenderPassColorAttachment}
- */
- RenderPassColorAttachment(start) {
- const viewIdx = this.mem.loadPtr(start + 4);
- const resolveTargetIdx = this.mem.loadPtr(start + 12);
- let depthSlice = this.mem.loadU32(start + 8);
- if (depthSlice == 0xFFFFFFFF) { // DEPTH_SLICE_UNDEFINED.
- depthSlice = undefined;
- }
- return {
- view: viewIdx > 0 ? this.textureViews.get(viewIdx) : undefined,
- resolveTarget: resolveTargetIdx > 0 ? this.textureViews.get(resolveTargetIdx) : undefined,
- depthSlice: depthSlice,
- loadOp: this.enumeration("LoadOp", start + 16),
- storeOp: this.enumeration("StoreOp", start + 20),
- clearValue: this.Color(start + 24),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUColor}
- */
- Color(start) {
- return {
- r: this.mem.loadF64(start + 0),
- g: this.mem.loadF64(start + 8),
- b: this.mem.loadF64(start + 16),
- a: this.mem.loadF64(start + 24),
- };
- }
- /**
- * @param {number} ptr
- * @returns {GPURenderPassDepthStencilAttachment}
- */
- RenderPassDepthStencilAttachmentPtr(ptr) {
- const start = this.mem.loadPtr(ptr);
- if (start == 0) {
- return undefined;
- }
- return {
- view: this.textureViews.get(this.mem.loadPtr(start + 0)),
- depthLoadOp: this.enumeration("LoadOp", start + 4),
- depthStoreOp: this.enumeration("StoreOp", start + 8),
- depthClearValue: this.mem.loadF32(start + 12),
- depthReadOnly: this.mem.loadB32(start + 16),
- stencilLoadOp: this.enumeration("LoadOp", start + 20),
- stencilStoreOp: this.enumeration("StoreOp", start + 24),
- stencilClearValue: this.mem.loadF32(start + 28),
- stencilReadOnly: this.mem.loadB32(start + 32),
- };
- }
- /**
- * @param {number} ptr
- * @returns {undefined|GPUQuerySet}
- */
- QuerySet(ptr) {
- ptr = this.mem.loadPtr(ptr);
- if (ptr == 0) {
- return undefined;
- }
- return this.querySets.get(ptr);
- }
- /**
- * @param {number} ptr
- * @returns {GPURenderPassTimestampWrites}
- */
- RenderPassTimestampWritesPtr(ptr) {
- return this.ComputePassTimestampWritesPtr(ptr);
- }
-
- /**
- * @param {number} start
- * @returns {GPUImageDataLayout}
- */
- TextureDataLayout(start) {
- return {
- offset: this.mem.loadU64(start + 8),
- bytesPerRow: this.mem.loadU32(start + 16),
- rowsPerImage: this.mem.loadU32(start + 20),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUImageCopyBuffer}
- */
- ImageCopyBuffer(start) {
- return {
- ...this.TextureDataLayout(start + 8),
- buffer: this.buffers.get(this.mem.loadPtr(start + 32)).buffer,
- };
- }
- /**
- * @param {number} start
- * @returns {GPUImageCopyTexture}
- */
- ImageCopyTexture(start) {
- return {
- texture: this.textures.get(this.mem.loadPtr(start + 4)),
- mipLevel: this.mem.loadU32(start + 8),
- origin: this.Origin3D(start + 12),
- aspect: this.enumeration("TextureAspect", start + 24),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUOrigin3D}
- */
- Origin3D(start) {
- return {
- x: this.mem.loadU32(start + 0),
- y: this.mem.loadU32(start + 4),
- z: this.mem.loadU32(start + 8),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUExtent3D}
- */
- Extent3D(start) {
- return {
- width: this.mem.loadU32(start + 0),
- height: this.mem.loadU32(start + 4),
- depthOrArrayLayers: this.mem.loadU32(start + 8),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUBindGroupEntry}
- */
- BindGroupEntry(start) {
- const buffer = this.mem.loadPtr(start + 8);
- const sampler = this.mem.loadPtr(start + 32);
- const textureView = this.mem.loadPtr(start + 36);
- /** @type {GPUBindingResource} */
- let resource;
- if (buffer > 0) {
- resource = {
- buffer: this.buffers.get(buffer).buffer,
- offset: this.mem.loadU64(start + 16),
- size: this.mem.loadU64(start + 24),
- }
- } else if (sampler > 0) {
- resource = this.samplers.get(sampler);
- } else if (textureView > 0) {
- resource = this.textureViews.get(textureView);
- }
- return {
- binding: this.mem.loadU32(start + 4),
- resource: resource,
- };
- }
- /**
- * @param {number} start
- * @returns {GPUBindGroupLayoutEntry}
- */
- BindGroupLayoutEntry(start) {
- const entry = {
- binding: this.mem.loadU32(start + 4),
- visibility: this.mem.loadU32(start + 8),
- buffer: this.BufferBindingLayout(start + 16),
- sampler: this.SamplerBindingLayout(start + 40),
- texture: this.TextureBindingLayout(start + 48),
- storageTexture: this.StorageTextureBindingLayout(start + 64),
- };
- if (!entry.buffer.type) {
- entry.buffer = undefined;
- }
- if (!entry.sampler.type) {
- entry.sampler = undefined;
- }
- if (!entry.texture.sampleType) {
- entry.texture = undefined;
- }
- if (!entry.storageTexture.access) {
- entry.storageTexture = undefined;
- }
- return entry;
- }
- /**
- * @param {number} start
- * @returns {GPUBufferBindingLayout}
- */
- BufferBindingLayout(start) {
- return {
- type: this.enumeration("BufferBindingType", start + 4),
- hasDynamicOffset: this.mem.loadB32(start + 8),
- minBindingSize: this.mem.loadU64(start + 16),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUSamplerBindingLayout}
- */
- SamplerBindingLayout(start) {
- return {
- type: this.enumeration("SamplerBindingType", start + 4),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUTextureBindingLayout}
- */
- TextureBindingLayout(start) {
- return {
- sampleType: this.enumeration("TextureSampleType", start + 4),
- viewDimension: this.enumeration("TextureViewDimension", start + 8),
- multisampled: this.mem.loadB32(start + 12),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUStorageTextureBindingLayout}
- */
- StorageTextureBindingLayout(start) {
- return {
- access: this.enumeration("StorageTextureAccess", start + 4),
- format: this.enumeration("TextureFormat", start + 8),
- viewDimension: this.enumeration("TextureViewDimension", start + 12),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUProgrammableStage}
- */
- ProgrammableStageDescriptor(start) {
- const constantsArray = this.array(
- this.mem.loadUint(start + 8 + this.mem.intSize),
- this.mem.loadPtr(start + 8 + this.mem.intSize*2),
- this.ConstantEntry,
- 16,
- );
- return {
- module: this.shaderModules.get(this.mem.loadPtr(start + 4)),
- entryPoint: this.mem.loadCstring(start + 8),
- constants: constantsArray.reduce((prev, curr) => {
- prev[curr.key] = curr.value;
- return prev;
- }, {}),
- };
- }
- /**
- * @param {number} start
- * @returns {{ key: string, value: number }}
- */
- ConstantEntry(start) {
- return {
- key: this.mem.loadCstring(start + 4),
- value: this.mem.loadF64(start + 8),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUComputePipelineDescriptor}
- */
- ComputePipelineDescriptor(start) {
- const layoutIdx = this.mem.loadPtr(start + 8)
- return {
- label: this.mem.loadCstring(start + 4),
- layout: layoutIdx > 0 ? this.pipelineLayouts.get(layoutIdx) : undefined,
- compute: this.ProgrammableStageDescriptor(start + 8 + this.mem.intSize),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUVertexState}
- */
- VertexState(start) {
- let off = 8 + this.mem.intSize;
- const constantsArray = this.array(
- this.mem.loadUint(start + off),
- this.mem.loadPtr(start + off + this.mem.intSize),
- this.ConstantEntry,
- 16,
- );
- off += this.mem.intSize * 2;
- return {
- module: this.shaderModules.get(this.mem.loadPtr(start + 4)),
- entryPoint: this.mem.loadCstring(start + 8),
- constants: constantsArray.reduce((prev, curr) => {
- prev[curr.key] = curr.value;
- return prev;
- }, {}),
- buffers: this.array(
- this.mem.loadUint(start + off),
- this.mem.loadPtr(start + off + this.mem.intSize),
- this.VertexBufferLayout,
- this.mem.intSize == 8 ? 32 : 24,
- ),
- };
- }
- /**
- * @param {number} start
- * @returns {?GPUVertexBufferLayout}
- */
- VertexBufferLayout(start) {
- const stepMode = this.enumeration("VertexStepMode", start + 8);
- if (stepMode == "vertex-buffer-not-used") {
- return null;
- }
- return {
- arrayStride: this.mem.loadU64(start + 0),
- stepMode: stepMode,
- attributes: this.array(
- this.mem.loadUint(start + 8 + this.mem.intSize),
- this.mem.loadPtr(start + 8 + this.mem.intSize*2),
- this.VertexAttribute,
- 24,
- ),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUVertexAttribute}
- */
- VertexAttribute(start) {
- return {
- format: this.enumeration("VertexFormat", start + 0),
- offset: this.mem.loadU64(start + 8),
- shaderLocation: this.mem.loadU32(start + 16),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUPrimitiveState}
- */
- PrimitiveState(start) {
- let unclippedDepth = undefined;
- const nextInChain = this.mem.loadPtr(start);
- if (nextInChain != 0) {
- const nextInChainType = this.mem.loadI32(nextInChain + 4);
- // PrimitiveDepthClipControl = 0x00000007,
- if (nextInChainType == 7) {
- unclippedDepth = this.mem.loadB32(nextInChain + 8);
- }
- }
- return {
- topology: this.enumeration("PrimitiveTopology", start + 4),
- stripIndexFormat: this.enumeration("IndexFormat", start + 8),
- frontFace: this.enumeration("FrontFace", start + 12),
- cullMode: this.enumeration("CullMode", start + 16),
- unclippedDepth: unclippedDepth,
- };
- }
- /**
- * @param {number} start
- * @returns {GPURenderPipelineDescriptor}
- */
- RenderPipelineDescriptor(start) {
- const layoutIdx = this.mem.loadPtr(start + 8);
- const offs = this.mem.intSize == 8 ? [64, 84, 88, 104] : [40, 60, 64, 80];
- return {
- label: this.mem.loadCstring(start + 4),
- layout: layoutIdx > 0 ? this.pipelineLayouts.get(layoutIdx) : undefined,
- vertex: this.VertexState(start + 8 + this.mem.intSize),
- primitive: this.PrimitiveState(start + offs[0]),
- depthStencil: this.DepthStencilStatePtr(start + offs[1]),
- multisample: this.MultisampleState(start + offs[2]),
- fragment: this.FragmentStatePtr(start + offs[3]),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUShaderModuleCompilationHint}
- */
- ShaderModuleCompilationHint(start) {
- return {
- entryPoint: this.mem.loadCstring(start + 4),
- layout: this.pipelineLayouts.get(this.mem.loadPtr(start + 8)),
- };
- }
- /**
- * @param {number} ptr
- * @returns {?GPUDepthStencilState}
- */
- DepthStencilStatePtr(ptr) {
- const start = this.mem.loadPtr(ptr);
- if (start == 0) {
- return undefined;
- }
- return {
- format: this.enumeration("TextureFormat", start + 4),
- depthWriteEnabled: this.mem.loadB32(start + 8),
- depthCompare: this.enumeration("CompareFunction", start + 12),
- stencilFront: this.StencilFaceState(start + 16),
- stencilBack: this.StencilFaceState(start + 32),
- stencilReadMask: this.mem.loadU32(start + 48),
- stencilWriteMask: this.mem.loadU32(start + 52),
- depthBias: this.mem.loadI32(start + 56),
- depthBiasSlopeScale: this.mem.loadF32(start + 60),
- depthBiasClamp: this.mem.loadF32(start + 64),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUStencilFaceState}
- */
- StencilFaceState(start) {
- return {
- compare: this.enumeration("CompareFunction", start + 0),
- failOp: this.enumeration("StencilOperation", start + 4),
- depthFailOp: this.enumeration("StencilOperation", start + 8),
- passOp: this.enumeration("StencilOperation", start + 12),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUMultisampleState}
- */
- MultisampleState(start) {
- return {
- count: this.mem.loadU32(start + 4),
- mask: this.mem.loadU32(start + 8),
- alphaToCoverageEnabled: this.mem.loadB32(start + 12),
- };
- }
- /**
- * @param {number} ptr
- * @returns {?GPUFragmentState}
- */
- FragmentStatePtr(ptr) {
- const start = this.mem.loadPtr(ptr);
- if (start == 0) {
- return undefined;
- }
- let off = 8 + this.mem.intSize;
- const constantsArray = this.array(
- this.mem.loadUint(start + off),
- this.mem.loadPtr(start + off + this.mem.intSize),
- this.ConstantEntry,
- 16,
- );
- off += this.mem.intSize * 2;
- return {
- module: this.shaderModules.get(this.mem.loadPtr(start + 4)),
- entryPoint: this.mem.loadCstring(start + 8),
- constants: constantsArray.reduce((prev, curr) => {
- prev[curr.key] = curr.value;
- return prev;
- }, {}),
- targets: this.array(
- this.mem.loadUint(start + off),
- this.mem.loadPtr(start + off + this.mem.intSize),
- this.ColorTargetState,
- 16,
- ),
- };
- }
- /**
- * @param {number} start
- * @returns {GPUColorTargetState}
- */
- ColorTargetState(start) {
- return {
- format: this.enumeration("TextureFormat", start + 4),
- blend: this.BlendStatePtr(start + 8),
- writeMask: this.mem.loadU32(start + 12),
- };
- }
- /**
- * @param {number} ptr
- * @returns {?GPUBlendState}
- */
- BlendStatePtr(ptr) {
- const start = this.mem.loadPtr(ptr);
- if (start == 0) {
- return undefined;
- }
- return {
- color: this.BlendComponent(start + 0),
- alpha: this.BlendComponent(start + 12),
- };
- }
- /**
- * @param {number} start
- * @returns {?GPUBlendComponent}
- */
- BlendComponent(start) {
- return {
- operation: this.enumeration("BlendOperation", start + 0),
- srcFactor: this.enumeration("BlendFactor", start + 4),
- dstFactor: this.enumeration("BlendFactor", start + 8),
- };
- }
- getInterface() {
- return {
- /**
- * @param {0|number} descriptorPtr
- * @returns {number}
- */
- wgpuCreateInstance: (descriptorPtr) => {
- if (!navigator.gpu) {
- console.error("WebGPU is not supported by this browser");
- return 0;
- }
- return this.instances.create({});
- },
- /**
- * @param {number} deviceIdx
- * @param {number} procNamePtr
- * @returns {number}
- */
- wgpuGetProcAddress: (deviceIdx, procNamePtr) => {
- console.error(`unimplemented: wgpuGetProcAddress`);
- return 0;
- },
- /* ---------------------- Adapter ---------------------- */
- /**
- * @param {number} adapterIdx
- * @param {number} featuresPtr
- * @returns {number|BigInt}
- */
- wgpuAdapterEnumerateFeatures: (adapterIdx, featuresPtr) => {
- const adapter = this.adapters.get(adapterIdx);
- return this.genericEnumerateFeatures(adapter.features, featuresPtr);
- },
- /**
- * @param {number} adapterIdx
- * @param {number} supportedLimitsPtr
- * @returns {boolean}
- */
- wgpuAdapterGetLimits: (adapterIdx, supportedLimitsPtr) => {
- const adapter = this.adapters.get(adapterIdx);
- return this.genericGetLimits(adapter.limits, supportedLimitsPtr);
- },
- /**
- * @param {number} adapterIdx
- * @param {number} infoPtr
- */
- wgpuAdapterGetInfo: (adapterIdx, infoPtr) => {
- this.assert(infoPtr != 0);
- // WebGPU backend.
- this.mem.storeI32(infoPtr + 20, 2);
- // Unknown adapter.
- this.mem.storeI32(infoPtr + 24, 3);
- // NOTE: I don't think getting the other fields in this struct is possible.
- // `adapter.requestAdapterInfo` is deprecated.
- },
- /**
- * @param {number} infoPtr
- */
- wgpuAdapterInfoFreeMembers: (infoPtr) => {
- // NOTE: nothing to free.
- },
- /**
- * @param {number} adapterIdx
- * @param {number} featureInt
- * @returns {boolean}
- */
- wgpuAdapterHasFeature: (adapterIdx, featureInt) => {
- const adapter = this.adapters.get(adapterIdx);
- return adapter.features.has(this.enums.FeatureName[featureInt]);
- },
- /**
- * @param {number} adapterIdx
- * @param {0|number} descriptorPtr
- * @param {number} callbackPtr
- * @param {0|number} userdata
- */
- wgpuAdapterRequestDevice: async (adapterIdx, descriptorPtr, callbackPtr, userdata) => {
- const adapter = this.adapters.get(adapterIdx);
- const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
- /** @type {GPUDeviceDescriptor} */
- let descriptor;
- if (descriptorPtr != 0) {
- descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- requiredFeatures: this.array(
- this.mem.loadUint(descriptorPtr + 8),
- this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize),
- this.FeatureNamePtr,
- 4,
- ),
- requiredLimits: this.RequiredLimitsPtr(descriptorPtr + 8 + this.mem.intSize + 4),
- defaultQueue: this.QueueDescriptor( descriptorPtr + 8 + this.mem.intSize + 4 + 4),
- };
- }
- let device;
- let deviceIdx;
- try {
- device = await adapter.requestDevice(descriptor);
- deviceIdx = this.devices.create(device);
- // NOTE: don't callback here, any errors that happen later will then be caught by the catch here.
- } catch (e) {
- const messageLength = new TextEncoder().encode(e.message).length;
- const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
- this.mem.storeString(messageAddr, e.message);
- callback(1, null, messageAddr, userdata);
- this.mem.exports.wgpu_free(messageAddr);
- }
- let callbacksPtr = descriptorPtr + 24 + this.mem.intSize;
- const deviceLostCallbackPtr = this.mem.loadPtr(callbacksPtr);
- if (deviceLostCallbackPtr != 0) {
- const deviceLostUserData = this.mem.loadPtr(callbacksPtr) + 4;
- const deviceLostCallback = this.mem.exports.__indirect_function_table.get(deviceLostCallbackPtr);
- device.lost.then((info) => {
- const reason = this.enums.DeviceLostReason.indexOf(info.reason);
- const messageLength = new TextEncoder().encode(info.message).length;
- const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
- this.mem.storeString(messageAddr, info.message);
- deviceLostCallback(reason, messageAddr, deviceLostUserData);
- this.mem.exports.wgpu_free(messageAddr);
- });
- }
- callbacksPtr += 8;
- // Skip over `nextInChain`.
- callbacksPtr += 4;
- const uncapturedErrorCallbackPtr = this.mem.loadPtr(callbacksPtr);
- if (uncapturedErrorCallbackPtr != 0) {
- const uncapturedErrorUserData = this.mem.loadPtr(callbacksPtr + 4);
- const uncapturedErrorCallback = this.mem.exports.__indirect_function_table.get(uncapturedErrorCallbackPtr);
- device.onuncapturederror = (ev) => {
- let status = 4; // Unknown
- if (ev.error instanceof GPUValidationError) {
- status = 1; // Validation
- } else if (ev.error instanceof GPUOutOfMemoryError) {
- status = 2; // OutOfMemory
- } else if (ev.error instanceof GPUInternalError) {
- status = 3; // Internal
- }
- const messageLength = new TextEncoder().encode(ev.error.message).length;
- const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
- this.mem.storeString(messageAddr, ev.error.message);
- uncapturedErrorCallback(status, messageAddr, uncapturedErrorUserData);
- this.mem.exports.wgpu_free(messageAddr);
- };
- }
- callback(0, deviceIdx, null, userdata);
- },
- ...this.adapters.interface(),
- /* ---------------------- BindGroup ---------------------- */
- ...this.bindGroups.interface(true),
- /* ---------------------- BindGroupLayout ---------------------- */
- ...this.bindGroupLayouts.interface(true),
- /* ---------------------- Buffer ---------------------- */
- /** @param {number} bufferIdx */
- wgpuBufferDestroy: (bufferIdx) => {
- const buffer = this.buffers.get(bufferIdx);
- buffer.buffer.destroy();
- },
- /**
- * @param {number} bufferIdx
- * @param {number|BigInt} offset
- * @param {number|BigInt} size
- * @returns {number}
- */
- wgpuBufferGetMappedRange: (bufferIdx, offset, size) => {
- const buffer = this.buffers.get(bufferIdx);
- offset = this.unwrapBigInt(offset);
- size = this.unwrapBigInt(size);
- this.assert(!buffer.mapping, "buffer already mapped");
- const range = buffer.buffer.getMappedRange(offset, size);
- const ptr = this.mem.exports.wgpu_alloc(range.byteLength);
- buffer.mapping = { range: range, ptr: ptr, size: range.byteLength };
- return ptr;
- },
- /**
- * @param {number} bufferIdx
- * @returns {BigInt}
- */
- wgpuBufferGetSize: (bufferIdx) => {
- const buffer = this.buffers.get(bufferIdx);
- return BigInt(buffer.buffer.size);
- },
- /**
- * @param {number} bufferIdx
- * @returns {number}
- */
- wgpuBufferGetUsage: (bufferIdx) => {
- const buffer = this.buffers.get(bufferIdx);
- return buffer.buffer.usage;
- },
- /**
- * @param {number} bufferIdx
- * @param {number} mode
- * @param {number|BigInt} offset
- * @param {number|BigInt} size
- * @param {number} callbackPtr
- * @param {0|number} userdata
- */
- wgpuBufferMapAsync: async (bufferIdx, mode, offset, size, callbackPtr, userdata) => {
- const buffer = this.buffers.get(bufferIdx);
- const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
- offset = this.unwrapBigInt(offset);
- size = this.unwrapBigInt(size);
- if (buffer.buffer.mapState == "pending") {
- callback(this.enums.BufferMapAsyncStatus.MappingAlreadyPending, userdata);
- } else {
- let result;
- try {
- await buffer.buffer.mapAsync(mode, offset, size);
- result = 0; // Success.
- } catch(e) {
- console.warn(e);
- result = 2; // Unknown error.
- if (e instanceof DomException) {
- if (e.name == "OperationError") {
- result = 1; // Validation error.
- }
- }
- }
- callback(result, userdata);
- }
- },
- /**
- * @param {number} bufferIdx
- * @param {number} labelPtr
- */
- wgpuBufferSetLabel: (bufferIdx, labelPtr) => {
- const buffer = this.buffers.get(bufferIdx);
- buffer.buffer.label = this.mem.loadCstring(labelPtr);
- },
- /**
- * @param {number} bufferIdx
- */
- wgpuBufferUnmap: (bufferIdx) => {
- const buffer = this.buffers.get(bufferIdx);
- this.assert(buffer.mapping, "buffer not mapped");
- const mapping = new Uint8Array(this.mem.memory.buffer, buffer.mapping.ptr, buffer.mapping.size);
- (new Uint8Array(buffer.mapping.range)).set(mapping);
- buffer.buffer.unmap();
- this.mem.exports.wgpu_free(buffer.mapping.ptr);
- buffer.mapping = null;
- },
- ...this.buffers.interface(),
- /* ---------------------- CommandBuffer ---------------------- */
- ...this.commandBuffers.interface(true),
- /* ---------------------- CommandEncoder ---------------------- */
- /**
- * @param {number} commandEncoderIdx
- * @param {0|number} descriptorPtr
- * @return {number} The compute pass encoder
- */
- wgpuCommandEncoderBeginComputePass: (commandEncoderIdx, descriptorPtr) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- /** @type {?GPUComputePassDescriptor} */
- let descriptor;
- if (descriptorPtr != 0) {
- descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- timestampWrites: this.ComputePassTimestampWritesPtr(descriptorPtr + 8),
- };
- }
- const computePassEncoder = commandEncoder.beginComputePass(descriptor);
- return this.computePassEncoders.create(computePassEncoder);
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} descriptorPtr
- * @return {number} The render pass encoder
- */
- wgpuCommandEncoderBeginRenderPass: (commandEncoderIdx, descriptorPtr) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- this.assert(descriptorPtr != 0);
- let maxDrawCount = undefined;
- const nextInChain = this.mem.loadPtr(descriptorPtr);
- if (nextInChain != 0) {
- const nextInChainType = this.mem.loadI32(nextInChain + 4);
- // RenderPassDescriptorMaxDrawCount = 0x0000000F,
- if (nextInChainType == 0x0000000F) {
- maxDrawCount = this.mem.loadU64(nextInChain + 8);
- }
- }
- /** @type {GPURenderPassDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- colorAttachments: this.array(
- this.mem.loadUint(descriptorPtr + 8),
- this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize),
- this.RenderPassColorAttachment,
- 56,
- ),
- depthStencilAttachment: this.RenderPassDepthStencilAttachmentPtr(descriptorPtr + 8 + this.mem.intSize + 4),
- occlusionQuerySet: this.QuerySet(descriptorPtr + 8 + this.mem.intSize + 4 + 4),
- timestampWrites: this.RenderPassTimestampWritesPtr(descriptorPtr + 8 + this.mem.intSize + 4 + 4),
- maxDrawCount: maxDrawCount,
- };
- const renderPassEncoder = commandEncoder.beginRenderPass(descriptor);
- return this.renderPassEncoders.create(renderPassEncoder);
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} bufferIdx
- * @param {BigInt} offset
- * @param {BigInt} size
- */
- wgpuCommandEncoderClearBuffer: (commandEncoderIdx, bufferIdx, offset, size) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- const buffer = this.buffers.get(bufferIdx);
- offset = this.unwrapBigInt(offset);
- size = this.unwrapBigInt(size);
- commandEncoder.clearBuffer(buffer.buffer, offset, size);
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} sourceIdx
- * @param {BigInt} sourceOffset
- * @param {number} destinationIdx
- * @param {BigInt} destinationOffset
- * @param {BigInt} size
- */
- wgpuCommandEncoderCopyBufferToBuffer: (commandEncoderIdx, sourceIdx, sourceOffset, destinationIdx, destinationOffset, size) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- const source = this.buffers.get(sourceIdx);
- const destination = this.buffers.get(destinationIdx);
- sourceOffset = this.unwrapBigInt(sourceOffset);
- destinationOffset = this.unwrapBigInt(destinationOffset);
- size = this.unwrapBigInt(size);
- commandEncoder.copyBufferToBuffer(source.buffer, sourceOffset, destination.buffer, destinationOffset, size);
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} sourcePtr
- * @param {number} destinationPtr
- * @param {number} copySizePtr
- */
- wgpuCommandEncoderCopyBufferToTexture: (commandEncoderIdx, sourcePtr, destinationPtr, copySizePtr) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- commandEncoder.copyBufferToTexture(
- this.ImageCopyBuffer(sourcePtr),
- this.ImageCopyTexture(destinationPtr),
- this.Extent3D(copySizePtr),
- );
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} sourcePtr
- * @param {number} destinationPtr
- * @param {number} copySizePtr
- */
- wgpuCommandEncoderCopyTextureToBuffer: (commandEncoderIdx, sourcePtr, destinationPtr, copySizePtr) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- commandEncoder.copyTextureToBuffer(
- this.ImageCopyTexture(sourcePtr),
- this.ImageCopyBuffer(destinationPtr),
- this.Extent3D(copySizePtr),
- );
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} sourcePtr
- * @param {number} destinationPtr
- * @param {number} copySizePtr
- */
- wgpuCommandEncoderCopyTextureToTexture: (commandEncoderIdx, sourcePtr, destinationPtr, copySizePtr) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- commandEncoder.copyTextureToTexture(
- this.ImageCopyTexture(sourcePtr),
- this.ImageCopyTexture(destinationPtr),
- this.Extent3D(copySizePtr),
- );
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {0|number} descriptorPtr
- * @returns {number} The command buffer.
- */
- wgpuCommandEncoderFinish: (commandEncoderIdx, descriptorPtr) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- /** @type {undefined|GPUCommandBufferDescriptor} */
- let descriptor;
- if (descriptorPtr != 0) {
- descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- };
- }
- const commandBuffer = commandEncoder.finish(descriptor);
- return this.commandBuffers.create(commandBuffer);
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} markerLabelPtr
- */
- wgpuCommandEncoderInsertDebugMarker: (commandEncoderIdx, markerLabelPtr) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- commandEncoder.insertDebugMarker(this.mem.loadCstring(markerLabelPtr));
- },
- /**
- * @param {number} commandEncoderIdx
- */
- wgpuCommandEncoderPopDebugGroup: (commandEncoderIdx) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- commandEncoder.popDebugGroup();
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} markerLabelPtr
- */
- wgpuCommandEncoderPushDebugGroup: (commandEncoderIdx, groupLabelPtr) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- commandEncoder.pushDebugGroup(this.mem.loadCstring(groupLabelPtr));
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} querySetIdx
- * @param {number} firstQuery
- * @param {number} queryCount
- * @param {number} destinationIdx
- * @param {BigInt} destinationOffset
- */
- wgpuCommandEncoderResolveQuerySet: (commandEncoderIdx, querySetIdx, firstQuery, queryCount, destinationIdx, destinationOffset) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- const querySet = this.querySets.get(querySetIdx);
- const destination = this.buffers.get(destinationIdx);
- destinationOffset = this.unwrapBigInt(destinationOffset);
- commandEncoder.resolveQuerySet(querySet, firstQuery, queryCount, destination.buffer, destinationOffset);
- },
- /**
- * @param {number} commandEncoderIdx
- * @param {number} querySetIdx
- * @param {number} queryIndex
- */
- wgpuCommandEncoderWriteTimestamp: (commandEncoderIdx, querySetIdx, queryIndex) => {
- const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
- const querySet = this.querySets.get(querySetIdx);
- commandEncoder.writeTimestamp(querySet, queryIndex);
- },
- ...this.commandEncoders.interface(true),
- /* ---------------------- ComputePassEncoder ---------------------- */
- /**
- * @param {number} computePassEncoderIdx
- * @param {number} workgroupCountX
- * @param {number} workgroupCountY
- * @param {number} workgroupCountZ
- */
- wgpuComputePassEncoderDispachWorkgroups: (computePassEncoderIdx, workgroupCountX, workgroupCountY, workgroupCountZ) => {
- const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
- computePassEncoder.dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ);
- },
- /**
- * @param {number} computePassEncoderIdx
- * @param {number} indirectBufferIdx
- * @param {BigInt} indirectOffset
- */
- wgpuComputePassEncoderDispachWorkgroupsIndirect: (computePassEncoderIdx, indirectBufferIdx, indirectOffset) => {
- const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
- const indirectBuffer = this.buffers.get(indirectBufferIdx);
- indirectOffset = this.unwrapBigInt(indirectOffset);
- computePassEncoder.dispatchWorkgroupsIndirect(indirectBuffer.buffer, indirectOffset);
- },
- /**
- * @param {number} computePassEncoderIdx
- */
- wgpuComputePassEncoderEnd: (computePassEncoderIdx) => {
- const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
- computePassEncoder.end();
- },
- /**
- * @param {number} computePassEncoderIdx
- * @param {number} markerLabelPtr
- */
- wgpuComputePassEncoderInsertDebugMarker: (computePassEncoderIdx, markerLabelPtr) => {
- const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
- computePassEncoder.insertDebugMarker(this.mem.loadCstring(markerLabelPtr));
- },
- /**
- * @param {number} computePassEncoderIdx
- */
- wgpuComputePassEncoderPopDebugGroup: (computePassEncoderIdx) => {
- const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
- computePassEncoder.popDebugGroup();
- },
- /**
- * @param {number} computePassEncoderIdx
- * @param {number} markerLabelPtr
- */
- wgpuComputePassEncoderPushDebugGroup: (computePassEncoderIdx, groupLabelPtr) => {
- const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
- computePassEncoder.pushDebugGroup(this.mem.loadCstring(groupLabelPtr));
- },
- /**
- * @param {number} computePassEncoderIdx
- * @param {number} groupIndex
- * @param {0|number} groupIdx
- * @param {number|BigInt} dynamicOffsetCount
- * @param {number} dynamicOffsetsPtr
- */
- wgpuComputePassEncoderSetBindGroup: (computePassEncoderIdx, groupIndex, groupIdx, dynamicOffsetCount, dynamicOffsetsPtr) => {
- const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
- dynamicOffsetCount = this.unwrapBigInt(dynamicOffsetCount);
- let bindGroup;
- if (groupIdx != 0) {
- bindGroup = this.bindGroups.get(groupIdx);
- }
- const dynamicOffsets = [];
- for (let i = 0; i < dynamicOffsetCount; i += 1) {
- dynamicOffsets.push(this.mem.loadU32(dynamicOffsetsPtr));
- dynamicOffsetsPtr += 4;
- }
- computePassEncoder.setBindGroup(groupIndex, bindGroup, dynamicOffsets);
- },
- /**
- * @param {number} computePassEncoderIdx
- * @param {number} pipelineIdx
- */
- wgpuComputePassEncoderSetPipeline: (computePassEncoderIdx, pipelineIdx) => {
- const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
- const pipeline = this.computePipelines.get(pipelineIdx);
- computePassEncoder.setPipeline(pipeline);
- },
- ...this.computePassEncoders.interface(true),
- /* ---------------------- ComputePipeline ---------------------- */
- /**
- * @param {number} computePipelineIdx
- * @param {number} groupIndex
- * @returns {number}
- */
- wgpuComputePipelineGetBindGroupLayout: (computePipelineIdx, groupIndex) => {
- const computePipeline = this.computePipelines.get(computePipelineIdx);
- const bindGroupLayout = computePipeline.getBindGroupLayout(groupIndex);
- return this.bindGroupLayouts.create(bindGroupLayout);
- },
- ...this.computePipelines.interface(true),
- /* ---------------------- Device ---------------------- */
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The bind group.
- */
- wgpuDeviceCreateBindGroup: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- /** @type {GPUBindGroupDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- layout: this.bindGroupLayouts.get(this.mem.loadPtr(descriptorPtr + 8)),
- entries: this.array(
- this.mem.loadUint(descriptorPtr + 8 + this.mem.intSize),
- this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize * 2),
- this.BindGroupEntry,
- 40,
- ),
- };
-
- const bindGroup = device.createBindGroup(descriptor);
- return this.bindGroups.create(bindGroup);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The bind group layout.
- */
- wgpuDeviceCreateBindGroupLayout: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- /** @type {GPUBindGroupLayoutDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- entries: this.array(
- this.mem.loadUint(descriptorPtr + 8),
- this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize),
- this.BindGroupLayoutEntry,
- 80,
- ),
- };
- const bindGroupLayout = device.createBindGroupLayout(descriptor);
- return this.bindGroupLayouts.create(bindGroupLayout);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The buffer.
- */
- wgpuDeviceCreateBuffer: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- /** @type {GPUBufferDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- usage: this.mem.loadU32(descriptorPtr + 8),
- size: this.mem.loadU64(descriptorPtr + 16),
- mappedAtCreation: this.mem.loadB32(descriptorPtr + 24),
- };
- const buffer = device.createBuffer(descriptor);
- return this.buffers.create({buffer: buffer, mapping: null});
- },
- /**
- * @param {number} deviceIdx
- * @param {0|number} descriptorPtr
- * @returns {number} The command encoder.
- */
- wgpuDeviceCreateCommandEncoder: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- /** @type {GPUCommandEncoderDescriptor} */
- let descriptor;
- if (descriptor != 0) {
- descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- };
- }
- const commandEncoder = device.createCommandEncoder(descriptor);
- return this.commandEncoders.create(commandEncoder);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The compute pipeline.
- */
- wgpuDeviceCreateComputePipeline: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- const computePipeline = device.createComputePipeline(this.ComputePipelineDescriptor(descriptorPtr));
- return this.computePipelines.create(computePipeline);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @param {number} callbackPtr
- * @param {number} userdata
- */
- wgpuDeviceCreateComputePipelineAsync: async (deviceIdx, descriptorPtr, callbackPtr, userdata) => {
- const device = this.devices.get(deviceIdx);
- const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
- this.assert(descriptorPtr != 0);
- let result;
- let resultIdx;
- try {
- const computePipeline = await device.createComputePipelineAsync(this.ComputePipelineDescriptor(descriptorPtr));
- resultIdx = this.computePipelines.create(computePipeline);
- result = 0; /* Success */
- // NOTE: don't callback here, any errors that happen later will then be caught by the catch here.
- } catch (e) {
- console.warn(e);
- result = 5; /* Unknown error */
- }
- callback(result, resultIdx, null, userdata);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The pipeline layout.
- */
- wgpuDeviceCreatePipelineLayout: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- /** @type {GPUPipelineLayoutDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- bindGroupLayouts: this.array(
- this.mem.loadUint(descriptorPtr + 8),
- this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize),
- (ptr) => this.bindGroupLayouts.get(this.mem.loadPtr(ptr)),
- 4,
- ),
- };
- const pipelineLayout = device.createPipelineLayout(descriptor);
- return this.pipelineLayouts.create(pipelineLayout);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The query set.
- */
- wgpuDeviceCreateQuerySet: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- /** @type {GPUQuerySetDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- type: this.QueryType(descriptorPtr + 8),
- count: this.mem.loadU32(descriptorPtr + 12),
- };
- const querySet = device.createQuerySet(descriptor);
- return this.querySets.create(querySet);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The query set.
- */
- wgpuDeviceCreateRenderBundleEncoder: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- /** @type {GPURenderBundleEncoderDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- colorFormats: this.array(
- this.mem.loadUint(descriptorPtr + 8),
- this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize),
- this.TextureFormat,
- 4,
- ),
- depthStencilFormat: this.enumeration("TextureFormat", descriptorPtr + 8 + this.mem.intSize + 4),
- sampleCount: this.mem.loadU32(descriptorPtr + 8 + this.mem.intSize + 8),
- depthReadOnly: this.mem.loadB32(descriptorPtr + 8 + this.mem.intSize + 12),
- stencilReadOnly: this.mem.loadB32(descriptorPtr + 8 + this.mem.intSize + 16),
- };
- const renderBundleEncoder = device.createRenderBundleEncoder(descriptor);
- return this.renderBundleEncoders.create(renderBundleEncoder);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The render pipeline.
- */
- wgpuDeviceCreateRenderPipeline: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- const descriptor = this.RenderPipelineDescriptor(descriptorPtr);
- const renderPipeline = device.createRenderPipeline(descriptor);
- return this.renderPipelines.create(renderPipeline);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @param {number} callbackPtr
- * @param {number} userdata
- */
- wgpuDeviceCreateRenderPipelineAsync: async (deviceIdx, descriptorPtr, callbackPtr, userdata) => {
- const device = this.devices.get(deviceIdx);
- const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
- this.assert(descriptorPtr != 0);
- let result;
- let resultIdx;
- try {
- const renderPipeline = await device.createRenderPipelineAsync(this.RenderPipelineDescriptor(descriptorPtr));
- resultIdx = this.renderPipelines.create(renderPipeline);
- result = 0; /* Success */
- // NOTE: don't callback here, any errors that happen later will then be caught by the catch here.
- } catch (e) {
- console.warn(e);
- result = 5; /* Unknown error */
- }
- callback(result, resultIdx, null, userdata);
- },
- /**
- * @param {number} deviceIdx
- * @param {0|number} descriptorPtr
- * @returns {number} The sampler.
- */
- wgpuDeviceCreateSampler: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- /** @type {?GPUSamplerDescriptor} */
- let descriptor;
- if (descriptorPtr != 0) {
- descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- addressModeU: this.enumeration("AddressMode", descriptorPtr + 8),
- addressModeV: this.enumeration("AddressMode", descriptorPtr + 12),
- addressModeW: this.enumeration("AddressMode", descriptorPtr + 16),
- magFilter: this.enumeration("FilterMode", descriptorPtr + 20),
- minFilter: this.enumeration("FilterMode", descriptorPtr + 24),
- mipMapFilter: this.enumeration("MipmapFilterMode", descriptorPtr + 28),
- lodMinClamp: this.mem.loadF32(descriptorPtr + 32),
- lodMaxClamp: this.mem.loadF32(descriptorPtr + 36),
- compare: this.enumeration("CompareFunction", descriptorPtr + 40),
- maxAnisotropy: this.mem.loadU16(descriptorPtr + 44),
- };
- }
- const sampler = device.createSampler(descriptor);
- return this.samplers.create(sampler);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The shader module.
- */
- wgpuDeviceCreateShaderModule: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- const nextInChain = this.mem.loadPtr(descriptorPtr);
- const nextInChainType = this.mem.loadI32(nextInChain + 4);
- // ShaderModuleWGSLDescriptor = 0x00000006,
- if (nextInChainType != 6) {
- throw new TypeError(`Descriptor type should be 'ShaderModuleWGSLDescriptor', got ${nextInChainType}`);
- }
- /** @type {GPUShaderModuleDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- code: this.mem.loadCstring(nextInChain + 8),
- compilationHints: this.array(
- this.mem.loadUint(descriptorPtr + 8),
- this.mem.loadPtr(descriptorPtr + 8 + this.mem.intSize),
- this.ShaderModuleCompilationHint,
- 12,
- ),
- };
- const shaderModule = device.createShaderModule(descriptor);
- return this.shaderModules.create(shaderModule);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} descriptorPtr
- * @returns {number} The texture.
- */
- wgpuDeviceCreateTexture: (deviceIdx, descriptorPtr) => {
- const device = this.devices.get(deviceIdx);
- this.assert(descriptorPtr != 0);
- /** @type {GPUTextureDescriptor} */
- const descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- usage: this.mem.loadU32(descriptorPtr + 8),
- dimension: this.enumeration("TextureDimension", descriptorPtr + 12),
- size: this.Extent3D(descriptorPtr + 16),
- format: this.enumeration("TextureFormat", descriptorPtr + 28),
- mipLevelCount: this.mem.loadU32(descriptorPtr + 32),
- sampleCount: this.mem.loadU32(descriptorPtr + 36),
- viewFormats: this.array(
- this.mem.loadUint(descriptorPtr + 40),
- this.mem.loadPtr(descriptorPtr + 40 + this.mem.intSize),
- (ptr) => this.enumeration("TextureFormat", ptr),
- 4,
- ),
- };
- const texture = device.createTexture(descriptor);
- return this.textures.create(texture);
- },
- /**
- * @param {number} deviceIdx
- */
- wgpuDeviceDestroy: (deviceIdx) => {
- const device = this.devices.get(deviceIdx);
- device.destroy();
- },
- /**
- * @param {number} deviceIdx
- * @param {number} featuresPtr
- * @returns {number|BigInt}
- */
- wgpuDeviceEnumerateFeatures: (deviceIdx, featuresPtr) => {
- const device = this.devices.get(deviceIdx);
- return this.genericEnumerateFeatures(device.features, featuresPtr);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} limitsPtr
- * @returns {boolean}
- */
- wgpuDeviceGetLimits: (deviceIdx, limitsPtr) => {
- const device = this.devices.get(deviceIdx);
- return this.genericGetLimits(device.limits, limitsPtr);
- },
- /**
- * @param {number} deviceIdx
- * @returns {number}
- */
- wgpuDeviceGetQueue: (deviceIdx) => {
- const device = this.devices.get(deviceIdx);
- return this.queues.create(device.queue);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} featureInt
- * @returns {boolean}
- */
- wgpuDeviceHasFeature: (deviceIdx, featureInt) => {
- const device = this.devices.get(deviceIdx);
- return device.features.has(this.enums.FeatureName[featureInt]);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} callbackPtr
- * @param {number} userdata
- */
- wgpuDevicePopErrorScope: async (deviceIdx, callbackPtr, userdata) => {
- const device = this.devices.get(deviceIdx);
- const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
- const error = await device.popErrorScope();
- if (!error) {
- callback(0, null, userdata);
- return;
- }
- console.warn(error);
- let status = 4;
- if (error instanceof GPUValidationError) {
- status = 1;
- } else if (error instanceof GPUOutOfMemoryError) {
- status = 2;
- } else if (error instanceof GPUInternalError) {
- status = 3;
- }
- callback(status, null, userdata);
- },
- /**
- * @param {number} deviceIdx
- * @param {number} filterInt
- */
- wgpuDevicePushErrorScope: (deviceIdx, filterInt) => {
- const device = this.devices.get(deviceIdx);
- device.pushErrorScope(this.enums.ErrorFilter[filterInt]);
- },
- ...this.devices.interface(true),
- /* ---------------------- Instance ---------------------- */
- /**
- * @param {number} instanceIdx
- * @param {number} descriptorPtr
- */
- wgpuInstanceCreateSurface: (instanceIdx, descriptorPtr) => {
- this.assert(instanceIdx > 0);
- this.assert(descriptorPtr != 0);
- const nextInChain = this.mem.loadPtr(descriptorPtr);
- const nextInChainType = this.mem.loadI32(nextInChain + 4);
- // SurfaceDescriptorFromCanvasHTMLSelector = 0x00000004,
- if (nextInChainType != 4) {
- throw new TypeError(`Descriptor type should be 'SurfaceDescriptorFromCanvasHTMLSelector', got ${nextInChainType}`);
- }
- const selector = this.mem.loadCstring(nextInChain + 8);
- const surface = document.querySelector(selector);
- if (!surface) {
- throw new Error(`Selector '${selector}' did not match any element`);
- }
- if (!(surface instanceof HTMLCanvasElement)) {
- throw new Error('Selector matches an element that is not a canvas');
- }
- return this.surfaces.create(surface);
- },
- /**
- * @param {number} instanceIdx
- * @param {number} featureInt
- * @returns {boolean}
- */
- wgpuInstanceHasWGSLLanguageFeature: (instanceIdx, featureInt) => {
- return navigator.gpu.wgslLanguageFeatures.has(this.enums.WGSLFeatureName[featureInt]);
- },
- /**
- * @param {number} instanceIdx
- */
- wgpuInstanceProcessEvents: (instanceIdx) => {
- console.warn("unimplemented: wgpuInstanceProcessEvents");
- },
- /**
- * @param {number} instanceIdx
- * @param {0|number} optionsPtr
- * @param {number} callbackPtr
- * @param {number} userdata
- */
- wgpuInstanceRequestAdapter: async (instanceIdx, optionsPtr, callbackPtr, userdata) => {
- this.assert(instanceIdx > 0);
- const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
- /** @type {GPURequestAdapterOptions} */
- let options;
- if (optionsPtr != 0) {
- options = {
- powerPreference: this.enumeration("PowerPreference", optionsPtr + 8),
- forceFallbackAdapter: this.mem.loadB32(optionsPtr + 16),
- };
- }
- let adapterIdx;
- try {
- const adapter = await navigator.gpu.requestAdapter(options);
- adapterIdx = this.adapters.create(adapter);
- // NOTE: don't callback here, any errors that happen later will then be caught by the catch here.
- } catch(e) {
- console.warn(e);
- callback(2, null, null, userdata);
- }
- callback(0, adapterIdx, null, userdata);
- },
- ...this.instances.interface(false),
- /* ---------------------- PipelineLayout ---------------------- */
- ...this.pipelineLayouts.interface(true),
- /* ---------------------- QuerySet ---------------------- */
- /**
- * @param {number} querySetIdx
- */
- wgpuQuerySetDestroy: (querySetIdx) => {
- const querySet = this.querySets.get(querySetIdx);
- querySet.destroy();
- },
- /**
- * @param {number} querySetIdx
- * @returns {number}
- */
- wgpuQuerySetGetCount: (querySetIdx) => {
- const querySet = this.querySets.get(querySetIdx);
- return querySet.count;
- },
- /**
- * @param {number} querySetIdx
- * @returns {number}
- */
- wgpuQuerySetGetType: (querySetIdx) => {
- const querySet = this.querySets.get(querySetIdx);
- return this.enums.QueryType.indexOf(querySet.type);
- },
- ...this.querySets.interface(true),
- /* ---------------------- Queue ---------------------- */
- /**
- * @param {number} queueIdx
- * @param {number} callbackPtr
- * @param {number} userdata
- */
- wgpuQueueOnSubmittedWorkDone: async (queueIdx, callbackPtr, userdata) => {
- const queue = this.queues.get(queueIdx);
- const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
- let result;
- try {
- await queue.onSubmittedWorkDone();
- result = 0;
- } catch(e) {
- console.warn(e);
- result = 1;
- }
- callback(result, userdata);
- },
- /**
- * @param {number} queueIdx
- * @param {BigInt|number} commandCount
- * @param {number} commandsPtr
- */
- wgpuQueueSubmit: (queueIdx, commandCount, commandsPtr) => {
- const queue = this.queues.get(queueIdx);
- const commands = this.array(
- this.unwrapBigInt(commandCount),
- commandsPtr,
- (ptr) => this.commandBuffers.get(this.mem.loadPtr(ptr)),
- 4,
- );
- queue.submit(commands);
- },
- /**
- * @param {number} queueIdx
- * @param {number} bufferIdx
- * @param {BigInt} bufferOffset
- * @param {number} dataPtr
- * @param {number|BigInt} size
- */
- wgpuQueueWriteBuffer: (queueIdx, bufferIdx, bufferOffset, dataPtr, size) => {
- const queue = this.queues.get(queueIdx);
- const buffer = this.buffers.get(bufferIdx);
- bufferOffset = this.unwrapBigInt(bufferOffset);
- size = this.unwrapBigInt(size);
- queue.writeBuffer(buffer.buffer, bufferOffset, this.mem.loadBytes(dataPtr, size), 0, size);
- },
- /**
- * @param {number} queueIdx
- * @param {number} destinationPtr
- * @param {number} dataPtr
- * @param {number|BigInt} dataSize
- * @param {number} dataLayoutPtr
- * @param {number} writeSizePtr
- */
- wgpuQueueWriteTexture: (queueIdx, destinationPtr, dataPtr, dataSize, dataLayoutPtr, writeSizePtr) => {
- const queue = this.queues.get(queueIdx);
- const destination = this.ImageCopyTexture(destinationPtr);
- dataSize = this.unwrapBigInt(dataSize);
- const dataLayout = this.TextureDataLayout(dataLayoutPtr);
- const writeSize = this.Extent3D(writeSizePtr);
- queue.writeTexture(destination, this.mem.loadBytes(dataPtr, dataSize), dataLayout, writeSize);
- },
- ...this.queues.interface(true),
- /* ---------------------- RenderBundle ---------------------- */
- ...this.renderBundles.interface(true),
- /* ---------------------- RenderBundleEncoder ---------------------- */
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} vertexCount
- * @param {number} instanceCount
- * @param {number} firstVertex
- * @param {number} firstInstance
- */
- wgpuRenderBundleEncoderDraw: (renderBundleEncoderIdx, vertexCount, instanceCount, firstVertex, firstInstance) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- renderBundleEncoder.draw(vertexCount, instanceCount, firstVertex, firstInstance);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} indexCount
- * @param {number} instanceCount
- * @param {number} firstIndex
- * @param {number} baseVertex
- * @param {number} firstInstance
- */
- wgpuRenderBundleEncoderDrawIndexed: (renderBundleEncoderIdx, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- renderBundleEncoder.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} indirectBufferIdx
- * @param {BigInt} indirectOffset
- */
- wgpuRenderBundleEncoderDrawIndexedIndirect: (renderBundleEncoderIdx, indirectBufferIdx, indirectOffset) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- indirectOffset = this.unwrapBigInt(indirectOffset);
- const buffer = this.buffers.get(indirectBufferIdx);
- renderBundleEncoder.drawIndexedIndirect(buffer.buffer, indirectOffset);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} indirectBufferIdx
- * @param {BigInt} indirectOffset
- */
- wgpuRenderBundleEncoderDrawIndirect: (renderBundleEncoderIdx, indirectBufferIdx, indirectOffset) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- indirectOffset = this.unwrapBigInt(indirectOffset);
- const buffer = this.buffers.get(indirectBufferIdx);
- renderBundleEncoder.drawIndirect(buffer.buffer, indirectOffset);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {0|number} descriptorPtr
- * @returns {number}
- */
- wgpuRenderBundleEncoderFinish: (renderBundleEncoderIdx, descriptorPtr) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- /** @type {?GPURenderBundleDescriptor} */
- let descriptor;
- if (descriptorPtr != 0) {
- descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- };
- }
- const renderBundle = renderBundleEncoder.finish(descriptor);
- return this.renderBundles.create(renderBundle);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} markerLabelPtr
- */
- wgpuRenderBundleEncoderInsertDebugMarker: (renderBundleEncoderIdx, markerLabelPtr) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- this.assert(markerLabelPtr != 0);
- const markerLabel = this.mem.loadCstring(markerLabelPtr);
- renderBundleEncoder.insertDebugMarker(markerLabel);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- */
- wgpuRenderBundleEncoderPopDebugGroup: (renderBundleEncoderIdx) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- renderBundleEncoder.popDebugGroup();
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} groupLabelPtr
- */
- wgpuRenderBundleEncoderPushDebugGroup: (renderBundleEncoderIdx, groupLabelPtr) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- this.assert(groupLabelPtr!= 0);
- const groupLabel = this.mem.loadCstring(groupLabelPtr);
- renderBundleEncoder.pushDebugGroup(groupLabel);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} groupIndex
- * @param {0|number} groupIdx
- * @param {number|BigInt} dynamicOffsetCount
- * @param {number} dynamicOffsetsPtr
- */
- wgpuRenderBundleEncoderSetBindGroup: (renderBundleEncoderIdx, groupIndex, groupIdx, dynamicOffsetCount, dynamicOffsetsPtr) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- let group;
- if (groupIdx > 0) {
- group = this.bindGroups.get(groupIdx);
- }
- dynamicOffsetCount = this.unwrapBigInt(dynamicOffsetCount);
- const dynamicOffsets = this.array(dynamicOffsetCount, dynamicOffsetsPtr, this.mem.loadU32, 4);
- renderBundleEncoder.setBindGroup(groupIndex, group, dynamicOffsets);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} bufferIdx
- * @param {number} formatInt
- * @param {BigInt} offset
- * @param {BigInt} size
- */
- wgpuRenderBundleEncoderSetIndexBuffer: (renderBundleEncoderIdx, bufferIdx, formatInt, offset, size) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- const buffer = this.buffers.get(bufferIdx);
- const format = this.enums.IndexFormat[formatInt];
- offset = this.unwrapBigInt(offset);
- size = this.unwrapBigInt(size);
- renderBundleEncoder.setIndexBuffer(buffer.buffer, format, offset, size);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} pipelineIdx
- */
- wgpuRenderBundleEncoderSetPipeline: (renderBundleEncoderIdx, pipelineIdx) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- const pipeline = this.renderPipelines.get(pipelineIdx);
- renderBundleEncoder.setPipeline(pipeline);
- },
- /**
- * @param {number} renderBundleEncoderIdx
- * @param {number} slot
- * @param {0|number} bufferIdx
- * @param {BigInt} offset
- * @param {BigInt} size
- */
- wgpuRenderBundleEncoderSetVertexBuffer: (renderBundleEncoderIdx, slot, bufferIdx, offset, size) => {
- const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
- let buffer;
- if (bufferIdx > 0) {
- buffer = this.buffers.get(bufferIdx).buffer;
- }
- offset = this.unwrapBigInt(offset);
- size = this.unwrapBigInt(size);
- renderBundleEncoder.setVertexBuffer(slot, buffer, offset, size);
- },
- ...this.renderBundleEncoders.interface(true),
- /* ---------------------- RenderPassEncoder ---------------------- */
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} queryIndex
- */
- wgpuRenderPassEncoderBeginOcclusionQuery: (renderPassEncoderIdx, queryIndex) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.beginOcclusionQuery(queryIndex);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} vertexCount
- * @param {number} instanceCount
- * @param {number} firstVertex
- * @param {number} firstInstance
- */
- wgpuRenderPassEncoderDraw: (renderPassEncoderIdx, vertexCount, instanceCount, firstVertex, firstInstance) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.draw(vertexCount, instanceCount, firstVertex, firstInstance);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} indexCount
- * @param {number} instanceCount
- * @param {number} firstIndex
- * @param {number} baseVertex
- * @param {number} firstInstance
- */
- wgpuRenderPassEncoderDrawIndexed: (renderPassEncoderIdx, indexCount, instanceCount, firstIndex, baseVertex, firstInstance) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} indirectBufferIdx
- * @param {BigInt} indirectOffset
- */
- wgpuRenderPassEncoderDrawIndexedIndirect: (renderPassEncoderIdx, indirectBufferIdx, indirectOffset) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- const buffer = this.buffers.get(indirectBufferIdx);
- indirectOffset = this.unwrapBigInt(indirectOffset);
- renderPassEncoder.drawIndexedIndirect(buffer.buffer, indirectOffset);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} indirectBufferIdx
- * @param {BigInt} indirectOffset
- */
- wgpuRenderPassEncoderDrawIndirect: (renderPassEncoderIdx, indirectBufferIdx, indirectOffset) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- const buffer = this.buffers.get(indirectBufferIdx);
- indirectOffset = this.unwrapBigInt(indirectOffset);
- renderPassEncoder.drawIndirect(buffer.buffer, indirectOffset);
- },
- /**
- * @param {number} renderPassEncoderIdx
- */
- wgpuRenderPassEncoderEnd: (renderPassEncoderIdx) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.end();
- },
- /**
- * @param {number} renderPassEncoderIdx
- */
- wgpuRenderPassEncoderEndOcclusionQuery: (renderPassEncoderIdx) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.endOcclusionQuery();
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number|BigInt} bundleCount
- * @param {number} bundlesPtr
- */
- wgpuRenderPassEncoderExecuteBundles: (renderPassEncoderIdx, bundleCount, bundlesPtr) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- bundleCount = this.unwrapBigInt(bundleCount);
- const bundles = this.array(
- bundleCount,
- bundlesPtr,
- (ptr) => this.renderBundles.get(this.mem.loadPtr(ptr)),
- 4,
- );
- renderPassEncoder.executeBundles(bundles);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} markerLabelPtr
- */
- wgpuRenderPassEncoderInsertDebugMarker: (renderPassEncoderIdx, markerLabelPtr) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- const markerLabel = this.mem.loadCstring(markerLabelPtr);
- renderPassEncoder.insertDebugMarker(markerLabel);
- },
- /**
- * @param {number} renderPassEncoderIdx
- */
- wgpuRenderPassEncoderPopDebugGroup: (renderPassEncoderIdx) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.popDebugGroup();
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} groupLabelPtr
- */
- wgpuRenderPassEncoderPushDebugGroup: (renderPassEncoderIdx, groupLabelPtr) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- const groupLabel = this.mem.loadCstring(groupLabelPtr);
- renderPassEncoder.pushDebugGroup(groupLabel);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} groupIndex
- * @param {0|number} groupIdx
- * @param {number|BigInt} dynamicOffsetCount
- * @param {number} dynamicOffsetsPtr
- */
- wgpuRenderPassEncoderSetBindGroup: (renderPassEncoderIdx, groupIndex, groupIdx, dynamicOffsetCount, dynamicOffsetsPtr) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- let group;
- if (groupIdx > 0) {
- group = this.bindGroups.get(groupIdx);
- }
- dynamicOffsetCount = this.unwrapBigInt(dynamicOffsetCount);
- const dynamicOffsets = this.array(dynamicOffsetCount, dynamicOffsetsPtr, this.mem.loadU32, 4);
- renderPassEncoder.setBindGroup(groupIndex, group, dynamicOffsets);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} bufferIdx
- * @param {number} formatInt
- * @param {BigInt} offset
- * @param {BigInt} size
- */
- wgpuRenderPassEncoderSetIndexBuffer: (renderPassEncoderIdx, bufferIdx, formatInt, offset, size) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- const buffer = this.buffers.get(bufferIdx);
- const format = this.enums.IndexFormat[formatInt];
- offset = this.unwrapBigInt(offset);
- size = this.unwrapBigInt(size);
- renderPassEncoder.setIndexBuffer(buffer.buffer, format, offset, size);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} pipelineIdx
- */
- wgpuRenderPassEncoderSetPipeline: (renderPassEncoderIdx, pipelineIdx) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- const pipeline = this.renderPipelines.get(pipelineIdx);
- renderPassEncoder.setPipeline(pipeline);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} x
- * @param {number} y
- * @param {number} width
- * @param {number} height
- */
- wgpuRenderPassEncoderSetScissorRect: (renderPassEncoderIdx, x, y, width, height) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.setScissorRect(x, y, width, height);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} reference
- */
- wgpuRenderPassEncoderSetStencilReference: (renderPassEncoderIdx, reference) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.setStencilReference(reference);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} slot
- * @param {0|number} bufferIdx
- * @param {BigInt} offset
- * @param {BigInt} size
- */
- wgpuRenderPassEncoderSetVertexBuffer: (renderPassEncoderIdx, slot, bufferIdx, offset, size) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- let buffer;
- if (bufferIdx > 0) {
- buffer = this.buffers.get(bufferIdx).buffer;
- }
- offset = this.unwrapBigInt(offset);
- size = this.unwrapBigInt(size);
- renderPassEncoder.setVertexBuffer(slot, buffer, offset, size);
- },
- /**
- * @param {number} renderPassEncoderIdx
- * @param {number} x
- * @param {number} y
- * @param {number} width
- * @param {number} height
- * @param {number} minDepth
- * @param {number} maxDepth
- */
- wgpuRenderPassEncoderSetViewport: (renderPassEncoderIdx, x, y, width, height, minDepth, maxDepth) => {
- const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
- renderPassEncoder.setViewport(x, y, width, height, minDepth, maxDepth);
- },
- ...this.renderPassEncoders.interface(true),
- /* ---------------------- RenderPipeline ---------------------- */
- /**
- * @param {number} renderPipelineIdx
- * @param {number} groupIndex
- * @returns {number}
- */
- wgpuRenderPipelineGetBindGroupLayout: (renderPipelineIdx, groupIndex) => {
- const renderPipeline = this.renderPipelines.get(renderPipelineIdx);
- const bindGroupLayout = renderPipeline.getBindGroupLayout(groupIndex);
- return this.bindGroupLayouts.create(bindGroupLayout);
- },
- ...this.renderPipelines.interface(true),
- /* ---------------------- Sampler ---------------------- */
- ...this.samplers.interface(true),
- /* ---------------------- ShaderModule ---------------------- */
- /**
- * @param {number} shaderModuleIdx
- * @param {number} callbackPtr
- * @param {number} userdata
- */
- wgpuShaderModuleGetCompilationInfo: async (shaderModuleIdx, callbackPtr, userdata) => {
- const shaderModule = this.shaderModules.get(shaderModuleIdx);
- const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
- let status = 0;
- let retAddr = 0;
- const ptrsToFree = [];
- try {
- const compilationInfo = await shaderModule.getCompilationInfo();
- const size = compilationInfo.messages.length * 72;
- const addr = this.mem.exports.wgpu_alloc(size);
- ptrsToFree.push(addr);
- compilationInfo.messages.forEach((message, i) => {
- const messageLength = new TextEncoder().encode(message.message).length;
- const messageAddr = this.mem.exports.wgpu_alloc(messageLength);
- ptrsToFree.push(messageAddr);
- this.mem.storeString(messageAddr, message.message);
- this.mem.storeI32(addr + (i * size) + 4);
- this.mem.storeI32(addr + (i * size) + 8, this.enums.CompilationMessageType.indexOf(message.type));
- this.mem.storeU64(addr + (i * size) + 16, message.lineNum);
- this.mem.storeU64(addr + (i * size) + 24, message.linePos);
- this.mem.storeU64(addr + (i * size) + 32, message.offset);
- this.mem.storeU64(addr + (i * size) + 40, message.length);
- // TODO: UTF16 units.
- this.mem.storeU64(addr + (i * size) + 48, message.linePos);
- this.mem.storeU64(addr + (i * size) + 56, message.offset);
- this.mem.storeU64(addr + (i * size) + 64, message.length);
- });
- retAddr = this.mem.exports.wgpu_alloc(3*this.mem.intSize);
- ptrsToFree.push(retAddr);
- this.mem.storeUint(retAddr + this.mem.intSize, compilationInfo.messages.length);
- this.mem.storeI32(retAddr + this.mem.intSize*2, addr);
- } catch (e) {
- console.warn(e);
- status = 1;
- }
- callback(status, retAddr, userdata);
- ptrsToFree.forEach(ptr => this.mem.exports.wgpu_free(ptr));
- },
- ...this.shaderModules.interface(true),
- /* ---------------------- Surface ---------------------- */
- /**
- * @param {number} surfaceIdx
- * @param {number} configPtr
- */
- wgpuSurfaceConfigure: (surfaceIdx, configPtr) => {
- const surface = this.surfaces.get(surfaceIdx);
- const context = surface.getContext('webgpu');
- const widthOff = 16 + this.mem.intSize + 8;
- surface.width = this.mem.loadU32(configPtr + widthOff);
- surface.height = this.mem.loadU32(configPtr + widthOff + 4);
- /** @type {GPUCanvasConfiguration} */
- const config = {
- device: this.devices.get(this.mem.loadPtr(configPtr + 4)),
- format: this.enumeration("TextureFormat", configPtr + 8),
- usage: this.mem.loadU32(configPtr + 12),
- viewFormats: this.array(
- this.mem.loadUint(configPtr + 16),
- this.mem.loadPtr(configPtr + 16 + this.mem.intSize),
- (ptr) => this.enumeration("TextureFormat", ptr),
- 4,
- ),
- alphaMode: this.enumeration("CompositeAlphaMode", configPtr + widthOff - 4),
- // // NOTE: present mode seems unused.
- presentMode: this.enumeration("PresentMode", configPtr + widthOff + 4),
- };
- context.configure(config);
- },
- /**
- * @param {number} surfaceIdx
- * @param {number} adapterIdx
- * @param {number} capabilitiesPtr
- */
- wgpuSurfaceGetCapabilities: (surfaceIdx, adapterIdx, capabilitiesPtr) => {
- const formatStr = navigator.gpu.getPreferredCanvasFormat();
- const format = this.enums.TextureFormat.indexOf(formatStr);
- this.mem.storeUint(capabilitiesPtr + 8, 1);
- const formatAddr = this.mem.exports.wgpu_alloc(4);
- this.mem.storeI32(formatAddr, format);
- this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize, formatAddr);
- // NOTE: present modes don't seem to actually do anything in JS, we can just give back a default FIFO though.
- this.mem.storeUint(capabilitiesPtr + 8 + this.mem.intSize*2, 1);
- const presentModesAddr = this.mem.exports.wgpu_alloc(4);
- this.mem.storeI32(presentModesAddr, 0);
- this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize*3, presentModesAddr);
- // Browser seems to support opaque (1) and premultiplied (2).
- this.mem.storeUint(capabilitiesPtr + 8 + this.mem.intSize*4, 2);
- const alphaModesAddr = this.mem.exports.wgpu_alloc(8);
- this.mem.storeI32(alphaModesAddr + 0, 1); // Opaque.
- this.mem.storeI32(alphaModesAddr + 4, 2); // premultiplied.
- this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize*5, alphaModesAddr);
- },
- /**
- * @param {number} surfaceIdx
- * @param {number} texturePtr
- */
- wgpuSurfaceGetCurrentTexture: (surfaceIdx, texturePtr) => {
- const surface = this.surfaces.get(surfaceIdx);
- const context = surface.getContext('webgpu');
- const texture = context.getCurrentTexture();
- const textureIdx = this.textures.create(texture);
- this.mem.storeI32(texturePtr, textureIdx);
- // TODO: determine suboptimal and/or status.
- },
- /**
- * @param {number} surfaceIdx
- */
- wgpuSurfacePresent: (surfaceIdx) => {
- // NOTE: Not really anything to do here.
- },
- /**
- * @param {number} surfaceIdx
- */
- wgpuSurfaceUnconfigure: (surfaceIdx) => {
- const surface = this.surfaces.get(surfaceIdx);
- surface.getContext('webgpu').unconfigure();
- },
- ...this.surfaces.interface(true),
- /* ---------------------- SurfaceCapabilities ---------------------- */
- /**
- * @param {number} surfaceCapabilitiesPtr
- */
- wgpuSurfaceCapabilitiesFreeMembers: (surfaceCapabilitiesPtr) => {
- const formatsAddr = this.mem.loadI32(surfaceCapabilitiesPtr + this.mem.intSize*2);
- this.mem.exports.wgpu_free(formatsAddr);
- const presentModesAddr = this.mem.loadI32(surfaceCapabilitiesPtr + this.mem.intSize*4);
- this.mem.exports.wgpu_free(presentModesAddr);
- const alphaModesAddr = this.mem.loadI32(surfaceCapabilitiesPtr + this.mem.intSize*6);
- this.mem.exports.wgpu_free(alphaModesAddr);
- },
- /* ---------------------- Texture ---------------------- */
-
- /**
- * @param {number} textureIdx
- * @param {0|number} descriptorPtr
- * @returns {number}
- */
- wgpuTextureCreateView: (textureIdx, descriptorPtr) => {
- const texture = this.textures.get(textureIdx);
- /** @type {?GPUTextureViewDescriptor} */
- let descriptor;
- if (descriptorPtr != 0) {
- descriptor = {
- label: this.mem.loadCstring(descriptorPtr + 4),
- format: this.enumeration("TextureFormat", descriptorPtr + 8),
- dimension: this.enumeration("TextureViewDimension", descriptorPtr + 12),
- baseMipLevel: this.mem.loadU32(descriptorPtr + 16),
- mipLevelCount: this.mem.loadU32(descriptorPtr + 20),
- baseArrayLayer: this.mem.loadU32(descriptorPtr + 24),
- arrayLayerCount: this.mem.loadU32(descriptorPtr + 28),
- aspect: this.enumeration("TextureAspect", descriptorPtr + 32),
- };
- if (descriptor.arrayLayerCount == 0xFFFFFFFF) {
- descriptor.arrayLayerCount = undefined;
- }
- if (descriptor.mipLevelCount == 0xFFFFFFFF) {
- descriptor.mipLevelCount = undefined;
- }
- }
- const textureView = texture.createView(descriptor);
- return this.textureViews.create(textureView);
- },
- /**
- * @param {number} textureIdx
- */
- wgpuTextureDestroy: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- texture.destroy();
- },
- /**
- * @param {number} textureIdx
- * @returns {number}
- */
- wgpuTextureDepthOrArrayLayers: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- return texture.depthOrArrayLayers;
- },
- /**
- * @param {number} textureIdx
- * @returns {number}
- */
- wgpuTextureGetDimension: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- return this.enums.TextureDimension.indexOf(texture.dimension);
- },
- /**
- * @param {number} textureIdx
- * @returns {number}
- */
- wgpuTextureGetFormat: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- return this.enums.TextureFormat.indexOf(texture.format);
- },
- /**
- * @param {number} textureIdx
- * @returns {number}
- */
- wgpuTextureGetHeight: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- return texture.height;
- },
- /**
- * @param {number} textureIdx
- * @returns {number}
- */
- wgpuTextureGetMipLevelCount: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- return texture.mipLevelCount;
- },
- /**
- * @param {number} textureIdx
- * @returns {number}
- */
- wgpuTextureGetSampleCount: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- return texture.sampleCount;
- },
- /**
- * @param {number} textureIdx
- * @returns {number}
- */
- wgpuTextureGetUsage: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- return texture.usage;
- },
- /**
- * @param {number} textureIdx
- * @returns {number}
- */
- wgpuTextureGetWidth: (textureIdx) => {
- const texture = this.textures.get(textureIdx);
- return texture.width;
- },
- ...this.textures.interface(true),
- /* ---------------------- TextureView ---------------------- */
- ...this.textureViews.interface(true),
- };
- }
- }
- /** @template T */
- class WebGPUObjectManager {
- /**
- * @param {string} name
- * @param {WasmMemoryInterface} mem
- */
- constructor(name, mem) {
- this.name = name;
- this.mem = mem;
- this.idx = 0;
- /** @type {Record<number, { references: number, object: T }>} */
- this.objects = {};
- }
- /**
- * @param {T} object
- * @returns {number}
- */
- create(object) {
- this.objects[this.idx] = { references: 1, object };
- this.idx += 1;
- return this.idx;
- }
- /**
- * @param {number} idx
- * @returns {T}
- */
- get(idx) {
- return this.objects[idx-1].object;
- }
- /** @param {number} idx */
- release(idx) {
- this.objects[idx-1].references -= 1;
- if (this.objects[idx-1].references == 0) {
- delete this.objects[idx-1];
- }
- }
- /** @param {number} idx */
- reference(idx) {
- this.objects[idx-1].references += 1;
- }
-
- interface(withLabelSetter = false) {
- const inter = {};
- inter[`wgpu${this.name}Reference`] = this.reference.bind(this);
- inter[`wgpu${this.name}Release`] = this.release.bind(this);
- if (withLabelSetter) {
- inter[`wgpu${this.name}SetLabel`] = (idx, labelPtr) => {
- const obj = this.get(idx);
- obj.label = this.mem.loadCstring(labelPtr);
- };
- }
- return inter;
- }
- }
- window.odin = window.odin || {};
- window.odin.WebGPUInterface = WebGPUInterface;
- })();
|