-
Notifications
You must be signed in to change notification settings - Fork 61
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
WebGL fixes after disabling threaded chunk builder #451
Conversation
src/chunk_builder.rs is going to be a problem. It uses a thread pool of 8 threads to build chunks. This crate attempts to be a replacement for std::thread on wasm: https://lib.rs/crates/wasm_thread - though it requires some tricks to support atomics. Another option is web workers. More akin to processes than threads, pass messages between workers. mpsc::channel()? What's the canonical way to use web workers in wasm from Rust, while also supporting native threads? WASI (wasm32-wasi) is looking more and more interesting (versus wasm32-unknown-unknown, which doesn't specify the target platform — not necessarily running in the browser), found this: https://lib.rs/crates/wasi-worker Disabling chunk builder, enabling only the renderer, hits a more interesting error: "Bind frag data location is not supported", a call to glow bind_frag_data_location(), used in src/render/mod.rs for the chunk shader program "accum" and "revealage" attributes: (after fixing this, since layout is already specified in-shader: https://www.khronos.org/opengl/wiki/Fragment_Shader#Output_buffers, get GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, right before the bind_frag_data_location() calls) At a fork in the road here, could try to disable threading as much as possible and work on getting the rendering up to snuff. Threads are non-trivial, but some kind of multiprocessing will likely be needed ultimately. Uses of std::thread:
Most of these are network I/O. On the web, the way to do I/O without blocking is asynchronous callbacks, either functions passed in directly as arguments, or using Our use of reqwest, in particular, should be switched from reqwest::blocking in a thread, to async, and since reqwest supports WASM, this probably should "just work" on the web. As for the protocol/packet sending and receiving, similar idea, convert to async to prepare for implementing I/O on the web using Web Sockets, maybe using: https://lib.rs/crates/ws_stream_wasm (A convenience library for using websockets in WASM) - "AsyncRead/AsyncWrite on top of websockets" |
…der specification layout(location=), which works on native in OpenGL 4.1 but we're on OpenGL 3.2 - see https://www.khronos.org/opengl/wiki/Fragment_Shader#Output_buffers
TransInfo framebuffer is incomplete, but continuing past this error, at last something finally appears on screen! (albeit with more errors): glGetError 1280 = GL_INVALID_ENUM Interesting the UI is rendered, so that is working, just not the chunks. The logo splash text animates, demonstrating the std::time replacement paid off (#449, replacing with web.mov |
Firefox 84.0 (64-bit) gives more information on the incomplete
|
Valid combinations of format, type, and internalFormat are listed at https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf#page=124&zoom=100,168,206. We had UNSIGNED_BYTE for DEPTH_COMPONENT24, but only UNSIGNED_INT is a valid type for this internal format. Fixes texImage: Mismatched internalFormat and format/type: 0x81a6 and 0x1902/0x1401 and fixes the subsequent GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT error.
Latest GL warnings/errors in Firefox 84:
|
Fixes WebGL warning: enabled: cap: Invalid enum value <enum 0x809d> 0.bootstrap.js line 11 > eval:851:21
0x8b52 = FLOAT_VEC4 per FLOAT_VEC4 color_mul is set with: if let Some(v) = &collection.shader.color_mul {
unsafe {
v.set_float_multi_raw(model.colors.as_ptr() as *const _, model.colors.len())
}
}
bug in the wrapper? #[allow(clippy::missing_safety_doc)]
pub unsafe fn set_float_multi_raw(&self, data: *const f32, len: usize) {
glow_context().uniform_4_f32_slice(Some(&self.0), std::slice::from_raw_parts(data, len));
} "length (1)" -- the passed in
The wrapper in glow https://github.com/grovesNL/glow/blob/main/src/native.rs#L1374 unsafe fn uniform_4_f32_slice(&self, location: Option<&Self::UniformLocation>, v: &[f32]) {
let gl = &self.raw;
if let Some(loc) = location {
gl.Uniform4fv(*loc as i32, v.len() as i32 / 4, v.as_ptr());
}
} https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml https://www.khronos.org/opengl/wiki/GLSL_:_common_mistakes#How_to_use_glUniform says the count is of the type, glUniform4fv type (4f, which corresponds to vec4, so it should be 1. glow is dividing by 4. declaration: pub struct Model {
...
pub colors: Vec<[f32; 4]>, initialization: for (i, part) in parts.into_iter().enumerate() {
model.matrix.push(Matrix4::identity());
model.colors.push([1.0, 1.0, 1.0, 1.0]); used in src/render/shaders/model_frag.glsl uniform vec4 colorMul[10]; fragColor = col * colorMul[int(vID)]; and src/render/shaders/sun_frag.glsl uniform vec4 colorMul[10]; fragColor = col * colorMul[int(vID)]; Passing in a raw pointer (set_float_multi_raw) seems suboptimal, better way to do this? Model |
Removes use of passing raw pointers in set_float_multi_raw parameters Instead, casts raw pointers to flatten, similar to set_matrix_multi Fixes WebGL warning: uniform setter: (uniform colorMul[0]) values length (1) must be a positive integer multiple of size of <enum 0x8b52>.
Final remaining warning is:
https://stackoverflow.com/questions/46437800/webgl-2-0-integer-attribute-throws-type-error-if-vertexattribarray-is-disabled
glGetError = 1282 check the draw_elements() call [gl/mod.rs:57][ERROR] about to draw_elements ty=4 count=6 dty=5123 offset=0 2 stevenarella_bg.js:1475:13 uses:
src/render/ui.rs index_type: gl::UNSIGNED_BYTE, vertex_pointer and vertex_pointer in src/gl go to glow vertex_attrib_pointer_f32 and vertex_attrib_pointer_i32, to native glVertexAttribPointer and glVertexAttribIPointer. https://stackoverflow.com/questions/46437800/webgl-2-0-integer-attribute-throws-type-error-if-vertexattribarray-is-disabled says:
https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/vertexAttribI The error in Chrome 87:
|
|
The error seems to be in model's draw_elements, commenting it out avoids the error (while the ui draw_elements continues without error; chunk rendering draw_elements is not invoked). What could be the type mismatch with this call? src/render/model.rs ``rust
super::generate_element_buffer is in src/render/mod.rs, ty is UNSIGNED_SHORT or if exceeds u16::max_value() then UNSIGNED_INT: #[allow(unused_must_use)]
pub fn generate_element_buffer(size: usize) -> (Vec<u8>, gl::Type) {
let mut ty = gl::UNSIGNED_SHORT;
let mut data = if (size / 6) * 4 * 3 >= u16::max_value() as usize {
ty = gl::UNSIGNED_INT;
Vec::with_capacity(size * 4)
} else {
Vec::with_capacity(size * 2)
};
for i in 0..size / 6 {
for val in &[0, 1, 2, 2, 1, 3] {
if ty == gl::UNSIGNED_INT {
data.write_u32::<NativeEndian>((i as u32) * 4 + val);
} else {
data.write_u16::<NativeEndian>((i as u16) * 4 + (*val as u16));
}
}
}
(data, ty)
} both unsigned. Where is the signed int coming from, what is vertex attrib 0? WebGL warning: drawElementsInstanced: Vertex attrib 0 requires data of type INT, but is being supplied with type UINT. 2 0.bootstrap.js line 11 > eval:847:21 https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElements.xhtml says valid values are:
changing to SHORT fails WebGL warning: drawElementsInstanced: type: Invalid enum value <enum 0x1402> (= GL_SHORT) Chrome: glDrawElements: vertexAttrib function must match shader attrib type Found how this other project fixed a similar issue: google/filament#1726 // In some OpenGL implementation, (e.g. WebGL and maybe Angle), we must supply a
// properly-typed placeholder for every input that is declared in the vertex shader,
// similar to Vulkan and Metal.
const uint32_t kBoneIndicesLocation = 5; // VertexAttribute::BONE_INDICES
if (i == kBoneIndicesLocation) {
glVertexAttribI4ui(GLuint(i), 0, 0, 0, 0);
} |
…ibI4ui" This reverts commit 116bee0.
First cut at adding glVertexAttribI4ui() wrappers to glow in iceiix/glow#2 (if useful, can PR to https://github.com/grovesNL/glow/compare/main). glow doesn't seem to have many of the glVertexAttrib(I) family even though they are available in OpenGL ES 3.0: https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glVertexAttrib.xhtml and probably WebGL 2.0. These glVertexAttrib functions we haven't used before. glVertexAttribPointer is used extensively, however, through vertex_pointer and vertex_pointer_int. https://stackoverflow.com/questions/13603956/glvertexattrib-vs-glvertexattribpointer explains the difference:
tried to call glVertexAttribI4ui(0, 0, 0, 0, 0, 0) to effectively set the type of attribute 0 to uint, to no effect. |
Attributes in the model renderer:
In Firefox, which logged the attrib 0 error, it is
in the Vertex struct, id is u8 (unsigned), and it is populated with: if let Some(v) = collection.shader.id {
v.vertex_pointer_int(1, gl::UNSIGNED_BYTE, 36, 32)
} which calls into glow_context().vertex_attrib_pointer_i32 -> glVertexAttribIPointer https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribPointer.xhtml family shows three functions: glVertexAttribPointer, glVertexAttribIPointer, glVertexAttribLPointer
In the shader (model_vertex.glsl), |
Turns out glVertexAttribI4ui (iceiix/glow#2) is not needed, the fix was to change UNSIGNED_BYTE to BYTE in |
This pull request ended up being more about miscellaneous fixes for WebGL, after getting past the chunk builder threading, but now we are back to src/chunk_builder.rs — without it, no chunks will be built. This will have to be solved to actually show the world, nonetheless, the fixes so far are enough to show the UI, so I'll merge this (continue in #446). |
std::thread vs wasm32
for 🕸️ Web support #446