Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Websys #444

Merged
merged 34 commits into from
Dec 26, 2020
Merged

Websys #444

merged 34 commits into from
Dec 26, 2020

Conversation

iceiix
Copy link
Owner

@iceiix iceiix commented Dec 26, 2020

Now that graphics are implemented on top of glow (#262), support using WebGL through glow

Replace context creation through glutin with glow, when running on the web (keep using glutin for native). This fixes #171 failed to resolve: could not find Context in platform_impl

Replace stdweb with web-sys, since stdweb is unsupported and web-sys is more complete. Remove the std_or_web wrapper and localstoragefs because they depend on stdweb, will need to be rethought.

This does not complete the web port (still doesn't run), but it gets closer

…he glutin window, the only event which does this
…UniformLocation doesn't so gl::Uniform can't
@iceiix
Copy link
Owner Author

iceiix commented Dec 26, 2020

cargo web start --target wasm32-unknown-unknown now successfully compiles, while retaining native compatibility, but it fails to run:

[Log] Error loading Rust wasm module 'stevenarella': (stevenarella.js, line 46)
TypeError: import __wbindgen_placeholder__:__wbindgen_object_drop_ref must be an object
[Error] Unhandled Promise Rejection: TypeError: import __wbindgen_placeholder__:__wbindgen_object_drop_ref must be an object
	(anonymous function) (stevenarella.js:47)
	promiseReactionJob

I think I'm missing a step. Lots of different ways to do this, in flux. The example at https://github.com/grovesNL/glow/tree/main/examples/hello says to run with:

cargo build --target wasm32-unknown-unknown
mkdir -p generated
wasm-bindgen ../../target/wasm32-unknown-unknown/debug/hello.wasm --out-dir generated --target web
cp index.html generated

This fails on the first step, with a different error (even though cargo web start succeeds):

rror: entry symbol `main` declared multiple times
   --> src/main.rs:222:9
    |
222 |         pub fn main() { main2(); }
    |         ^^^^^^^^^^^^^
    |
    = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead

error: aborting due to previous error; 41 warnings emitted

error: could not compile `stevenarella`

despite the cfg_if! on #[cfg(target_arch = "wasm32")]...and trying to add #[start] says it is experimental/unstable. Something different than building with cargo web start.

And I used to build with wasm-pack, but removed it in 472208c since cargo web start got further, time to revisit it? Errors previously seen: #171 (comment). No longer occur, wasm-pack build succeeds:

warning: 41 warnings emitted

    Finished release [optimized] target(s) in 1m 25s
[INFO]: ⬇️  Installing wasm-bindgen...
[INFO]: ✨   Done in 1m 27s
[INFO]: 📦   Your wasm pkg is ready to publish at ./pkg.

Guides:

@iceiix
Copy link
Owner Author

iceiix commented Dec 26, 2020

Screen Shot 2020-12-25 at 6 53 09 PM

        let mut file = BufWriter::new(fs::File::create("conf.cfg").unwrap());

conditionally-compiling out, next failure is in threading (but called from where?)

[Error] panicked at 'failed to spawn thread: Custom { kind: Other, error: "operation not supported on this platform" }', /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/thread/mod.rs:610:29

Stack:

__wbg_new_59cb74e423758ede
__wbg_new_59cb74e423758ede@http://localhost:8080/bootstrap.js:71:106
wasm-stub@[wasm code]
<?>.wasm-function[1018]@[wasm code]
<?>.wasm-function[3391]@[wasm code]
<?>.wasm-function[1841]@[wasm code]
<?>.wasm-function[2836]@[wasm code]
<?>.wasm-function[2856]@[wasm code]
<?>.wasm-function[2773]@[wasm code]
<?>.wasm-function[2857]@[wasm code]
<?>.wasm-function[2278]@[wasm code]
<?>.wasm-function[1150]@[wasm code]
<?>.wasm-function[218]@[wasm code]
<?>.wasm-function[203]@[wasm code]
<?>.wasm-function[3420]@[wasm code]
wasm-stub@[wasm code]
main@[native code]
eval code
eval@[native code]
./index.js@http://localhost:8080/0.bootstrap.js:34:5
__webpack_require__@http://localhost:8080/bootstrap.js:603:34
__webpack_require__@[native code]
promiseReactionJob@[native code]


	__wbg_error_4bb6c2a97407129a (stevenarella_bg.js:492)
	__wbg_error_4bb6c2a97407129a (bootstrap.js:77:109)
	wasm-stub
	<?>.wasm-function[1018]
	<?>.wasm-function[3391]
	<?>.wasm-function[1841]
	<?>.wasm-function[2836]
	<?>.wasm-function[2856]
	<?>.wasm-function[2773]
	<?>.wasm-function[2857]
	<?>.wasm-function[2278]
	<?>.wasm-function[1150]
	<?>.wasm-function[218]
	<?>.wasm-function[203]
	<?>.wasm-function[3420]
	wasm-stub
	main
	Eval Code (index.js:5)
	eval
	./index.js (0.bootstrap.js:34)
	__webpack_require__ (bootstrap.js:603)
	__webpack_require__
	promiseReactionJob

@iceiix
Copy link
Owner Author

iceiix commented Dec 26, 2020

Restoring std_or_web until there is something better, current failure:

Screen Shot 2020-12-26 at 9 45 54 AM

Panic error message: – "attempted to leave type webcore::serialization::SerializedValue uninitialized, which is invalid"
Panic location: – "/rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/mem/mod.rs:658"
[Error] Error importing index.js: – RuntimeError: Unreachable code should not be executed (evaluating 'pkg_stevenarella_bg_wasm__WEBPACK_IMPORTED_MODULE_0_"main"')

What is this core/src/mem/mod.rs:658? If this is the right version of the library, https://github.com/rust-lang/rust/blob/master/library/core/src/mem/mod.rs#L658:

pub unsafe fn uninitialized<T>() -> T {
    // SAFETY: the caller must guarantee that an unitialized value is valid for `T`.
    unsafe {
        intrinsics::assert_uninit_valid::<T>();
        MaybeUninit::uninit().assume_init()
    }

What is webcore::serialization::SerializedValue? Looks like it is in our old friend stdweb: https://docs.rs/stdweb/0.4.20/src/stdweb/webcore/value.rs.html

Building with wasm-pack build --dev confirms:

[Error] Panic error message: – "attempted to leave type `webcore::serialization::SerializedValue` uninitialized, which is invalid"
	__cargo_web_snippet_97495987af1720d8a9a923fa4683a7b683e3acd6 (inline626.js:3:103)
	(anonymous function) (stevenarella_bg.js:1403:153)
	(anonymous function) (stevenarella_bg.js:442)
	__wbg_cargowebsnippet97495987af1720d8a9a923fa4683a7b683e3acd6_a438202dc16f44c0 (bootstrap.js:572:159)
	wasm-stub
	<?>.wasm-function[stdweb::webcore::initialization::initialize::{{closure}}::snippet::__cargo_web_snippet_97495987af1720d8a9a923fa4683a7b683e3acd6::__cargo_web_snippet_97495987af1720d8a9a923fa4683a7b683e3acd6::h3dabe35974c7b3b2]
	<?>.wasm-function[stdweb::webcore::initialization::initialize::{{closure}}::snippet::__cargo_web_snippet_97495987af1720d8a9a923fa4683a7b683e3acd6::h3f9a9f88e54c64ed]
	<?>.wasm-function[stdweb::webcore::initialization::initialize::{{closure}}::snippet::h99e107659947e789]
	<?>.wasm-function[stdweb::webcore::initialization::initialize::{{closure}}::hed8770302786655d]
	<?>.wasm-function[std::panicking::rust_panic_with_hook::hc5713da015ebaa19]
	<?>.wasm-function[std::panicking::begin_panic_handler::{{closure}}::hc5eba7f0030e8f4f]
	<?>.wasm-function[std::sys_common::backtrace::__rust_end_short_backtrace::he811f0bd07938b42]
	<?>.wasm-function[rust_begin_unwind]
	<?>.wasm-function[core::panicking::panic_fmt::h775d5c012939dd41]
	<?>.wasm-function[core::panicking::panic::hf103660e9eaae571]
	<?>.wasm-function[<stdweb::webcore::serialization::SerializedValue as core::convert::From<stdweb::webcore::serialization::SerializedUntaggedReference>>::from::he6fa71027b6660de]
	<?>.wasm-function[<T as core::convert::Into<U>>::into::hf946dfd05fbc24ce]
	<?>.wasm-function[<stdweb::webcore::value::Reference as stdweb::webcore::serialization::JsSerialize>::_into_js::h38561bb79fb71fed]
	<?>.wasm-function[<&T as stdweb::webcore::serialization::JsSerialize>::_into_js::h95d26001fd95b648]
	<?>.wasm-function[<stdweb::webcore::newtype::Newtype<(stdweb::webcore::serialization::NonFunctionTag,()),T> as stdweb::webcore::serialization::JsSerializeOwned>::into_js_owned::h4807e99c2bc80c72]
	<?>.wasm-function[stdweb::webapi::window::Window::local_storage::hfcd2d0713ee243fb]
	<?>.wasm-function[localstoragefs::fs::File::open::h526a646c80a81590]
	<?>.wasm-function[stevenarella::console::Vars::load_config::h585808260ef40191]
	<?>.wasm-function[stevenarella::main2::heddadd9feacdeaa9]
	<?>.wasm-function[stevenarella::main::ha395fada26a8133c]
	<?>.wasm-function[main]
	wasm-stub
	main
	Eval Code
	eval
	./index.js (0.bootstrap.js:118)
	__webpack_require__ (bootstrap.js:651)
	__webpack_require__
	promiseReactionJob

After removing localstoragefs since it requires stdweb, and replacing std_or_web with a stubbed-out File, we are back to the original Thread error:

[Info] [WDS] Live Reloading enabled.
[Info] [main.rs:240][INFO] Starting steven
panicked at 'failed to spawn thread: Custom { kind: Other, error: "operation not supported on this platform" }', /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/thread/mod.rs:610:29

Stack:

__wbg_new_59cb74e423758ede@http://localhost:8080/bootstrap.js:74:106
wasm-stub@[wasm code]
<?>.wasm-function[console_error_panic_hook::Error::new::h07bd190f3f82f830]@[wasm code]
<?>.wasm-function[console_error_panic_hook::hook_impl::h1bacdd9e2d2e7801]@[wasm code]
<?>.wasm-function[console_error_panic_hook::hook::h67ae4e7ff7237ec9]@[wasm code]
<?>.wasm-function[core::ops::function::Fn::call::h4a70a8d50c1533af]@[wasm code]
<?>.wasm-function[std::panicking::rust_panic_with_hook::hc5713da015ebaa19]@[wasm code]
<?>.wasm-function[std::panicking::begin_panic_handler::{{closure}}::hc5eba7f0030e8f4f]@[wasm code]
<?>.wasm-function[std::sys_common::backtrace::__rust_end_short_backtrace::he811f0bd07938b42]@[wasm code]
<?>.wasm-function[rust_begin_unwind]@[wasm code]
<?>.wasm-function[core::panicking::panic_fmt::h775d5c012939dd41]@[wasm code]
<?>.wasm-function[core::option::expect_none_failed::h924688d051ea0ca4]@[wasm code]
<?>.wasm-function[core::result::Result<T,E>::expect::h9743326f916308c4]@[wasm code]
<?>.wasm-function[std::thread::spawn::h31e99ceb42f0aaa8]@[wasm code]
<?>.wasm-function[stevenarella::render::TextureManager::new::h98124d7a66d6d1ce]@[wasm code]
<?>.wasm-function[stevenarella::render::Renderer::new::h4ced0273e291dcfa]@[wasm code]
<?>.wasm-function[stevenarella::main2::heddadd9feacdeaa9]@[wasm code]
<?>.wasm-function[stevenarella::main::ha395fada26a8133c]@[wasm code]
<?>.wasm-function[main]@[wasm code]
wasm-stub@[wasm code]
main@[native code]
eval code
eval@[native code]
./index.js@http://localhost:8080/0.bootstrap.js:34:5
__webpack_require__@http://localhost:8080/bootstrap.js:621:34
__webpack_require__@[native code]
promiseReactionJob@[native code]

skin thread:

impl TextureManager {
    fn new(
        res: Arc<RwLock<resources::Manager>>,
    ) -> (
        TextureManager,
        mpsc::Sender<String>,
        mpsc::Receiver<(String, Option<image::DynamicImage>)>,
    ) {
        let (tx, rx) = mpsc::channel();
        let (stx, srx) = mpsc::channel();
        let skin_thread = thread::spawn(|| Self::process_skins(srx, tx));

After disabling the skin thread, the errors get more interesting:

Screen Shot 2020-12-26 at 10 24 34 AM

@iceiix
Copy link
Owner Author

iceiix commented Dec 26, 2020

Updating to support #version 300 es GLSL (WebGL 2 / OpenGL ES 3), in addition to the #version 150 (OpenGL 3.2) we supported before (examples show #version 410 = OpenGL 4.1 but we're not using any OpenGL 4 functionality so no need to update to OpenGL 3 yet, see https://en.wikipedia.org/wiki/OpenGL_Shading_Language).

The current error is related to accum and revealage outputs in src/render/shaders/chunk_frag.glsl:

[Error] WebGL: ERROR: 0:16: 'accum' : must explicitly specify all locations when using multiple fragment outputs
[Error] WebGL: ERROR: 0:17: 'revealage' : must explicitly specify all locations when using multiple fragment outputs
[Error] [render/shaders.rs:150][ERROR] Src: #version 300 es
precision mediump float;
precision mediump sampler2DArray;
#define alpha
uniform sampler2DArray textures;

in vec3 vColor;
in vec4 vTextureInfo;
in vec2 vTextureOffset;
in float vAtlas;
in vec3 vLighting;

#ifndef alpha
out vec4 fragColor;
#else
out vec4 accum;
out float revealage;
#endif

const float invAtlasSize = 1.0 / 1024.0;
vec4 atlasTexture() {
    vec2 tPos = vTextureOffset;
    tPos = clamp(tPos, vec2(0.1), vTextureInfo.zw - 0.1);
    tPos += vTextureInfo.xy;
    tPos *= invAtlasSize;
    return texture(textures, vec3(tPos, vAtlas));
}

void main() {
    vec4 col = atlasTexture();
    #ifndef alpha
    if (col.a < 0.5) discard;
    #endif
    col *= vec4(vColor, 1.0);
    col.rgb *= vLighting;

    #ifndef alpha
    fragColor = col;
    #else
    float z = gl_FragCoord.z;
    float al = col.a;
    float weight = pow(al + 0.01f, 4.0f) +
                     max(0.01f, min(3000.0f, 0.3f / (0.00001f + pow(abs(z) / 800.0f, 4.0f))));
    accum = vec4(col.rgb * al * weight, al);
    revealage = weight * al;
    #endif
}

Useful articles: https://webgl2fundamentals.org/webgl/lessons/webgl1-to-webgl2.html and https://webgl2fundamentals.org/webgl/lessons/webgl2-whats-new.html, in particular, WebGL2 is more on par with what this project needs (it uses vertex arrays, etc., now always available in WebGL2 unlike WebGL1)

@iceiix
Copy link
Owner Author

iceiix commented Dec 26, 2020

https://www.khronos.org/opengl/wiki/Fragment_Shader#Outputs

Now gets as far as hitting the multisample sample in src/render/shaders/trans_frag.glsl:

[main.rs:240][INFO] Starting steven
[main.rs:335][INFO] Shader version: #version 300 es
WebGL: ERROR: 0:7: 'sampler2DMS' : Illegal use of reserved word
WebGL: ERROR: 0:7: 'sampler2DMS' : syntax error
[render/shaders.rs:150][ERROR] Src: #version 300 es
...
uniform sampler2D taccum;
uniform sampler2D trevealage;
uniform sampler2DMS tcolor;

sample2DMS will have to be removed/replaced, but it is non-trivial: #442 renderbuffer

@iceiix iceiix mentioned this pull request Dec 26, 2020
29 tasks
@iceiix
Copy link
Owner Author

iceiix commented Dec 26, 2020

Since further progress is hitting a blocker (#442), but this is a useful step towards web support, will merge this to master. Opened a new issue for the overall effort: #446 🕸️ Web support

@iceiix iceiix merged commit 3692f7a into master Dec 26, 2020
@iceiix iceiix deleted the websys branch December 26, 2020 21:42
iceiix added a commit that referenced this pull request Dec 26, 2020
A small step for #446 🕸️ Web support, use web-sys to interface to the web.
Previously, we would try to use glutin on the web, which is not supported;
now glutin is only used on native: fixes #171 could not find Context in platform_impl.

winit is still used on both, but the GL context is created with web-sys and glow
(on the web), and created with glutin and used with glow (on native). stdweb is
no longer used, being replaced by web-sys.

Substantial refactoring to allow reusing the code between web/native:

* settings: use VirtualKeyCode from winit, not reexported from glutin
* std_or_web: remove broken localstoragefs/stdweb, add File placeholder
* render: disable skin_thread on wasm since we don't have threads

* gl: use glow types in gl wrapper (integers in native, but Web*Key in web)
* gl: web-sys WebGlUniformLocation does not implement Copy trait, so glow::UniformLocation doesn't so gl::Uniform can't
* gl: refactor context initialization, pass glow::Context to gl::init for consistency between native/web
* gl: update to glow with panicking tex_image_2d_multisample web-sys wrapper

* glsl: use shader version in GLSL for WebGL 2 and OpenGL 3.2

* shaders: add explicit float/int type conversions, required for WebGL
* shaders: specify mediump precision, required for WebGL
* shaders: specify fragment shader output locations for WebGL

* main: refactor handle_window_event to take a winit window, not glutin context
* main: handle resize outside of handle_window_event since it updates the glutin window (the only event which does this)
* main: use winit events in handle_window_event not reexported glutin events
* main: refactor game loop handling into tick_all()
* main: create winit window for WebGL, and use winit_window from glutin
* main: restore console_error_panic_hook,  mistakingly removed in (#260)
* main: remove force setting env RUST_BACKTRACE=1, no longer can set env on web

* www: index.js: fix wasm import path
* www: npm update, npm audit fix
* www: update readme to link to status on #446 🕸️ Web support
@iceiix iceiix mentioned this pull request Dec 27, 2020
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

wasm broken: failed to resolve: could not find Context in platform_impl
1 participant