{"id":34524801,"url":"https://github.com/devsh-graphics-programming/gpu-with-c-sharp-angular-wasm","last_synced_at":"2026-05-24T23:03:10.521Z","repository":{"id":42327906,"uuid":"510677787","full_name":"Devsh-Graphics-Programming/GPU-With-C-Sharp-Angular-WASM","owner":"Devsh-Graphics-Programming","description":null,"archived":false,"fork":false,"pushed_at":"2023-01-29T22:22:37.000Z","size":2971,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-25T16:28:35.719Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Devsh-Graphics-Programming.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-05T09:53:28.000Z","updated_at":"2022-07-29T13:07:22.000Z","dependencies_parsed_at":"2023-02-16T01:31:31.709Z","dependency_job_id":null,"html_url":"https://github.com/Devsh-Graphics-Programming/GPU-With-C-Sharp-Angular-WASM","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Devsh-Graphics-Programming/GPU-With-C-Sharp-Angular-WASM","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devsh-Graphics-Programming%2FGPU-With-C-Sharp-Angular-WASM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devsh-Graphics-Programming%2FGPU-With-C-Sharp-Angular-WASM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devsh-Graphics-Programming%2FGPU-With-C-Sharp-Angular-WASM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devsh-Graphics-Programming%2FGPU-With-C-Sharp-Angular-WASM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Devsh-Graphics-Programming","download_url":"https://codeload.github.com/Devsh-Graphics-Programming/GPU-With-C-Sharp-Angular-WASM/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devsh-Graphics-Programming%2FGPU-With-C-Sharp-Angular-WASM/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33453557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-24T19:21:36.376Z","status":"ssl_error","status_checked_at":"2026-05-24T19:21:10.562Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-24T05:06:43.834Z","updated_at":"2026-05-24T23:03:10.515Z","avatar_url":"https://github.com/Devsh-Graphics-Programming.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GPU-With-C-Sharp-Angular-WASM\n\n![Emscripten in chrome](./Docs/img3.jpg)\n\nWe developed a  proof of concept of a WebAssembly application to answer the question:\n\n## Is it possible to mix languages such as C# and C++ on the web with the current tools?\n\n----------------------------\n\n## TL;DR Yes it is possible but you'll never escape C++\n\nBasically bindings to WebGL (likewise for WebGPU) and any other WebAPI usually accessible from JavaScript are absent from WebAssembly and are provided by Emscripten's curated mix of C and C++ headers with JavaScript glue code in its library.\n\nIf you need a refresher or an explanation why that is the case, please refer to our detailed explanation here:\u003cbr\u003e\nhttps://github.com/Devsh-Graphics-Programming/JS-WASM-interop-benchmark#how-the-browser-wasm-runtime-works-and-its-limits\n\nAny further C# bindings you might use would simply be nice wrappers around a set of P/Invokes into Emscripten's WASM main module or JS library.\n\n### Are there any alternatives to WASM, short of rewriting your C++ or C# codebase to TypeScript or JavaScript?\n\nNot really, unless you count Emscripten's `asm.js` which cross compiles C++ to JavaScript as an option, which is bound to get far less attention and maintenance going forward than the WASM backend.\n\n#### PRO: Only WASM will give you support for a true 64bit target (8 byte pointers, eventually)\n\nJavaScript does not have a native 64bit integer type, while WASM has the `memory64` WASM proposal.\n\nFor now Emscripten has the `sMEMORY64=2` option which will emulate 64bit by casting 32bit WASM memory addresses, which is harmless since upper half of the address is always zero.\n\n**This makes it significantly easier and less stressful to port existing C++ and C# codebases which may have made assumptions about 64bit architecture being targetted**.\n\n#### PRO: Eventually the amount of JavaScript glue code emitted by Emscripten will shrink\n\nThis is because:\n1. Most C-APIs (like `malloc`) were already implemented in JavaScript for `asm.js` and work perfectly, so a C implementation compiled WASM will happen eventually but is low priority\n2. [Direct WebAPI calls from WASM are being considered, but are delayed due to contingency on WASM being JavaScript Garbage Collector aware](https://github.com/WebAssembly/spec/issues/1221#issuecomment-671549664)\n3. [JS to C/C++ function call overheads are small, but not negligible, so there's an incentive to cull them](https://github.com/Devsh-Graphics-Programming/JS-WASM-interop-benchmark#c-and-c-function-invocation-overheads)\n\n#### CON: The only reason to avoid WASM is to be able to reclaim memory\n\nThe WASM browser runtime can only grow a single WASM Module's heaps, it can't release memory back to the OS, this is both because of security and because of WASM virtual machine's unified address space which apparently has no virtualization.\n\n[As discussed here](https://github.com/WebAssembly/design/issues/1397) it could be a problem for applications that experience very large memory spikes.\n\n#### CON: WASM DWARF Debug Symbols save absolute paths to sourcecode (only affects C/C++)\n\nThis makes debug builds non-portable across machines, we even tried \"patching\" DWARFs by finding and modiying file paths in a file containing separated binary DWARF info. However the DWARF format is offset based, so changing the length of the path was not an option, while padding the strings with null characters messed with concatenation.\n\nThe solution is to find or develop some DWARF editing script or library that lets us modify these files properly.\n\n_We'd like to highlight that Android NDK is also plagued by a similar issue of not being able to debug a C++ project on a machine that has not built it, so we consider this a minor nuisance._\n\n### Downsides of using any C# as opposed to pure C++\n\n#### Blazor and Mono-WASM are buggy, compromise on performance and are missing features\n\nSee the issues we've opened during our development:\n- Lack of documentation of available features https://github.com/dotnet/aspnetcore/issues/42850\n- Probable lack of Native-style threading support https://github.com/dotnet/aspnetcore/issues/42851\n- The way Blazor uses Emscripten is shabby https://github.com/dotnet/runtime/issues/75257 https://github.com/dotnet/runtime/issues/75345\n- performance regression in C# to JS argument passing speed https://github.com/dotnet/aspnetcore/issues/38510\n- Abysmal JS to C# argument passing speed, function call and memory usage overhead https://github.com/dotnet/aspnetcore/issues/44088\n\n#### Being forced into the Razor pages bloat\n\nThere's no standalone Mono-WASM toolchain for producing \"simple\" WASM+JS Libraries for later linkage, as you would desire, if you didn't want Blazor to be in charge of your website layout or UI framework.\n\nIn order to extract your C# code AOT compiled into a `dotnet.wasm` and `dotnet.js` for later usage you have to produce a full Blazor website with `wwwroot`, CSS, `index.html`, etc. as well as publish it, as AOT is only performed upon publish. Until then your C# code stays as a DLL to be interpreted by the runtime.\n\nIn reality, because of the need to launch and debug the code from VS2022, you would be copying your entire website (any JS or TS) to `wwwroot` to facilitate 1-click launch and debug.\n\nFuthermore this means that there can only be one C# WASM module, you cannot have separate C# `DLL`s which can be linked into a single WASM main module. You could in theory use multiple separate WASM main modules in a single JS script, but whether the JS glue code accompanying each main module won't complain is a separate issue. \n\n#### Blazor or Mono-WASM toolchain scripts for adding `NativeFileReference`s break dynamic linking of WASM sidemodules\n\nDynamic Linking of WASM modules is useful for decreasing waiting time for page load and only fetching the modules that are needed to perform a task.\n\nAlso this would allow us to compile C++ or C WASM modules with an Emscripten version of our choice rather than the one that is shipped with Blazor, which would help to work around Blazor toolchain issues [such as the compiler hanging if its not ran as Admin](https://github.com/dotnet/runtime/issues/75345).\n\n#### VS2022 provides no single Debugger that can deal with a mixed C#, C++/C, TypeScript and JavaScript callstack\n\nNaturally as the Chrome Dev Tools Debugger is oblivious to the .Net Runtime it has no information about C# functions and variables, even when the program was built with AoT. However with the DWARF debugging extension it can offer a C++ and C debugging experience on par with any IDE's debugger, with the additional bonus of being able to debug a mixed JavaScript and DWARF stack.\n\nThe VS2022 Debugger for Emscripten Targets supports mixed language callstacks with watches, breakpoints, etc. if the correct DWARF extensions and options are enabled in the Chrome instance it connects to. However this does not get used when debugging a Blazor Target project.\n\nThe Blazor Target debugger only supports mixes stacks of C#, TypeScript and JavaScript, where any part of the callstack in C or C++ shows up as pure unannotated WASM.\n\nThis leads to an awkward situation where VS2022 has two debuggers that can debug C++ and JS or C# and JS but not both at the same time, which is mildly annoying.\n\nThe solution is to have the Chrome Dev Tools Debugger open simultaneously in the chrome tab started by the VS2022 Debugger, which works most of the time but can interfere with each other with regards to breakpoint hitting and stepping.\n\n### Pros of Blazor\n\nUsing other .NET dependencies is extremely easy. Because the entire .NET runtime is shipped with Blazor wasm, it's possible to load and use C# libraries without any extra effort compared to a native .NET app.  \n\n----------------------------\n\n## Project and Report Structure\n\nThis repository contains our findings on the intricacies of having each language compiled compiling, debugging to WebAssembly and maintaining its codebase. \n\nEach variant renders the ame interactive pathtraced scene using the same shader code. The source for `./data/shader.frag` is [stochastic pathtracer v1 on shadertoy](https://www.shadertoy.com/view/4ddcRn). Minor adapatations were made to run it outside of ShaderToy.\n\n\n### Application Controls\n\n - Use `1, 2, 3, 4, 5` on the alphanumerical keyboard to switch background.\n - The fifth background is a cubemap, that can be toggled between two variants by repeatedly pressing the `5` key.\n - Click and drag with the mouse butons mouse on screen to change the position of a camera.\n\nThe apps were created in this order (CI deployed builds on GH static pages are hyperlinked):\n1. Native\n2. [EmscriptenGLFW](https://devsh-graphics-programming.github.io/GPU-With-C-Sharp-Angular-WASM/EmscriptenGLFW/build/WASM-Release/EmscriptenGLFW.html)\n3. [EmscriptenHTML5](https://devsh-graphics-programming.github.io/GPU-With-C-Sharp-Angular-WASM/EmscriptenGLFW/build/WASM-Release/EmscriptenHTML5.html)\n4. EmscriptenHTML5SeparateLibs\n5. NativeCSharp\n6. [BlazorEmscripten](https://devsh-graphics-programming.github.io/GPU-With-C-Sharp-Angular-WASM/BlazorEmscripten)\n7. [TBD] Emscripten in AngularJS\n  \nAnd thus the notes are a followup of the previous chapters.\n\n----------------------------\n\n## Set-up\n\n### Required Tools\n\n#### Git\n\nNeed a command line client with a configured SSH key for GitHub (otherwise you cannot checkout submodules recursively).\n\n#### Visual Studio 2022\n\nInstall the following Visual Studio 2022 workloads:\n- Desktop Development with C++\n- ASP.Net and WebDevelopment \n\nAnd components:\n- Emscripten Build Target\n- .NET WebAssembly build tools\n\n#### Chrome WASM C/C++ Devtools Extension\n\nYou wil need an extension for Chrome to be able to debug C++ code with dwarf debug symbols.\n\nThe DWARF format contains source mapping to files on a local machine that compiled the app (absolute filepaths). It allows placing breakpoints and watches in source code as well as inspecting unmangled local variables. \n\nhttps://chrome.google.com/webstore/detail/cc%20%20-devtools-support-dwa/pdcpmagijalfljmkmjngeonclgbbannb\n\n_Note: Other debug symbol formats and compile options do not work as well, and will result in missing function and variable names as WASM simply enumerates all symbols and uses their indexes in place of names. This is why you need DWARF._\n\n#### Emscripten (TODO: Remove, make all targets use VS2022 solutions)\n\n*EmscriptenGLFW, EmscriptenHTML5, EmscriptenHTML5SeparateLibs*\n\nInstead of the standard C++ and C# compiler, the apps in this repository use Emscripten.\n\nTo install, clone the repository somewhere on your machine:\n\n```\ngit clone https://github.com/emscripten-core/emsdk.git\n\ncd emsdk\n```\n\nRun the following emsdk commands to get the latest tools from GitHub and set them as active:\n```\n# Download and install the latest SDK tools.\n./emsdk install latest\n\n# Make the \"latest\" SDK \"active\" for the current user. (writes .emscripten file)\n./emsdk activate latest --permanent\n\n# Activate PATH and other environment variables in the current terminal\nsource ./emsdk_env.sh\n```\n\nInstruction on how to install Emscripten can be found on the [official site](https://emscripten.org/docs/getting_started/downloads.html).\n\nThen, add an extra environment variable **EMSCRIPTEN**  with value `path-to-emsdk/upstream/emscripten`. We use i\n\nOnce thats done and all the environment variables are assigned *(with --permament option)* you can proceed.\n\nDespite this, Blazor Wasm will clone its own fork of `git@github.com:emscripten-core/emscripten.git` to `C:\\Program Files\\dotnet\\packs\\Microsoft.NET.Runtime.Emscripten.2.0.23.Sdk.win-x64\\6.0.4\\tools\\emscripten\\` and be adamant on using that to compile the C++ portions of *BlazorEmscripten* hybrid app.\n\n#### SWIG (TODO: Remove, just add swigwin binary to 3rdparty and don't add it to PATH)\n\n*BlazorEmscripten only*\n\nHybrid apps require a language bridge. We use SWIG to generate platform invokes and native class equvalents in C# (and C-API function wrappers) for C++ public methods and fields in the C++ part of the app.\n\nGo to [SWIG download page](https://www.swig.org/download.html) and get the latest **swigwin** version (swigwin contains swig.exe and allows us to skip building on windows).\n\nExtract the zip archive.\n\nAdd the extracted dir to PATH. \n\n### Obtain source\n\nClone this repository recursively (needed for dependency submodules).\n\n```\ngit clone https://github.com/Devsh-Graphics-Programming/GPU-With-C-Sharp-Angular-WASM.git --recurse-submodules \n```\n\n### Configuring and Building\n\nSimply open each example's `.sln` file in their folder and build.\n\nTODO: Change all targets to use Visual Studio solutions instead of CMake.\n\nBefore the TODO is done, for details check each example's Readme\n\n### Running\n\nCan be ran using the Visual Studio's Debug option (TODO: remove `run.py`).\n\nOtherwise a webserver like the one provied by emrun need to be started with the correct root directory equal to the repository root and one needs to manually navigate to the example build's `index.html`.\n\nCaveats:\n- The examples use a fragment shader located in a relative path at `../../data/shader.frag`\n- Similarly, ithey uses cube maps located in a relative path `../../data/env/`\nTherefore, carelessly moving the exectuable, `.js` or `.html` will break the app.\n\n### CPU Debugging\n\nDebugging WASM with watches, breakpoints and original variable and function names is only possible on Chromium-based browsers.\n\nC/C++ can be debugged either via the built-in Chrome Developer Tools with the DWARF Extension, or using a tool which understands the Chrome Remote Debug Protocol and connects to an instance of Chrome which was started with the RDP listening port argument.\n\nOne of such tools is VS2022 itself when debugging Emscripten Target or Blazor Target projects.\n\n#### C/C++ and JavaScript\n\nThe Chrome Developer Tools will show you JavaScript and WASM C/C++ function calls in a unified stack, you will be able to defined watches, place breakpoints and perform stepping in both languages.\n\nYou can also use VS2022 as the Debugger.\n\n##### MAKE SURE TO ENABLE: The Chrome DWARF experimental option\n\nIn order for the aforementioned extension to work an extra option needs to be enabled in the browser:\n1. Open Chrome,\n2. Open Developer Tools (Ctrl + Shift + i) \n3. Open Options (F1)\n![Options](./Docs/img1.jpg)\n4. Go to Experiments \n5. Enable WebAssembly Debugging: Enable DWARF Support\n![DWARF support](./Docs/img2.jpg)\n\n##### MAKE SURE TO ENABLE THIS OPTION ON THE DEFAULT SIGNED OUT PROFILE\n\nWe had an issue where VS2022 was starting its own instance of Chrome listening to a remote debug port, and this instance is started without a user being signed in. As a consequence a lot of time was spent chasing a \"Blazor loses DWARF info when linking Native File Dependencies\" phantom bug.\n\n**!!! This means that if you downloaded and enabled the DWARF Debugging extension while signed into your own profile, you need to do it again from the Chrome instance that Visual Studio starts when debugging !!!**\n\n#### C#, TypeScript and Java Script\n\nYou need to use the VS2022 Debugger, otherwise you will only be able to debug JS code as the C# will show up as a bunch of unannotated WASM.\n\nUnfortunately the Blazor Target debugger does not incorporate the Emscripten Target debugger so if you want to debug C++ you need to do it from within Chrome itself (make sure to enable DWARF debugging).\n\nWe presume the reason is that the VS2022 Emscripten debugger is built off the existing Visual C++ Debugger to remote Linux GDB bridge, as we've found an existing project of a GDB to CRD bridge used for chaining to Visual Studio's GDB. Meanwhile the VS2022 Blazor debugger seems to be an extended TypeScript Debugger.\n\n### GPU Debugging with RenderDoc (TODO: explain everything)\n\nTODO\n\n----------------------------\n\n# License\n\nSee License.md\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevsh-graphics-programming%2Fgpu-with-c-sharp-angular-wasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevsh-graphics-programming%2Fgpu-with-c-sharp-angular-wasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevsh-graphics-programming%2Fgpu-with-c-sharp-angular-wasm/lists"}