update wgpu to 0.13 (#5168)

# Objective

- Update wgpu to 0.13
- ~~Wait, is wgpu 0.13 released? No, but I had most of the changes already ready since playing with webgpu~~ well it has been released now
- Also update parking_lot to 0.12 and naga to 0.9

## Solution

- Update syntax for wgsl shaders https://github.com/gfx-rs/wgpu/blob/master/CHANGELOG.md#wgsl-syntax
- Add a few options, remove some references: https://github.com/gfx-rs/wgpu/blob/master/CHANGELOG.md#other-breaking-changes
- fragment inputs should now exactly match vertex outputs for locations, so I added exports for those to be able to reuse them https://github.com/gfx-rs/wgpu/pull/2704
This commit is contained in:
François 2022-07-14 21:17:16 +00:00
parent c43295af80
commit 814f8d1635
70 changed files with 665 additions and 774 deletions

2
.github/bors.toml vendored
View file

@ -16,7 +16,7 @@ status = [
"miri",
"check-compiles",
"build-and-install-on-iOS",
"run-examples-on-windows",
"run-examples-on-windows-dx12",
]
use_squash_merge = true

View file

@ -61,9 +61,9 @@ jobs:
- name: Build APK
run: cargo apk build --example android_example
run-examples-on-windows:
run-examples-on-windows-dx12:
runs-on: windows-latest
timeout-minutes: 30
timeout-minutes: 60
steps:
- uses: actions/checkout@v3
@ -91,7 +91,7 @@ jobs:
for example in .github/example-run/*.ron; do
example_name=`basename $example .ron`
echo "running $example_name - "`date`
time CI_TESTING_CONFIG=$example cargo run --example $example_name --features "bevy_ci_testing"
time WGPU_BACKEND=dx12 CI_TESTING_CONFIG=$example cargo run --example $example_name --features "bevy_ci_testing"
sleep 10
done

View file

@ -1,24 +1,24 @@
#import bevy_pbr::mesh_types
#import bevy_pbr::mesh_view_bindings
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> mesh: Mesh;
// NOTE: Bindings must come before functions that use them!
#import bevy_pbr::mesh_functions
struct Vertex {
[[location(0)]] position: vec3<f32>;
[[location(1)]] normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;
@location(0) position: vec3<f32>,
@location(1) normal: vec3<f32>,
@location(2) uv: vec2<f32>,
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] uv: vec2<f32>;
@builtin(position) clip_position: vec4<f32>,
@location(0) uv: vec2<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = mesh_position_local_to_clip(mesh.model, vec4<f32>(vertex.position, 1.0));
@ -28,9 +28,9 @@ fn vertex(vertex: Vertex) -> VertexOutput {
struct Time {
time_since_startup: f32;
time_since_startup: f32,
};
[[group(2), binding(0)]]
@group(2) @binding(0)
var<uniform> time: Time;
@ -54,8 +54,8 @@ fn oklab_to_linear_srgb(c: vec3<f32>) -> vec3<f32> {
);
}
[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
let speed = 2.0;
let t_1 = sin(time.time_since_startup * speed) * 0.5 + 0.5;
let t_2 = cos(time.time_since_startup * speed);

View file

@ -8,27 +8,19 @@
#import bevy_pbr::shadows
#import bevy_pbr::pbr_functions
[[group(1), binding(0)]]
@group(1) @binding(0)
var my_array_texture: texture_2d_array<f32>;
[[group(1), binding(1)]]
@group(1) @binding(1)
var my_array_texture_sampler: sampler;
struct FragmentInput {
[[builtin(front_facing)]] is_front: bool;
[[builtin(position)]] frag_coord: vec4<f32>;
[[location(0)]] world_position: vec4<f32>;
[[location(1)]] world_normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
#endif
@builtin(front_facing) is_front: bool,
@builtin(position) frag_coord: vec4<f32>,
#import bevy_pbr::mesh_vertex_output
};
[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
let layer = i32(in.world_position.x) & 0x3;
// Prepare a 'processed' StandardMaterial by sampling all textures to resolve

View file

@ -1,15 +1,17 @@
struct CustomMaterial {
color: vec4<f32>;
color: vec4<f32>,
};
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> material: CustomMaterial;
[[group(1), binding(1)]]
@group(1) @binding(1)
var base_color_texture: texture_2d<f32>;
[[group(1), binding(2)]]
@group(1) @binding(2)
var base_color_sampler: sampler;
[[stage(fragment)]]
fn fragment([[location(2)]] uv: vec2<f32>) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
return material.color * textureSample(base_color_texture, base_color_sampler, uv);
}

View file

@ -1,14 +1,16 @@
#import bevy_pbr::mesh_view_bindings
[[group(1), binding(0)]]
@group(1) @binding(0)
var texture: texture_2d<f32>;
[[group(1), binding(1)]]
@group(1) @binding(1)
var our_sampler: sampler;
[[stage(fragment)]]
fn fragment([[builtin(position)]] position: vec4<f32>) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {
// Get screen position with coordinates from 0 to 1
let uv = position.xy / vec2<f32>(view.width, view.height);
let offset_strength = 0.02;

View file

@ -1,12 +1,15 @@
#import bevy_pbr::mesh_view_bindings
[[group(1), binding(0)]]
@group(1) @binding(0)
var texture: texture_2d<f32>;
[[group(1), binding(1)]]
@group(1) @binding(1)
var texture_sampler: sampler;
[[stage(fragment)]]
fn fragment([[builtin(position)]] position: vec4<f32>) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
let uv = position.xy / vec2<f32>(view.width, view.height);
let color = textureSample(texture, texture_sampler, uv);
return color;

View file

@ -2,25 +2,25 @@
#import bevy_pbr::mesh_bindings
struct CustomMaterial {
color: vec4<f32>;
color: vec4<f32>,
};
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> material: CustomMaterial;
// NOTE: Bindings must come before functions that use them!
#import bevy_pbr::mesh_functions
struct Vertex {
[[location(0)]] position: vec3<f32>;
[[location(1)]] blend_color: vec4<f32>;
@location(0) position: vec3<f32>,
@location(1) blend_color: vec4<f32>,
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] blend_color: vec4<f32>;
@builtin(position) clip_position: vec4<f32>,
@location(0) blend_color: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = mesh_position_local_to_clip(mesh.model, vec4<f32>(vertex.position, 1.0));
@ -29,10 +29,10 @@ fn vertex(vertex: Vertex) -> VertexOutput {
}
struct FragmentInput {
[[location(0)]] blend_color: vec4<f32>;
@location(0) blend_color: vec4<f32>,
};
[[stage(fragment)]]
fn fragment(input: FragmentInput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(input: FragmentInput) -> @location(0) vec4<f32> {
return material.color * input.blend_color;
}

View file

@ -1,4 +1,4 @@
[[group(0), binding(0)]]
@group(0) @binding(0)
var texture: texture_storage_2d<rgba8unorm, read_write>;
fn hash(value: u32) -> u32 {
@ -15,8 +15,8 @@ fn randomFloat(value: u32) -> f32 {
return f32(hash(value)) / 4294967295.0;
}
[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
@compute @workgroup_size(8, 8, 1)
fn init(@builtin(global_invocation_id) invocation_id: vec3<u32>, @builtin(num_workgroups) num_workgroups: vec3<u32>) {
let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));
@ -28,24 +28,24 @@ fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(nu
}
fn get(location: vec2<i32>, offset_x: i32, offset_y: i32) -> i32 {
fn is_alive(location: vec2<i32>, offset_x: i32, offset_y: i32) -> i32 {
let value: vec4<f32> = textureLoad(texture, location + vec2<i32>(offset_x, offset_y));
return i32(value.x);
}
fn count_alive(location: vec2<i32>) -> i32 {
return get(location, -1, -1) +
get(location, -1, 0) +
get(location, -1, 1) +
get(location, 0, -1) +
get(location, 0, 1) +
get(location, 1, -1) +
get(location, 1, 0) +
get(location, 1, 1);
return is_alive(location, -1, -1) +
is_alive(location, -1, 0) +
is_alive(location, -1, 1) +
is_alive(location, 0, -1) +
is_alive(location, 0, 1) +
is_alive(location, 1, -1) +
is_alive(location, 1, 0) +
is_alive(location, 1, 1);
}
[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
let n_alive = count_alive(location);
@ -55,7 +55,7 @@ fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
if (n_alive == 3) {
alive = true;
} else if (n_alive == 2) {
let currently_alive = get(location, 0, 0);
let currently_alive = is_alive(location, 0, 0);
alive = bool(currently_alive);
} else {
alive = false;

View file

@ -1,27 +1,27 @@
#import bevy_pbr::mesh_types
#import bevy_pbr::mesh_view_bindings
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> mesh: Mesh;
// NOTE: Bindings must come before functions that use them!
#import bevy_pbr::mesh_functions
struct Vertex {
[[location(0)]] position: vec3<f32>;
[[location(1)]] normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;
@location(0) position: vec3<f32>,
@location(1) normal: vec3<f32>,
@location(2) uv: vec2<f32>,
[[location(3)]] i_pos_scale: vec4<f32>;
[[location(4)]] i_color: vec4<f32>;
@location(3) i_pos_scale: vec4<f32>,
@location(4) i_color: vec4<f32>,
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] color: vec4<f32>;
@builtin(position) clip_position: vec4<f32>,
@location(0) color: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
let position = vertex.position * vertex.i_pos_scale.w + vertex.i_pos_scale.xyz;
var out: VertexOutput;
@ -30,7 +30,7 @@ fn vertex(vertex: Vertex) -> VertexOutput {
return out;
}
[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
return in.color;
}

View file

@ -1,12 +1,14 @@
struct CustomMaterial {
color: vec4<f32>;
color: vec4<f32>,
};
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> material: CustomMaterial;
[[stage(fragment)]]
fn fragment() -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(
#import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
#ifdef IS_RED
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
#else

View file

@ -31,7 +31,7 @@ thiserror = "1.0"
downcast-rs = "1.2.0"
fastrand = "1.7.0"
notify = { version = "=5.0.0-pre.11", optional = true }
parking_lot = "0.11.0"
parking_lot = "0.12.1"
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = { version = "0.2" }

View file

@ -19,7 +19,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }
# other
anyhow = "1.0.4"
rodio = { version = "0.15", default-features = false }
parking_lot = "0.11.0"
parking_lot = "0.12.1"
[target.'cfg(target_arch = "wasm32")'.dependencies]
rodio = { version = "0.15", default-features = false, features = ["wasm-bindgen"] }

View file

@ -64,7 +64,7 @@ impl Node for MainPass2dNode {
let _main_pass_2d = info_span!("main_pass_2d").entered();
let pass_descriptor = RenderPassDescriptor {
label: Some("main_pass_2d"),
color_attachments: &[target.get_color_attachment(Operations {
color_attachments: &[Some(target.get_color_attachment(Operations {
load: match camera_2d.clear_color {
ClearColorConfig::Default => {
LoadOp::Clear(world.resource::<ClearColor>().0.into())
@ -73,7 +73,7 @@ impl Node for MainPass2dNode {
ClearColorConfig::None => LoadOp::Load,
},
store: true,
})],
}))],
depth_stencil_attachment: None,
};
@ -102,10 +102,10 @@ impl Node for MainPass2dNode {
let _reset_viewport_pass_2d = info_span!("reset_viewport_pass_2d").entered();
let pass_descriptor = RenderPassDescriptor {
label: Some("reset_viewport_pass_2d"),
color_attachments: &[target.get_color_attachment(Operations {
color_attachments: &[Some(target.get_color_attachment(Operations {
load: LoadOp::Load,
store: true,
})],
}))],
depth_stencil_attachment: None,
};

View file

@ -73,7 +73,7 @@ impl Node for MainPass3dNode {
label: Some("main_opaque_pass_3d"),
// NOTE: The opaque pass loads the color
// buffer as well as writing to it.
color_attachments: &[target.get_color_attachment(Operations {
color_attachments: &[Some(target.get_color_attachment(Operations {
load: match camera_3d.clear_color {
ClearColorConfig::Default => {
LoadOp::Clear(world.resource::<ClearColor>().0.into())
@ -82,7 +82,7 @@ impl Node for MainPass3dNode {
ClearColorConfig::None => LoadOp::Load,
},
store: true,
})],
}))],
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &depth.view,
// NOTE: The opaque main pass loads the depth buffer and possibly overwrites it
@ -119,10 +119,10 @@ impl Node for MainPass3dNode {
let pass_descriptor = RenderPassDescriptor {
label: Some("main_alpha_mask_pass_3d"),
// NOTE: The alpha_mask pass loads the color buffer as well as overwriting it where appropriate.
color_attachments: &[target.get_color_attachment(Operations {
color_attachments: &[Some(target.get_color_attachment(Operations {
load: LoadOp::Load,
store: true,
})],
}))],
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &depth.view,
// NOTE: The alpha mask pass loads the depth buffer and possibly overwrites it
@ -158,10 +158,10 @@ impl Node for MainPass3dNode {
let pass_descriptor = RenderPassDescriptor {
label: Some("main_transparent_pass_3d"),
// NOTE: The transparent pass loads the color buffer as well as overwriting it where appropriate.
color_attachments: &[target.get_color_attachment(Operations {
color_attachments: &[Some(target.get_color_attachment(Operations {
load: LoadOp::Load,
store: true,
})],
}))],
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &depth.view,
// NOTE: For the transparent pass we load the depth buffer. There should be no
@ -202,10 +202,10 @@ impl Node for MainPass3dNode {
let _reset_viewport_pass_3d = info_span!("reset_viewport_pass_3d").entered();
let pass_descriptor = RenderPassDescriptor {
label: Some("reset_viewport_pass_3d"),
color_attachments: &[target.get_color_attachment(Operations {
color_attachments: &[Some(target.get_color_attachment(Operations {
load: LoadOp::Load,
store: true,
})],
}))],
depth_stencil_attachment: None,
};

View file

@ -97,14 +97,14 @@ use std::marker::PhantomData;
///
/// ```wgsl
/// struct CustomMaterial {
/// color: vec4<f32>;
/// color: vec4<f32>,
/// };
///
/// [[group(1), binding(0)]]
/// @group(1) @binding(0)
/// var<uniform> material: CustomMaterial;
/// [[group(1), binding(1)]]
/// @group(1) @binding(1)
/// var color_texture: texture_2d<f32>;
/// [[group(1), binding(2)]]
/// @group(1) @binding(2)
/// var color_sampler: sampler;
/// ```
pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'static {

View file

@ -1,14 +1,14 @@
#import bevy_pbr::mesh_view_types
#import bevy_pbr::mesh_types
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> mesh: Mesh;
#ifdef SKINNED
[[group(1), binding(1)]]
@group(1) @binding(1)
var<uniform> joint_matrices: SkinnedMesh;
#import bevy_pbr::skinning
#endif
@ -17,18 +17,18 @@ var<uniform> joint_matrices: SkinnedMesh;
#import bevy_pbr::mesh_functions
struct Vertex {
[[location(0)]] position: vec3<f32>;
@location(0) position: vec3<f32>,
#ifdef SKINNED
[[location(4)]] joint_indices: vec4<u32>;
[[location(5)]] joint_weights: vec4<f32>;
@location(4) joint_indices: vec4<u32>,
@location(5) joint_weights: vec4<f32>,
#endif
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
@builtin(position) clip_position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
#ifdef SKINNED
let model = skin_model(vertex.joint_indices, vertex.joint_weights);

View file

@ -37,6 +37,8 @@ const MAX_JOINTS: usize = 256;
const JOINT_SIZE: usize = std::mem::size_of::<Mat4>();
pub(crate) const JOINT_BUFFER_SIZE: usize = MAX_JOINTS * JOINT_SIZE;
pub const MESH_VERTEX_OUTPUT: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 2645551199423808407);
pub const MESH_VIEW_TYPES_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 8140454348013264787);
pub const MESH_VIEW_BINDINGS_HANDLE: HandleUntyped =
@ -54,6 +56,12 @@ pub const SKINNING_HANDLE: HandleUntyped =
impl Plugin for MeshRenderPlugin {
fn build(&self, app: &mut bevy_app::App) {
load_internal_asset!(
app,
MESH_VERTEX_OUTPUT,
"mesh_vertex_output.wgsl",
Shader::from_wgsl
);
load_internal_asset!(
app,
MESH_VIEW_TYPES_HANDLE,
@ -601,11 +609,11 @@ impl SpecializedMeshPipeline for MeshPipeline {
shader: MESH_SHADER_HANDLE.typed::<Shader>(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![ColorTargetState {
targets: vec![Some(ColorTargetState {
format: TextureFormat::bevy_default(),
blend,
write_mask: ColorWrites::ALL,
}],
})],
}),
layout: Some(bind_group_layout),
primitive: PrimitiveState {

View file

@ -5,39 +5,29 @@
#import bevy_pbr::mesh_functions
struct Vertex {
[[location(0)]] position: vec3<f32>;
[[location(1)]] normal: vec3<f32>;
@location(0) position: vec3<f32>,
@location(1) normal: vec3<f32>,
#ifdef VERTEX_UVS
[[location(2)]] uv: vec2<f32>;
@location(2) uv: vec2<f32>,
#endif
#ifdef VERTEX_TANGENTS
[[location(3)]] tangent: vec4<f32>;
@location(3) tangent: vec4<f32>,
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
@location(4) color: vec4<f32>,
#endif
#ifdef SKINNED
[[location(5)]] joint_indices: vec4<u32>;
[[location(6)]] joint_weights: vec4<f32>;
@location(5) joint_indices: vec4<u32>,
@location(6) joint_weights: vec4<f32>,
#endif
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] world_position: vec4<f32>;
[[location(1)]] world_normal: vec3<f32>;
#ifdef VERTEX_UVS
[[location(2)]] uv: vec2<f32>;
#endif
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
#endif
@builtin(position) clip_position: vec4<f32>,
#import bevy_pbr::mesh_vertex_output
};
[[stage(vertex)]]
@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
#ifdef SKINNED
@ -63,22 +53,12 @@ fn vertex(vertex: Vertex) -> VertexOutput {
}
struct FragmentInput {
[[builtin(front_facing)]] is_front: bool;
[[location(0)]] world_position: vec4<f32>;
[[location(1)]] world_normal: vec3<f32>;
#ifdef VERTEX_UVS
[[location(2)]] uv: vec2<f32>;
#endif
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
#endif
@builtin(front_facing) is_front: bool,
#import bevy_pbr::mesh_vertex_output
};
[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
#ifdef VERTEX_COLORS
return in.color;
#else

View file

@ -2,10 +2,10 @@
#import bevy_pbr::mesh_types
[[group(2), binding(0)]]
@group(2) @binding(0)
var<uniform> mesh: Mesh;
#ifdef SKINNED
[[group(2), binding(1)]]
@group(2) @binding(1)
var<uniform> joint_matrices: SkinnedMesh;
#import bevy_pbr::skinning
#endif

View file

@ -1,15 +1,15 @@
#define_import_path bevy_pbr::mesh_types
struct Mesh {
model: mat4x4<f32>;
inverse_transpose_model: mat4x4<f32>;
model: mat4x4<f32>,
inverse_transpose_model: mat4x4<f32>,
// 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.
flags: u32;
flags: u32,
};
#ifdef SKINNED
struct SkinnedMesh {
data: array<mat4x4<f32>, 256u>;
data: array<mat4x4<f32>, 256u>,
};
#endif

View file

@ -0,0 +1,13 @@
#define_import_path bevy_pbr::mesh_vertex_output
@location(0) world_position: vec4<f32>,
@location(1) world_normal: vec3<f32>,
#ifdef VERTEX_UVS
@location(2) uv: vec2<f32>,
#endif
#ifdef VERTEX_TANGENTS
@location(3) world_tangent: vec4<f32>,
#endif
#ifdef VERTEX_COLORS
@location(4) color: vec4<f32>,
#endif

View file

@ -2,41 +2,41 @@
#import bevy_pbr::mesh_view_types
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
[[group(0), binding(1)]]
@group(0) @binding(1)
var<uniform> lights: Lights;
#ifdef NO_ARRAY_TEXTURES_SUPPORT
[[group(0), binding(2)]]
@group(0) @binding(2)
var point_shadow_textures: texture_depth_cube;
#else
[[group(0), binding(2)]]
@group(0) @binding(2)
var point_shadow_textures: texture_depth_cube_array;
#endif
[[group(0), binding(3)]]
@group(0) @binding(3)
var point_shadow_textures_sampler: sampler_comparison;
#ifdef NO_ARRAY_TEXTURES_SUPPORT
[[group(0), binding(4)]]
@group(0) @binding(4)
var directional_shadow_textures: texture_depth_2d;
#else
[[group(0), binding(4)]]
@group(0) @binding(4)
var directional_shadow_textures: texture_depth_2d_array;
#endif
[[group(0), binding(5)]]
@group(0) @binding(5)
var directional_shadow_textures_sampler: sampler_comparison;
#ifdef NO_STORAGE_BUFFERS_SUPPORT
[[group(0), binding(6)]]
@group(0) @binding(6)
var<uniform> point_lights: PointLights;
[[group(0), binding(7)]]
@group(0) @binding(7)
var<uniform> cluster_light_index_lists: ClusterLightIndexLists;
[[group(0), binding(8)]]
@group(0) @binding(8)
var<uniform> cluster_offsets_and_counts: ClusterOffsetsAndCounts;
#else
[[group(0), binding(6)]]
@group(0) @binding(6)
var<storage> point_lights: PointLights;
[[group(0), binding(7)]]
@group(0) @binding(7)
var<storage> cluster_light_index_lists: ClusterLightIndexLists;
[[group(0), binding(8)]]
@group(0) @binding(8)
var<storage> cluster_offsets_and_counts: ClusterOffsetsAndCounts;
#endif

View file

@ -1,51 +1,51 @@
#define_import_path bevy_pbr::mesh_view_types
struct View {
view_proj: mat4x4<f32>;
inverse_view_proj: mat4x4<f32>;
view: mat4x4<f32>;
inverse_view: mat4x4<f32>;
projection: mat4x4<f32>;
inverse_projection: mat4x4<f32>;
world_position: vec3<f32>;
width: f32;
height: f32;
view_proj: mat4x4<f32>,
inverse_view_proj: mat4x4<f32>,
view: mat4x4<f32>,
inverse_view: mat4x4<f32>,
projection: mat4x4<f32>,
inverse_projection: mat4x4<f32>,
world_position: vec3<f32>,
width: f32,
height: f32,
};
struct PointLight {
// For point lights: the lower-right 2x2 values of the projection matrix [2][2] [2][3] [3][2] [3][3]
// For spot lights: the direction (x,z), spot_scale and spot_offset
light_custom_data: vec4<f32>;
color_inverse_square_range: vec4<f32>;
position_radius: vec4<f32>;
light_custom_data: vec4<f32>,
color_inverse_square_range: vec4<f32>,
position_radius: vec4<f32>,
// 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.
flags: u32;
shadow_depth_bias: f32;
shadow_normal_bias: f32;
spot_light_tan_angle: f32;
flags: u32,
shadow_depth_bias: f32,
shadow_normal_bias: f32,
spot_light_tan_angle: f32,
};
let POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u;
let POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE: u32 = 2u;
struct DirectionalLight {
view_projection: mat4x4<f32>;
color: vec4<f32>;
direction_to_light: vec3<f32>;
view_projection: mat4x4<f32>,
color: vec4<f32>,
direction_to_light: vec3<f32>,
// 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.
flags: u32;
shadow_depth_bias: f32;
shadow_normal_bias: f32;
flags: u32,
shadow_depth_bias: f32,
shadow_normal_bias: f32,
};
let DIRECTIONAL_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u;
struct Lights {
// NOTE: this array size must be kept in sync with the constants defined bevy_pbr2/src/render/light.rs
directional_lights: array<DirectionalLight, 1u>;
ambient_color: vec4<f32>;
directional_lights: array<DirectionalLight, 1u>,
ambient_color: vec4<f32>,
// x/y/z dimensions and n_clusters in w
cluster_dimensions: vec4<u32>;
cluster_dimensions: vec4<u32>,
// xy are vec2<f32>(cluster_dimensions.xy) / vec2<f32>(view.width, view.height)
//
// For perspective projections:
@ -56,32 +56,32 @@ struct Lights {
// NOTE: near and far are +ve but -z is infront of the camera
// z is -near
// w is cluster_dimensions.z / (-far - -near)
cluster_factors: vec4<f32>;
n_directional_lights: u32;
spot_light_shadowmap_offset: i32;
cluster_factors: vec4<f32>,
n_directional_lights: u32,
spot_light_shadowmap_offset: i32,
};
#ifdef NO_STORAGE_BUFFERS_SUPPORT
struct PointLights {
data: array<PointLight, 256u>;
data: array<PointLight, 256u>,
};
struct ClusterLightIndexLists {
// each u32 contains 4 u8 indices into the PointLights array
data: array<vec4<u32>, 1024u>;
data: array<vec4<u32>, 1024u>,
};
struct ClusterOffsetsAndCounts {
// each u32 contains a 24-bit index into ClusterLightIndexLists in the high 24 bits
// and an 8-bit count of the number of lights in the low 8 bits
data: array<vec4<u32>, 1024u>;
data: array<vec4<u32>, 1024u>,
};
#else
struct PointLights {
data: array<PointLight>;
data: array<PointLight>,
};
struct ClusterLightIndexLists {
data: array<u32>;
data: array<u32>,
};
struct ClusterOffsetsAndCounts {
data: array<vec4<u32>>;
data: array<vec4<u32>>,
};
#endif

View file

@ -9,23 +9,13 @@
#import bevy_pbr::pbr_functions
struct FragmentInput {
[[builtin(front_facing)]] is_front: bool;
[[builtin(position)]] frag_coord: vec4<f32>;
[[location(0)]] world_position: vec4<f32>;
[[location(1)]] world_normal: vec3<f32>;
#ifdef VERTEX_UVS
[[location(2)]] uv: vec2<f32>;
#endif
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] color: vec4<f32>;
#endif
@builtin(front_facing) is_front: bool,
@builtin(position) frag_coord: vec4<f32>,
#import bevy_pbr::mesh_vertex_output
};
[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
var output_color: vec4<f32> = material.base_color;
#ifdef VERTEX_COLORS
output_color = output_color * in.color;

View file

@ -2,25 +2,25 @@
#import bevy_pbr::pbr_types
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> material: StandardMaterial;
[[group(1), binding(1)]]
@group(1) @binding(1)
var base_color_texture: texture_2d<f32>;
[[group(1), binding(2)]]
@group(1) @binding(2)
var base_color_sampler: sampler;
[[group(1), binding(3)]]
@group(1) @binding(3)
var emissive_texture: texture_2d<f32>;
[[group(1), binding(4)]]
@group(1) @binding(4)
var emissive_sampler: sampler;
[[group(1), binding(5)]]
@group(1) @binding(5)
var metallic_roughness_texture: texture_2d<f32>;
[[group(1), binding(6)]]
@group(1) @binding(6)
var metallic_roughness_sampler: sampler;
[[group(1), binding(7)]]
@group(1) @binding(7)
var occlusion_texture: texture_2d<f32>;
[[group(1), binding(8)]]
@group(1) @binding(8)
var occlusion_sampler: sampler;
[[group(1), binding(9)]]
@group(1) @binding(9)
var normal_map_texture: texture_2d<f32>;
[[group(1), binding(10)]]
@group(1) @binding(10)
var normal_map_sampler: sampler;

View file

@ -87,19 +87,19 @@ fn calculate_view(
}
struct PbrInput {
material: StandardMaterial;
occlusion: f32;
frag_coord: vec4<f32>;
world_position: vec4<f32>;
material: StandardMaterial,
occlusion: f32,
frag_coord: vec4<f32>,
world_position: vec4<f32>,
// Normalized world normal used for shadow mapping as normal-mapping is not used for shadow
// mapping
world_normal: vec3<f32>;
world_normal: vec3<f32>,
// Normalized normal-mapped world normal used for lighting
N: vec3<f32>;
N: vec3<f32>,
// Normalized view vector in world space, pointing from the fragment world position toward the
// view world position
V: vec3<f32>;
is_orthographic: bool;
V: vec3<f32>,
is_orthographic: bool,
};
// Creates a PbrInput with default values

View file

@ -244,7 +244,7 @@ fn spot_light(
R: vec3<f32>, F0: vec3<f32>, diffuseColor: vec3<f32>
) -> vec3<f32> {
// reuse the point light calculations
let point = point_light(world_position, light, roughness, NdotV, N, V, R, F0, diffuseColor);
let point_light = point_light(world_position, light, roughness, NdotV, N, V, R, F0, diffuseColor);
// reconstruct spot dir from x/z and y-direction flag
var spot_dir = vec3<f32>(light.light_custom_data.x, 0.0, light.light_custom_data.y);
@ -261,7 +261,7 @@ fn spot_light(
let attenuation = saturate(cd * light.light_custom_data.z + light.light_custom_data.w);
let spot_attenuation = attenuation * attenuation;
return point * spot_attenuation;
return point_light * spot_attenuation;
}
fn directional_light(light: DirectionalLight, roughness: f32, NdotV: f32, normal: vec3<f32>, view: vec3<f32>, R: vec3<f32>, F0: vec3<f32>, diffuseColor: vec3<f32>) -> vec3<f32> {

View file

@ -1,14 +1,14 @@
#define_import_path bevy_pbr::pbr_types
struct StandardMaterial {
base_color: vec4<f32>;
emissive: vec4<f32>;
perceptual_roughness: f32;
metallic: f32;
reflectance: f32;
base_color: vec4<f32>,
emissive: vec4<f32>,
perceptual_roughness: f32,
metallic: f32,
reflectance: f32,
// 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.
flags: u32;
alpha_cutoff: f32;
flags: u32,
alpha_cutoff: f32,
};
let STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT: u32 = 1u;

View file

@ -4,28 +4,14 @@
#define_import_path bevy_pbr::skinning
/// HACK: This works around naga not supporting matrix addition in SPIR-V
// translations. See https://github.com/gfx-rs/naga/issues/1527
fn add_matrix(
a: mat4x4<f32>,
b: mat4x4<f32>,
) -> mat4x4<f32> {
return mat4x4<f32>(
a[0] + b[0],
a[1] + b[1],
a[2] + b[2],
a[3] + b[3],
);
}
fn skin_model(
indexes: vec4<u32>,
weights: vec4<f32>,
) -> mat4x4<f32> {
var matrix = weights.x * joint_matrices.data[indexes.x];
matrix = add_matrix(matrix, weights.y * joint_matrices.data[indexes.y]);
matrix = add_matrix(matrix, weights.z * joint_matrices.data[indexes.z]);
return add_matrix(matrix, weights.w * joint_matrices.data[indexes.w]);
return weights.x * joint_matrices.data[indexes.x]
+ weights.y * joint_matrices.data[indexes.y]
+ weights.z * joint_matrices.data[indexes.z]
+ weights.w * joint_matrices.data[indexes.w];
}
fn inverse_transpose_3x3(in: mat3x3<f32>) -> mat3x3<f32> {

View file

@ -1,11 +1,11 @@
#import bevy_pbr::mesh_types
#import bevy_pbr::mesh_view_bindings
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> mesh: Mesh;
#ifdef SKINNED
[[group(1), binding(1)]]
@group(1) @binding(1)
var<uniform> joint_matrices: SkinnedMesh;
#import bevy_pbr::skinning
#endif
@ -14,18 +14,18 @@ var<uniform> joint_matrices: SkinnedMesh;
#import bevy_pbr::mesh_functions
struct Vertex {
[[location(0)]] position: vec3<f32>;
@location(0) position: vec3<f32>,
#ifdef SKINNED
[[location(4)]] joint_indexes: vec4<u32>;
[[location(5)]] joint_weights: vec4<f32>;
@location(4) joint_indexes: vec4<u32>,
@location(5) joint_weights: vec4<f32>,
#endif
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
@builtin(position) clip_position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
#ifdef SKINNED
let model = skin_model(vertex.joint_indexes, vertex.joint_weights);
@ -38,7 +38,7 @@ fn vertex(vertex: Vertex) -> VertexOutput {
return out;
}
[[stage(fragment)]]
fn fragment() -> [[location(0)]] vec4<f32> {
@fragment
fn fragment() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 1.0, 1.0, 1.0);
}

View file

@ -20,7 +20,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }
# other
erased-serde = "0.3"
downcast-rs = "1.2"
parking_lot = "0.11.0"
parking_lot = "0.12.1"
thiserror = "1.0"
once_cell = "1.11"
serde = "1"

View file

@ -48,9 +48,9 @@ bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }
image = { version = "0.24", default-features = false }
# misc
wgpu = { version = "0.12.0", features = ["spirv"] }
wgpu = { version = "0.13.1", features = ["spirv"] }
codespan-reporting = "0.11.0"
naga = { version = "0.8.0", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] }
naga = { version = "0.9.0", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] }
serde = { version = "1", features = ["derive"] }
bitflags = "1.2.1"
smallvec = { version = "1.6", features = ["union", "const_generics"] }
@ -62,7 +62,7 @@ futures-lite = "1.4.0"
anyhow = "1.0"
hex = "0.4.2"
hexasphere = "7.2"
parking_lot = "0.11.0"
parking_lot = "0.12.1"
regex = "1.5"
copyless = "0.1.5"
ddsfile = { version = "0.5.0", optional = true }

View file

@ -88,14 +88,14 @@ impl Node for CameraDriverNode {
let _span = bevy_utils::tracing::info_span!("no_camera_clear_pass").entered();
let pass_descriptor = RenderPassDescriptor {
label: Some("no_camera_clear_pass"),
color_attachments: &[RenderPassColorAttachment {
color_attachments: &[Some(RenderPassColorAttachment {
view: swap_chain_texture,
resolve_target: None,
ops: Operations {
load: LoadOp::Clear(wgpu::Color::BLACK),
store: true,
},
}],
})],
depth_stencil_attachment: None,
};

View file

@ -91,14 +91,14 @@ impl Deref for BindGroup {
///
/// ```wgsl
/// struct CoolMaterial {
/// color: vec4<f32>;
/// color: vec4<f32>,
/// };
///
/// [[group(1), binding(0)]]
/// @group(1) @binding(0)
/// var<uniform> material: CoolMaterial;
/// [[group(1), binding(1)]]
/// @group(1) @binding(1)
/// var color_texture: texture_2d<f32>;
/// [[group(1), binding(2)]]
/// @group(1) @binding(2)
/// var color_sampler: sampler;
/// ```
/// Note that the "group" index is determined by the usage context. It is not defined in [`AsBindGroup`]. For example, in Bevy material bind groups
@ -165,11 +165,11 @@ impl Deref for BindGroup {
/// In WGSL shaders, the binding would look like this:
/// ```wgsl
/// struct CoolMaterial {
/// color: vec4<f32>;
/// roughness: f32;
/// color: vec4<f32>,
/// roughness: f32,
/// };
///
/// [[group(1), binding(0)]]
/// @group(1) @binding(0)
/// var<uniform> material: CoolMaterial;
/// ```
///

View file

@ -166,7 +166,7 @@ pub struct FragmentState {
/// function with this name in the shader.
pub entry_point: Cow<'static, str>,
/// The color state of the render targets.
pub targets: Vec<ColorTargetState>,
pub targets: Vec<Option<ColorTargetState>>,
}
/// Describes a compute pipeline.

View file

@ -155,7 +155,7 @@ impl ShaderCache {
render_device
.wgpu_device()
.push_error_scope(wgpu::ErrorFilter::Validation);
let shader_module = render_device.create_shader_module(&module_descriptor);
let shader_module = render_device.create_shader_module(module_descriptor);
let error = render_device.wgpu_device().pop_error_scope();
// `now_or_never` will return Some if the future is ready and None otherwise.
@ -410,7 +410,7 @@ impl PipelineCache {
Some((
fragment_module,
fragment.entry_point.deref(),
&fragment.targets,
fragment.targets.as_slice(),
))
} else {
None

View file

@ -557,26 +557,26 @@ mod tests {
#[rustfmt::skip]
const WGSL: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
#ifdef TEXTURE
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d<f32>;
#endif
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -587,29 +587,29 @@ fn vertex(
const WGSL_ELSE: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
#ifdef TEXTURE
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d<f32>;
#else
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d_array<f32>;
#endif
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -620,28 +620,28 @@ fn vertex(
const WGSL_NESTED_IFDEF: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
# ifdef TEXTURE
# ifdef ATTRIBUTE
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d<f32>;
# endif
# endif
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -652,31 +652,31 @@ fn vertex(
const WGSL_NESTED_IFDEF_ELSE: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
# ifdef TEXTURE
# ifdef ATTRIBUTE
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d<f32>;
#else
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d_array<f32>;
# endif
# endif
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -690,24 +690,24 @@ fn vertex(
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d<f32>;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -732,22 +732,22 @@ fn vertex(
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -772,24 +772,24 @@ fn vertex(
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d_array<f32>;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -937,22 +937,22 @@ void bar() { }
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -977,24 +977,24 @@ fn vertex(
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d_array<f32>;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -1019,22 +1019,22 @@ fn vertex(
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -1059,22 +1059,22 @@ fn vertex(
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -1099,22 +1099,22 @@ fn vertex(
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -1139,24 +1139,24 @@ fn vertex(
#[rustfmt::skip]
const EXPECTED: &str = r"
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d<f32>;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;

View file

@ -226,6 +226,9 @@ pub async fn initialize_renderer(
max_compute_workgroups_per_dimension: limits
.max_compute_workgroups_per_dimension
.min(constrained_limits.max_compute_workgroups_per_dimension),
max_buffer_size: limits
.max_buffer_size
.min(constrained_limits.max_buffer_size),
};
}

View file

@ -2,9 +2,8 @@ use crate::render_resource::{
BindGroup, BindGroupLayout, Buffer, ComputePipeline, RawRenderPipelineDescriptor,
RenderPipeline, Sampler, Texture,
};
use futures_lite::future;
use std::sync::Arc;
use wgpu::{util::DeviceExt, BufferBindingType};
use wgpu::{util::DeviceExt, BufferAsyncError, BufferBindingType};
use super::RenderQueue;
@ -39,7 +38,7 @@ impl RenderDevice {
/// Creates a [`ShaderModule`](wgpu::ShaderModule) from either SPIR-V or WGSL source code.
#[inline]
pub fn create_shader_module(&self, desc: &wgpu::ShaderModuleDescriptor) -> wgpu::ShaderModule {
pub fn create_shader_module(&self, desc: wgpu::ShaderModuleDescriptor) -> wgpu::ShaderModule {
self.device.create_shader_module(desc)
}
@ -170,13 +169,13 @@ impl RenderDevice {
&self.device
}
pub fn map_buffer(&self, buffer: &wgpu::BufferSlice, map_mode: wgpu::MapMode) {
let data = buffer.map_async(map_mode);
self.poll(wgpu::Maintain::Wait);
assert!(
future::block_on(data).is_ok(),
"Failed to map buffer to host."
);
pub fn map_buffer(
&self,
buffer: &wgpu::BufferSlice,
map_mode: wgpu::MapMode,
callback: impl FnOnce(Result<(), BufferAsyncError>) + Send + 'static,
) {
buffer.map_async(map_mode, callback);
}
pub fn align_copy_bytes_per_row(row_bytes: usize) -> usize {

View file

@ -1,7 +1,7 @@
use basis_universal::{
BasisTextureType, DecodeFlags, TranscodeParameters, Transcoder, TranscoderTextureFormat,
};
use wgpu::{Extent3d, TextureDimension, TextureFormat};
use wgpu::{AstcBlock, AstcChannel, Extent3d, TextureDimension, TextureFormat};
use super::{CompressedImageFormats, Image, TextureError};
@ -139,10 +139,13 @@ pub fn get_transcoded_formats(
if supported_compressed_formats.contains(CompressedImageFormats::ASTC_LDR) {
(
TranscoderTextureFormat::ASTC_4x4_RGBA,
if is_srgb {
TextureFormat::Astc4x4RgbaUnormSrgb
} else {
TextureFormat::Astc4x4RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
},
)
} else if supported_compressed_formats.contains(CompressedImageFormats::BC) {

View file

@ -742,36 +742,7 @@ impl CompressedImageFormats {
| TextureFormat::EacR11Snorm
| TextureFormat::EacRg11Unorm
| TextureFormat::EacRg11Snorm => self.contains(CompressedImageFormats::ETC2),
TextureFormat::Astc4x4RgbaUnorm
| TextureFormat::Astc4x4RgbaUnormSrgb
| TextureFormat::Astc5x4RgbaUnorm
| TextureFormat::Astc5x4RgbaUnormSrgb
| TextureFormat::Astc5x5RgbaUnorm
| TextureFormat::Astc5x5RgbaUnormSrgb
| TextureFormat::Astc6x5RgbaUnorm
| TextureFormat::Astc6x5RgbaUnormSrgb
| TextureFormat::Astc6x6RgbaUnorm
| TextureFormat::Astc6x6RgbaUnormSrgb
| TextureFormat::Astc8x5RgbaUnorm
| TextureFormat::Astc8x5RgbaUnormSrgb
| TextureFormat::Astc8x6RgbaUnorm
| TextureFormat::Astc8x6RgbaUnormSrgb
| TextureFormat::Astc10x5RgbaUnorm
| TextureFormat::Astc10x5RgbaUnormSrgb
| TextureFormat::Astc10x6RgbaUnorm
| TextureFormat::Astc10x6RgbaUnormSrgb
| TextureFormat::Astc8x8RgbaUnorm
| TextureFormat::Astc8x8RgbaUnormSrgb
| TextureFormat::Astc10x8RgbaUnorm
| TextureFormat::Astc10x8RgbaUnormSrgb
| TextureFormat::Astc10x10RgbaUnorm
| TextureFormat::Astc10x10RgbaUnormSrgb
| TextureFormat::Astc12x10RgbaUnorm
| TextureFormat::Astc12x10RgbaUnormSrgb
| TextureFormat::Astc12x12RgbaUnorm
| TextureFormat::Astc12x12RgbaUnormSrgb => {
self.contains(CompressedImageFormats::ASTC_LDR)
}
TextureFormat::Astc { .. } => self.contains(CompressedImageFormats::ASTC_LDR),
_ => true,
}
}

View file

@ -11,7 +11,7 @@ use ktx2::{
BasicDataFormatDescriptor, ChannelTypeQualifiers, ColorModel, DataFormatDescriptorHeader,
Header, SampleInformation,
};
use wgpu::{Extent3d, TextureDimension, TextureFormat};
use wgpu::{AstcBlock, AstcChannel, Extent3d, TextureDimension, TextureFormat};
use super::{CompressedImageFormats, DataFormat, Image, TextureError, TranscodeFormat};
@ -239,10 +239,13 @@ pub fn get_transcoded_formats(
if supported_compressed_formats.contains(CompressedImageFormats::ASTC_LDR) {
(
TranscoderBlockFormat::ASTC_4x4,
if is_srgb {
TextureFormat::Astc4x4RgbaUnormSrgb
} else {
TextureFormat::Astc4x4RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
},
)
} else if supported_compressed_formats.contains(CompressedImageFormats::BC) {
@ -1016,159 +1019,35 @@ pub fn ktx2_dfd_to_texture_format(
)));
}
},
Some(ColorModel::ASTC) => match data_format_descriptor.texel_block_dimensions[0] {
4 => match data_format_descriptor.texel_block_dimensions[1] {
4 => {
if is_srgb {
TextureFormat::Astc4x4RgbaUnormSrgb
} else {
TextureFormat::Astc4x4RgbaUnorm
}
}
Some(ColorModel::ASTC) => TextureFormat::Astc {
block: match (
data_format_descriptor.texel_block_dimensions[0],
data_format_descriptor.texel_block_dimensions[1],
) {
(4, 4) => AstcBlock::B4x4,
(5, 4) => AstcBlock::B5x4,
(5, 5) => AstcBlock::B5x5,
(6, 5) => AstcBlock::B6x5,
(8, 5) => AstcBlock::B8x5,
(8, 8) => AstcBlock::B8x8,
(10, 5) => AstcBlock::B10x5,
(10, 6) => AstcBlock::B10x6,
(10, 8) => AstcBlock::B10x8,
(10, 10) => AstcBlock::B10x10,
(12, 10) => AstcBlock::B12x10,
(12, 12) => AstcBlock::B12x12,
d => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ASTC y-dimension: {}",
d
"Invalid ASTC dimension: {} x {}",
d.0, d.1
)))
}
},
5 => match data_format_descriptor.texel_block_dimensions[1] {
4 => {
if is_srgb {
TextureFormat::Astc5x4RgbaUnormSrgb
} else {
TextureFormat::Astc5x4RgbaUnorm
}
}
5 => {
if is_srgb {
TextureFormat::Astc5x5RgbaUnormSrgb
} else {
TextureFormat::Astc5x5RgbaUnorm
}
}
d => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ASTC y-dimension: {}",
d
)))
}
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
6 => match data_format_descriptor.texel_block_dimensions[1] {
5 => {
if is_srgb {
TextureFormat::Astc6x5RgbaUnormSrgb
} else {
TextureFormat::Astc6x5RgbaUnorm
}
}
6 => {
if is_srgb {
TextureFormat::Astc6x6RgbaUnormSrgb
} else {
TextureFormat::Astc6x6RgbaUnorm
}
}
d => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ASTC y-dimension: {}",
d
)))
}
},
8 => match data_format_descriptor.texel_block_dimensions[1] {
5 => {
if is_srgb {
TextureFormat::Astc8x5RgbaUnormSrgb
} else {
TextureFormat::Astc8x5RgbaUnorm
}
}
6 => {
if is_srgb {
TextureFormat::Astc8x6RgbaUnormSrgb
} else {
TextureFormat::Astc8x6RgbaUnorm
}
}
8 => {
if is_srgb {
TextureFormat::Astc8x8RgbaUnormSrgb
} else {
TextureFormat::Astc8x8RgbaUnorm
}
}
d => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ASTC y-dimension: {}",
d
)))
}
},
10 => match data_format_descriptor.texel_block_dimensions[1] {
5 => {
if is_srgb {
TextureFormat::Astc10x5RgbaUnormSrgb
} else {
TextureFormat::Astc10x5RgbaUnorm
}
}
6 => {
if is_srgb {
TextureFormat::Astc10x6RgbaUnormSrgb
} else {
TextureFormat::Astc10x6RgbaUnorm
}
}
8 => {
if is_srgb {
TextureFormat::Astc10x8RgbaUnormSrgb
} else {
TextureFormat::Astc10x8RgbaUnorm
}
}
10 => {
if is_srgb {
TextureFormat::Astc10x10RgbaUnormSrgb
} else {
TextureFormat::Astc10x10RgbaUnorm
}
}
d => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ASTC y-dimension: {}",
d
)))
}
},
12 => match data_format_descriptor.texel_block_dimensions[1] {
10 => {
if is_srgb {
TextureFormat::Astc12x10RgbaUnormSrgb
} else {
TextureFormat::Astc12x10RgbaUnorm
}
}
12 => {
if is_srgb {
TextureFormat::Astc12x12RgbaUnormSrgb
} else {
TextureFormat::Astc12x12RgbaUnorm
}
}
d => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ASTC y-dimension: {}",
d
)))
}
},
d => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ASTC x-dimension: {}",
d
)))
}
},
Some(ColorModel::ETC1S) => {
return Err(TextureError::FormatRequiresTranscodingError(
@ -1362,101 +1241,143 @@ pub fn ktx2_format_to_texture_format(
ktx2::Format::EAC_R11G11_UNORM_BLOCK => TextureFormat::EacRg11Unorm,
ktx2::Format::EAC_R11G11_SNORM_BLOCK => TextureFormat::EacRg11Snorm,
ktx2::Format::ASTC_4x4_UNORM_BLOCK | ktx2::Format::ASTC_4x4_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc4x4RgbaUnormSrgb
} else {
TextureFormat::Astc4x4RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_5x4_UNORM_BLOCK | ktx2::Format::ASTC_5x4_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc5x4RgbaUnormSrgb
} else {
TextureFormat::Astc5x4RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B5x4,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_5x5_UNORM_BLOCK | ktx2::Format::ASTC_5x5_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc5x5RgbaUnormSrgb
} else {
TextureFormat::Astc5x5RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B5x5,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_6x5_UNORM_BLOCK | ktx2::Format::ASTC_6x5_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc6x5RgbaUnormSrgb
} else {
TextureFormat::Astc6x5RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B6x5,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_6x6_UNORM_BLOCK | ktx2::Format::ASTC_6x6_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc6x6RgbaUnormSrgb
} else {
TextureFormat::Astc6x6RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B6x6,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_8x5_UNORM_BLOCK | ktx2::Format::ASTC_8x5_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc8x5RgbaUnormSrgb
} else {
TextureFormat::Astc8x5RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B8x5,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_8x6_UNORM_BLOCK | ktx2::Format::ASTC_8x6_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc8x6RgbaUnormSrgb
} else {
TextureFormat::Astc8x6RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B8x6,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_8x8_UNORM_BLOCK | ktx2::Format::ASTC_8x8_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc8x8RgbaUnormSrgb
} else {
TextureFormat::Astc8x8RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B8x8,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_10x5_UNORM_BLOCK | ktx2::Format::ASTC_10x5_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc10x5RgbaUnormSrgb
} else {
TextureFormat::Astc10x5RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B10x5,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_10x6_UNORM_BLOCK | ktx2::Format::ASTC_10x6_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc10x6RgbaUnormSrgb
} else {
TextureFormat::Astc10x6RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B10x6,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_10x8_UNORM_BLOCK | ktx2::Format::ASTC_10x8_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc10x8RgbaUnormSrgb
} else {
TextureFormat::Astc10x8RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B10x8,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_10x10_UNORM_BLOCK | ktx2::Format::ASTC_10x10_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc10x10RgbaUnormSrgb
} else {
TextureFormat::Astc10x10RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B10x10,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_12x10_UNORM_BLOCK | ktx2::Format::ASTC_12x10_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc12x10RgbaUnormSrgb
} else {
TextureFormat::Astc12x10RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B12x10,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_12x12_UNORM_BLOCK | ktx2::Format::ASTC_12x12_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Astc12x12RgbaUnormSrgb
} else {
TextureFormat::Astc12x12RgbaUnorm
TextureFormat::Astc {
block: AstcBlock::B12x12,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
_ => {

View file

@ -169,6 +169,8 @@ pub fn prepare_windows(
PresentMode::Fifo => wgpu::PresentMode::Fifo,
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
PresentMode::Immediate => wgpu::PresentMode::Immediate,
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
},
};

View file

@ -2,41 +2,33 @@
#import bevy_sprite::mesh2d_view_bindings
struct ColorMaterial {
color: vec4<f32>;
color: vec4<f32>,
// 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.
flags: u32;
flags: u32,
};
let COLOR_MATERIAL_FLAGS_TEXTURE_BIT: u32 = 1u;
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> material: ColorMaterial;
[[group(1), binding(1)]]
@group(1) @binding(1)
var texture: texture_2d<f32>;
[[group(1), binding(2)]]
@group(1) @binding(2)
var texture_sampler: sampler;
[[group(2), binding(0)]]
@group(2) @binding(0)
var<uniform> mesh: Mesh2d;
struct FragmentInput {
[[builtin(front_facing)]] is_front: bool;
[[location(0)]] world_position: vec4<f32>;
[[location(1)]] world_normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] colors: vec4<f32>;
#endif
@builtin(front_facing) is_front: bool,
#import bevy_sprite::mesh2d_vertex_output
};
[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
var output_color: vec4<f32> = material.color;
if ((material.flags & COLOR_MATERIAL_FLAGS_TEXTURE_BIT) != 0u) {
#ifdef VERTEX_COLORS
output_color = output_color * textureSample(texture, texture_sampler, in.uv) * in.colors;
output_color = output_color * textureSample(texture, texture_sampler, in.uv) * in.color;
#else
output_color = output_color * textureSample(texture, texture_sampler, in.uv);
#endif

View file

@ -37,6 +37,8 @@ impl From<Handle<Mesh>> for Mesh2dHandle {
#[derive(Default)]
pub struct Mesh2dRenderPlugin;
pub const MESH2D_VERTEX_OUTPUT: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 7646632476603252194);
pub const MESH2D_VIEW_TYPES_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 12677582416765805110);
pub const MESH2D_VIEW_BINDINGS_HANDLE: HandleUntyped =
@ -52,6 +54,12 @@ pub const MESH2D_SHADER_HANDLE: HandleUntyped =
impl Plugin for Mesh2dRenderPlugin {
fn build(&self, app: &mut bevy_app::App) {
load_internal_asset!(
app,
MESH2D_VERTEX_OUTPUT,
"mesh2d_vertex_output.wgsl",
Shader::from_wgsl
);
load_internal_asset!(
app,
MESH2D_VIEW_TYPES_HANDLE,
@ -344,11 +352,11 @@ impl SpecializedMeshPipeline for Mesh2dPipeline {
shader: MESH2D_SHADER_HANDLE.typed::<Shader>(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![ColorTargetState {
targets: vec![Some(ColorTargetState {
format: TextureFormat::bevy_default(),
blend: Some(BlendState::ALPHA_BLENDING),
write_mask: ColorWrites::ALL,
}],
})],
}),
layout: Some(vec![self.view_layout.clone(), self.mesh_layout.clone()]),
primitive: PrimitiveState {

View file

@ -5,31 +5,23 @@
#import bevy_sprite::mesh2d_functions
struct Vertex {
[[location(0)]] position: vec3<f32>;
[[location(1)]] normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;
@location(0) position: vec3<f32>,
@location(1) normal: vec3<f32>,
@location(2) uv: vec2<f32>,
#ifdef VERTEX_TANGENTS
[[location(3)]] tangent: vec4<f32>;
@location(3) tangent: vec4<f32>,
#endif
#ifdef VERTEX_COLORS
[[location(4)]] colors: vec4<f32>;
@location(4) color: vec4<f32>,
#endif
};
struct VertexOutput {
[[builtin(position)]] clip_position: vec4<f32>;
[[location(0)]] world_position: vec4<f32>;
[[location(1)]] world_normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
#ifdef VERTEX_COLORS
[[location(4)]] colors: vec4<f32>;
#endif
};
@builtin(position) clip_position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
}
[[stage(vertex)]]
@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex.uv;
@ -40,22 +32,17 @@ fn vertex(vertex: Vertex) -> VertexOutput {
out.world_tangent = mesh2d_tangent_local_to_world(vertex.tangent);
#endif
#ifdef VERTEX_COLORS
out.colors = vertex.colors;
out.color = vertex.color;
#endif
return out;
}
struct FragmentInput {
[[builtin(front_facing)]] is_front: bool;
[[location(0)]] world_position: vec4<f32>;
[[location(1)]] world_normal: vec3<f32>;
[[location(2)]] uv: vec2<f32>;
#ifdef VERTEX_TANGENTS
[[location(3)]] world_tangent: vec4<f32>;
#endif
@builtin(front_facing) is_front: bool,
#import bevy_sprite::mesh2d_vertex_output
};
[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 1.0, 1.0);
}

View file

@ -2,5 +2,5 @@
#import bevy_sprite::mesh2d_types
[[group(2), binding(0)]]
@group(2) @binding(0)
var<uniform> mesh: Mesh2d;

View file

@ -1,8 +1,8 @@
#define_import_path bevy_sprite::mesh2d_types
struct Mesh2d {
model: mat4x4<f32>;
inverse_transpose_model: mat4x4<f32>;
model: mat4x4<f32>,
inverse_transpose_model: mat4x4<f32>,
// 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options.
flags: u32;
flags: u32,
};

View file

@ -0,0 +1,11 @@
#define_import_path bevy_sprite::mesh2d_vertex_output
@location(0) world_position: vec4<f32>,
@location(1) world_normal: vec3<f32>,
@location(2) uv: vec2<f32>,
#ifdef VERTEX_TANGENTS
@location(3) world_tangent: vec4<f32>,
#endif
#ifdef VERTEX_COLORS
@location(4) color: vec4<f32>,
#endif

View file

@ -2,5 +2,5 @@
#import bevy_sprite::mesh2d_view_types
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;

View file

@ -1,11 +1,11 @@
#define_import_path bevy_sprite::mesh2d_view_types
struct View {
view_proj: mat4x4<f32>;
view: mat4x4<f32>;
inverse_view: mat4x4<f32>;
projection: mat4x4<f32>;
world_position: vec3<f32>;
width: f32;
height: f32;
view_proj: mat4x4<f32>,
view: mat4x4<f32>,
inverse_view: mat4x4<f32>,
projection: mat4x4<f32>,
world_position: vec3<f32>,
width: f32,
height: f32,
};

View file

@ -143,11 +143,11 @@ impl SpecializedRenderPipeline for SpritePipeline {
shader: SPRITE_SHADER_HANDLE.typed::<Shader>(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![ColorTargetState {
targets: vec![Some(ColorTargetState {
format: TextureFormat::bevy_default(),
blend: Some(BlendState::ALPHA_BLENDING),
write_mask: ColorWrites::ALL,
}],
})],
}),
layout: Some(vec![self.view_layout.clone(), self.material_layout.clone()]),
primitive: PrimitiveState {

View file

@ -1,24 +1,24 @@
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
@location(0) uv: vec2<f32>,
#ifdef COLORED
[[location(1)]] color: vec4<f32>;
@location(1) color: vec4<f32>,
#endif
[[builtin(position)]] position: vec4<f32>;
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>,
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>,
#ifdef COLORED
[[location(2)]] vertex_color: vec4<f32>,
@location(2) vertex_color: vec4<f32>,
#endif
) -> VertexOutput {
var out: VertexOutput;
@ -30,13 +30,13 @@ fn vertex(
return out;
}
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d<f32>;
[[group(1), binding(1)]]
@group(1) @binding(1)
var sprite_sampler: sampler;
[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
var color = textureSample(sprite_texture, sprite_sampler, in.uv);
#ifdef COLORED
color = in.color * color;

View file

@ -86,11 +86,11 @@ impl SpecializedRenderPipeline for UiPipeline {
shader: super::UI_SHADER_HANDLE.typed::<Shader>(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![ColorTargetState {
targets: vec![Some(ColorTargetState {
format: TextureFormat::bevy_default(),
blend: Some(BlendState::ALPHA_BLENDING),
write_mask: ColorWrites::ALL,
}],
})],
}),
layout: Some(vec![self.view_layout.clone(), self.image_layout.clone()]),
primitive: PrimitiveState {

View file

@ -81,14 +81,14 @@ impl Node for UiPassNode {
};
let pass_descriptor = RenderPassDescriptor {
label: Some("ui_pass"),
color_attachments: &[RenderPassColorAttachment {
color_attachments: &[Some(RenderPassColorAttachment {
view: &target.view,
resolve_target: None,
ops: Operations {
load: LoadOp::Load,
store: true,
},
}],
})],
depth_stencil_attachment: None,
};

View file

@ -1,21 +1,21 @@
struct View {
view_proj: mat4x4<f32>;
world_position: vec3<f32>;
view_proj: mat4x4<f32>,
world_position: vec3<f32>,
};
[[group(0), binding(0)]]
@group(0) @binding(0)
var<uniform> view: View;
struct VertexOutput {
[[location(0)]] uv: vec2<f32>;
[[location(1)]] color: vec4<f32>;
[[builtin(position)]] position: vec4<f32>;
@location(0) uv: vec2<f32>,
@location(1) color: vec4<f32>,
@builtin(position) position: vec4<f32>,
};
[[stage(vertex)]]
@vertex
fn vertex(
[[location(0)]] vertex_position: vec3<f32>,
[[location(1)]] vertex_uv: vec2<f32>,
[[location(2)]] vertex_color: vec4<f32>,
@location(0) vertex_position: vec3<f32>,
@location(1) vertex_uv: vec2<f32>,
@location(2) vertex_color: vec4<f32>,
) -> VertexOutput {
var out: VertexOutput;
out.uv = vertex_uv;
@ -24,13 +24,13 @@ fn vertex(
return out;
}
[[group(1), binding(0)]]
@group(1) @binding(0)
var sprite_texture: texture_2d<f32>;
[[group(1), binding(1)]]
@group(1) @binding(1)
var sprite_sampler: sampler;
[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
var color = textureSample(sprite_texture, sprite_sampler, in.uv);
color = in.color * color;
return color;

View file

@ -23,20 +23,34 @@ pub struct WindowId(Uuid);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[doc(alias = "vsync")]
pub enum PresentMode {
/// Chooses FifoRelaxed -> Fifo based on availability.
///
/// Because of the fallback behavior, it is supported everywhere.
AutoVsync = 0,
/// Chooses Immediate -> Mailbox -> Fifo (on web) based on availability.
///
/// Because of the fallback behavior, it is supported everywhere.
AutoNoVsync = 1,
/// The presentation engine does **not** wait for a vertical blanking period and
/// the request is presented immediately. This is a low-latency presentation mode,
/// but visible tearing may be observed. Will fallback to `Fifo` if unavailable on the
/// selected platform and backend. Not optimal for mobile.
Immediate = 0,
///
/// Selecting this variant will panic if not supported, it is preferred to use
/// [`PresentMode::AutoNoVsync`].
Immediate = 2,
/// The presentation engine waits for the next vertical blanking period to update
/// the current image, but frames may be submitted without delay. This is a low-latency
/// presentation mode and visible tearing will **not** be observed. Will fallback to `Fifo`
/// if unavailable on the selected platform and backend. Not optimal for mobile.
Mailbox = 1,
///
/// Selecting this variant will panic if not supported, it is preferred to use
/// [`PresentMode::AutoNoVsync`].
Mailbox = 3,
/// The presentation engine waits for the next vertical blanking period to update
/// the current image. The framerate will be capped at the display refresh rate,
/// corresponding to the `VSync`. Tearing cannot be observed. Optimal for mobile.
Fifo = 2, // NOTE: The explicit ordinal values mirror wgpu and the vulkan spec.
Fifo = 4, // NOTE: The explicit ordinal values mirror wgpu.
}
impl WindowId {

View file

@ -40,6 +40,8 @@ skip = [
{ name = "ndk", version = "0.5" }, # from winit v0.26.1
{ name = "ndk-glue", version = "0.5" }, # from winit v0.26.1
{ name = "ndk-sys", version = "0.2" }, # from winit v0.26.1
{ name = "parking_lot", version = "0.11" }, # from rodio v0.15.0
{ name = "parking_lot_core", version = "0.8" }, # from rodio v0.15.0
{ name = "stdweb", version = "0.1" }, # from rodio v0.15.0
{ name = "nix", version = "0.23.1" }, # from alsa v0.6.0
]

View file

@ -160,11 +160,11 @@ impl SpecializedRenderPipeline for ColoredMesh2dPipeline {
shader: COLORED_MESH2D_SHADER_HANDLE.typed::<Shader>(),
shader_defs: Vec::new(),
entry_point: "fragment".into(),
targets: vec![ColorTargetState {
targets: vec![Some(ColorTargetState {
format: TextureFormat::bevy_default(),
blend: Some(BlendState::ALPHA_BLENDING),
write_mask: ColorWrites::ALL,
}],
})],
}),
// Use the two standard uniforms for 2d meshes
layout: Some(vec![
@ -212,7 +212,7 @@ const COLORED_MESH2D_SHADER: &str = r"
#import bevy_sprite::mesh2d_types
#import bevy_sprite::mesh2d_view_bindings
[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> mesh: Mesh2d;
// NOTE: Bindings must come before functions that use them!
@ -220,19 +220,19 @@ var<uniform> mesh: Mesh2d;
// The structure of the vertex buffer is as specified in `specialize()`
struct Vertex {
[[location(0)]] position: vec3<f32>;
[[location(1)]] color: u32;
@location(0) position: vec3<f32>,
@location(1) color: u32,
};
struct VertexOutput {
// The vertex shader must set the on-screen position of the vertex
[[builtin(position)]] clip_position: vec4<f32>;
@builtin(position) clip_position: vec4<f32>,
// We pass the vertex color to the fragment shader in location 0
[[location(0)]] color: vec4<f32>;
@location(0) color: vec4<f32>,
};
/// Entry point for the vertex shader
[[stage(vertex)]]
@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
// Project the world position of the mesh into screen position
@ -245,12 +245,12 @@ fn vertex(vertex: Vertex) -> VertexOutput {
// The input of the fragment shader must correspond to the output of the vertex shader for all `location`s
struct FragmentInput {
// The color is interpolated between vertices by default
[[location(0)]] color: vec4<f32>;
@location(0) color: vec4<f32>,
};
/// Entry point for the fragment shader
[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
return in.color;
}
";

View file

@ -25,7 +25,7 @@ fn main() {
.insert_resource(ClearColor(Color::BLACK))
.insert_resource(WindowDescriptor {
// uncomment for unthrottled FPS
// present_mode: bevy::window::PresentMode::Immediate,
// present_mode: bevy::window::PresentMode::AutoNoVsync,
..default()
})
.add_plugins(DefaultPlugins)
@ -227,14 +227,14 @@ impl render_graph::Node for GameOfLifeNode {
.get_compute_pipeline(pipeline.init_pipeline)
.unwrap();
pass.set_pipeline(init_pipeline);
pass.dispatch(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1);
pass.dispatch_workgroups(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1);
}
GameOfLifeState::Update => {
let update_pipeline = pipeline_cache
.get_compute_pipeline(pipeline.update_pipeline)
.unwrap();
pass.set_pipeline(update_pipeline);
pass.dispatch(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1);
pass.dispatch_workgroups(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1);
}
}

View file

@ -32,7 +32,7 @@ fn main() {
title: "BevyMark".to_string(),
width: 800.,
height: 600.,
present_mode: PresentMode::Immediate,
present_mode: PresentMode::AutoNoVsync,
resizable: true,
..default()
})

View file

@ -20,7 +20,7 @@ use bevy::{
fn main() {
App::new()
.insert_resource(WindowDescriptor {
present_mode: PresentMode::Immediate,
present_mode: PresentMode::AutoNoVsync,
..default()
})
.add_plugins(DefaultPlugins)

View file

@ -17,7 +17,7 @@ fn main() {
App::new()
.insert_resource(WindowDescriptor {
title: "🦊🦊🦊 Many Foxes! 🦊🦊🦊".to_string(),
present_mode: PresentMode::Immediate,
present_mode: PresentMode::AutoNoVsync,
..default()
})
.add_plugins(DefaultPlugins)

View file

@ -17,7 +17,7 @@ fn main() {
width: 1024.0,
height: 768.0,
title: "many_lights".to_string(),
present_mode: PresentMode::Immediate,
present_mode: PresentMode::AutoNoVsync,
..default()
})
.add_plugins(DefaultPlugins)

View file

@ -26,7 +26,7 @@ struct ColorTint(bool);
fn main() {
App::new()
.insert_resource(WindowDescriptor {
present_mode: PresentMode::Immediate,
present_mode: PresentMode::AutoNoVsync,
..default()
})
.insert_resource(ColorTint(

View file

@ -9,7 +9,7 @@ use bevy::{
fn main() {
App::new()
.insert_resource(WindowDescriptor {
present_mode: PresentMode::Immediate,
present_mode: PresentMode::AutoNoVsync,
..default()
})
.add_plugins(DefaultPlugins)

View file

@ -27,7 +27,7 @@ fn main() {
})
// Turn off vsync to maximize CPU/GPU usage
.insert_resource(WindowDescriptor {
present_mode: PresentMode::Immediate,
present_mode: PresentMode::AutoNoVsync,
..default()
})
.insert_resource(ExampleMode::Game)

View file

@ -43,7 +43,7 @@ fn setup(
descriptor: WindowDescriptor {
width: 800.,
height: 600.,
present_mode: PresentMode::Immediate,
present_mode: PresentMode::AutoNoVsync,
title: "Second window".to_string(),
..default()
},

View file

@ -9,7 +9,7 @@ fn main() {
title: "I am a window!".to_string(),
width: 500.,
height: 300.,
present_mode: PresentMode::Fifo,
present_mode: PresentMode::AutoVsync,
..default()
})
.add_plugins(DefaultPlugins)