注意: 运行前,需要将 bin/两个dll 拷贝 到 运行目录,或者 exe所在目录
WebGPU
接口子集的GL
后端,基于Rust
实现。
- 接口: 基于 wgpu-rs
v0.16
进行修改; - 功能: 仅仅对应WebGL2的子集
- 加
压缩纹理
扩展:DDS
/ASTC
- 加
- 平台:
Windows
:OpenGL 3.3
Android
/ PC-Android 模拟器:GLES 3.0
- 浏览器 / 微信小游戏: WebGL2
为了兼容 wgpu-rs,pi_wgpu 也 包含了 wgpu
如果不加 feature,默认就是用 pi-wgpu 的实现
如果 想用 wgpu-rs 实现,在 feature加入 use_wgpu
即可,例子:
[dependencies]
pi_wgpu = {version = "0.1", default-features = false, features = ["use_wgpu"]}
执行 cargo run --example triangle
命令运行 triangle example
1.3. 运行 Web 平台
- 执行
wasm-pack test --chrome --example triangle
命令,构建wasm以及测试环境,并开启服务器监听在8000
端口 - 在浏览器中访问
http://127.0.0.1:8000
地址,即可运行测试 - 如果想修改访问地址, 将地址设置在
WASM_BINDGEN_TEST_ADDRESS
环境变量中, 如$env:WASM_BINDGEN_TEST_ADDRESS="0.0.0.0:8000", 即可通过ip访问
- 打开Linux Shell, 执行
cargo apk run --example triangle --lib
编译 example为apk - 链接手机 在
target\debug\apk\examples
中打开cmd, 并执行adb install triangle.apk
来安装apk
- GUI: pi_ui_render, bevy 分支
- blend_mode.rs
- shadow.rs
- compress_texture
- 3D:
- pi_3d
- 最简单的渲染 simple / dispose.rs
- 动画,buffer更新:anime / 01.rs
- 粒子 particle / render_stretched.rs
- 后处理 pi_post_process / main.rs
- pi_3d
性能优化
:设置状态机,做GL的全状态比较;所以GL指令数量会比wgpu-rs少;
注1:为什么不直接用 wgpu-rs
- 实际测试,库 WebGL2 Backend性能不满足游戏需求;
Vulkan
/WebGPU
因兼容性问题,近期内不能广泛使用于各个平台;
注2:根据微信小游戏的开发者文档,在 iPhone / iPad 上,WebGL2
至少要 iOS
版本 >= 15.5 才能开启
注3:详细的 设计笔记,见这里
- 销毁资源:可以在录制指令时 创建 / 销毁 资源
- 线程安全:
- 录制指令 是
单线程
,录制即为提交,所谓的队列提交是空实现; - 创建,销毁 资源,Exe / Apk
多线程
; 注
:使用者自己确保,创建/释放 和 录制指令 的 线程安全性;
- 录制指令 是
- GLSL:
- 功能: 仅支持 gles-300 / std140-布局;
- 语法: 仅支持 GLSL 450 语法;
- 必须等该资源的物体
draw
之后,才能销毁; RenderPass
绑定的 纹理 资源,必须等到RenderPass
Drop 方法调用后,才能销毁;- 原因:因为 不知道调用顺序,vb / ib / ubo 的调用都是先缓存,等到 draw() 内部 才 统一调用的 gl 函数;
例子:
pass.set_vertex_buffer(vb1)
// 不能 调用 vb1 的 drop
pass.set_bind_group(bg1)
// 不能 调用 bg2 的 drop
pass.set_render_pipeline(rp1)
// 不能 调用 rp1 的 drop
pass.draw()
// 这里之后,可以扔掉 vb1, bg1, rp1
pass.set_vertex_buffer(vb2)
函数 | 支持 | 说明 |
---|---|---|
QuerySet | × | WebGL2 本身支持 |
hal::Fence | × | WebGL2 本身支持 |
RenderBundle | × | |
ComputePipeline | × | |
ComputePass | × | |
hal::Barrier | × |
函数 | 支持 | 说明 |
---|---|---|
backend_bits_from_env |
✔ | 永远返回 Some(Backends::GL) |
create_texture_with_data |
✔ | |
create_buffer_init |
✔ |
函数 | 支持 | 说明 |
---|---|---|
new |
✔ | |
request_adapter |
✔ | |
create_surface |
✔ | |
enumerate_adapters | × |
函数 | 支持 | 说明 |
---|---|---|
request_device |
✔ | |
features |
✔ | |
limits |
✔ | |
get_info |
✔ | |
get_downlevel_capabilities |
✔ | |
is_surface_supported |
✔ | |
get_texture_format_features |
✔ |
函数 | 支持 | 说明 |
---|---|---|
configure |
✔ | present_mode : 必须是Fifo ; alpha_mode : 必须是 Opaque |
get_current_texture |
✔ | |
get_default_config | × | |
get_capabilities | × |
函数 | 支持 | 说明 |
---|---|---|
present |
✔ |
注: 所有方法,都要等 Surface.configure(Device, &config) 调用之后,才能使用!
函数 | 支持 | 说明 |
---|---|---|
features |
✔ | |
limits |
✔ | |
create_shader_module |
✔ | |
create_command_encoder |
✔ | |
create_bind_group_layout |
✔ | |
create_bind_group |
✔ | |
create_pipeline_layout |
✔ | |
create_render_pipeline |
✔ | 参数 layout: Option<&'a PipelineLayout> 必须 有值! |
create_buffer |
✔ | |
create_texture |
✔ | |
create_sampler |
✔ | |
create_shader_module_unchecked | × | |
create_shader_module_spirv | × | |
create_render_bundle_encoder | × | |
create_compute_pipeline | × | |
create_texture_from_hal | × | |
create_query_set | × | |
poll | × | |
on_uncaptured_error | × | |
push_error_scope | × | |
pop_error_scope | × | |
start_capture | × | |
stop_capture | × | |
as_hal | × |
注: 所有方法,都要等和该Queue对应的Device 调用 Surface.configure(Device, &config) 之后,才能使用!
函数 | 支持 | 说明 |
---|---|---|
write_buffer |
✔ | |
write_texture |
✔ | |
submit |
✔ | 空实现 |
on_submitted_work_done | × | |
write_buffer_with | × | |
copy_external_image_to_texture | × | |
get_timestamp_period | × |
函数 | 支持 | 说明 |
---|---|---|
finish |
✔ | 空实现 |
begin_render_pass |
✔ | 只支持一个渲染目标 |
clear_texture | × | |
clear_buffer | × | |
begin_compute_pass | × | |
copy_buffer_to_buffer | × | |
copy_buffer_to_texture | × | |
copy_texture_to_buffer | × | |
copy_texture_to_texture | × | |
insert_debug_marker | × | |
push_debug_group | × | |
pop_debug_group | × | |
write_timestamp | × | |
resolve_query_set | × |
函数 | 支持 | 说明 |
---|---|---|
set_bind_group |
✔ | |
set_pipeline |
✔ | |
set_blend_constant |
✔ | |
set_index_buffer |
✔ | |
set_vertex_buffer |
✔ | |
set_scissor_rect |
✔ | |
set_viewport |
✔ | |
set_stencil_reference |
✔ | |
draw |
✔ | 参数 first_instance 必须为 0; base_vertex 必须为 0 |
draw_indexed |
✔ | 参数 first_instance 必须为 0; base_vertex 必须为 0 |
set_push_constants | × | |
insert_debug_marker | × | |
push_debug_group | × | |
pop_debug_group | × | |
draw_indirect | × | |
draw_indexed_indirect | × | |
execute_bundles | × | |
multi_draw_indirect | × | |
multi_draw_indexed_indirect | × | |
multi_draw_indirect_count | × | |
multi_draw_indexed_indirect_count | × | |
write_timestamp | × | |
begin_pipeline_statistics_query | × | |
end_pipeline_statistics_query | × |
注:其生命周期还受到 BindGroup
的影响,见BindGroup
注:其生命周期还受到 BindGroup
的影响,见BindGroup
函数 | 支持 | 说明 |
---|---|---|
create_view |
✔ | |
as_image_copy |
✔ | |
size |
✔ | |
width |
✔ | |
height |
✔ | |
depth_or_array_layers |
✔ | |
mip_level_count |
✔ | |
sample_count |
✔ | |
dimension |
✔ | |
format |
✔ | |
usage |
✔ | |
as_hal | × | |
destroy | × |
注:其生命周期还受到 BindGroup
的影响,见BindGroup
函数 | 支持 | 说明 |
---|---|---|
size |
✔ | |
usage |
✔ | |
as_entire_binding |
✔ | |
as_entire_buffer_binding |
✔ | |
slice |
✔ | |
unmap | × | |
destroy | × |
函数 | 支持 | 说明 |
---|---|---|
map_async | × | |
get_mapped_range | × | |
get_mapped_range_mut | × |
BindGroup
会握住它使用的Buffer
, Texture
, Sampler
对象,使其不会被销毁。
如果想要对应的资源被销毁,必须同时扔掉BindGroup
和对应的资源。
- 仅支持 Naga 编译过后,版本为 glsl 3.0 的 无 define 宏 的 glsl
- 扩展:带上一个字段,用于说明 这个shader原始的 set-binding 和 uniform 的 名字
- 代码 模拟
UBO
:用 uniform 模拟Sampler
:用 texture 函数 模拟VS
/FS
: 不能指定 layout- 难点,需要
可行性测试
:要找一套 WebGL Shader 的 编译转换工具,naga
未必支持;- 将 UBO 转成 Uniform;
- 去掉 所有的 layout,同时导出成 json文件,供 rust 设置;
- rust层,调用 WebGL 的 getXXXLocation 取 Uniform / Attribute 的 location,建立 layout 的 hash-map;
- 难点,需要
- 看 扩展 有没有
- 很多纹理格式: 比如 float 纹理,深度 纹理
VAO
几何实例化
- 多目标渲染 / drawBuffers clearBuffer
- 多重采样
- FeedBack
3.2. 微信小游戏: iOS
的 WebGL
WebGL
: 如果发现 iOS 14 的 帧率提升不上去,试试 在 canvas.getContext 接口 将 antialias: trueWebGL
: iOS 版本 14.0 ~ iOS 15.3, 多个 drawcall 使用不同偏移 来 共享VB
/IB
,性能非常糟糕 !
Instance --> Adatper --> (Device, QUeue)
--(Resumed Event)--> Surface
所有的 Device / Queue 的函数,都要等:Surface.configure(Device, &config) 之后调用。
原因:因为 Web平台 没有 跨 Surface 共享的 Context
可以将 所有的 渲染初始化,放到一个 furture,哪个furture 留到 窗口的 Resumed 事件判断并初始化。
然后,configure 还是要 等 Resized 调用(web没有Resize事件,就再 request_draw 中模拟)