Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ Bottom level categories:

## Unreleased

### New Features

#### OpenGL
- `@builtin(instance_index)` now properly reflects the range provided in the draw call instead of always counting from 0. By @cwfitzgerald in [#4722](https://github.com/gfx-rs/wgpu/pull/4722).

### Changes

#### General
Expand Down
1 change: 1 addition & 0 deletions naga/src/back/glsl/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,4 +480,5 @@ pub const RESERVED_KEYWORDS: &[&str] = &[
// Naga utilities:
super::MODF_FUNCTION,
super::FREXP_FUNCTION,
super::BASE_INSTANCE_BINDING,
];
17 changes: 15 additions & 2 deletions naga/src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ const CLAMPED_LOD_SUFFIX: &str = "_clamped_lod";
pub(crate) const MODF_FUNCTION: &str = "naga_modf";
pub(crate) const FREXP_FUNCTION: &str = "naga_frexp";

// Must match code in glsl_built_in
pub const BASE_INSTANCE_BINDING: &str = "naga_vs_base_instance";

/// Mapping between resources and bindings.
pub type BindingMap = std::collections::BTreeMap<crate::ResourceBinding, u8>;

Expand Down Expand Up @@ -569,7 +572,11 @@ impl<'a, W: Write> Writer<'a, W> {
keywords::RESERVED_KEYWORDS,
&[],
&[],
&["gl_"],
&[
"gl_", // all GL built-in variables
"_group", // all normal bindings
"_push_constant_binding_", // all push constant bindings
],
&mut names,
);

Expand Down Expand Up @@ -652,6 +659,11 @@ impl<'a, W: Write> Writer<'a, W> {
writeln!(self.out)?;
}

if self.entry_point.stage == ShaderStage::Vertex {
writeln!(self.out, "uniform uint {BASE_INSTANCE_BINDING};")?;
writeln!(self.out)?;
}

// Enable early depth tests if needed
if let Some(depth_test) = self.entry_point.early_depth_test {
// If early depth test is supported for this version of GLSL
Expand Down Expand Up @@ -4330,7 +4342,8 @@ const fn glsl_built_in(
Bi::BaseVertex => "uint(gl_BaseVertex)",
Bi::ClipDistance => "gl_ClipDistance",
Bi::CullDistance => "gl_CullDistance",
Bi::InstanceIndex => "uint(gl_InstanceID)",
// Must match BASE_INSTANCE_BINDING
Bi::InstanceIndex => "(uint(gl_InstanceID) + naga_vs_base_instance)",
Bi::PointSize => "gl_PointSize",
Bi::VertexIndex => "uint(gl_VertexID)",
// fragment
Expand Down
3 changes: 2 additions & 1 deletion naga/tests/in/push-constants.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ struct FragmentIn {
@vertex
fn vert_main(
@location(0) pos : vec2<f32>,
@builtin(instance_index) ii: u32,
@builtin(vertex_index) vi: u32,
) -> @builtin(position) vec4<f32> {
return vec4<f32>(f32(vi) * pc.multiplier * pos, 0.0, 1.0);
return vec4<f32>(f32(ii) * f32(vi) * pc.multiplier * pos, 0.0, 1.0);
}

@fragment
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/out/glsl/access.foo_vert.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

struct GlobalConst {
uint a;
uvec3 b;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;


void main() {
uint in_vertex_index = uint(gl_VertexID);
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/out/glsl/image.queries.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

uniform highp sampler2D _group_0_binding_0_vs;

uniform highp sampler2D _group_0_binding_1_vs;
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/out/glsl/interpolate.vert_main.Vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#version 400 core
uniform uint naga_vs_base_instance;

struct FragmentInput {
vec4 position;
uint _flat;
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/out/glsl/invariant.vs.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

invariant gl_Position;

void main() {
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/out/glsl/padding.vertex.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

struct S {
vec3 a;
};
Expand Down
7 changes: 5 additions & 2 deletions naga/tests/out/glsl/push-constants.vert_main.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

struct PushConstants {
float multiplier;
};
Expand All @@ -15,9 +17,10 @@ layout(location = 0) in vec2 _p2vs_location0;

void main() {
vec2 pos = _p2vs_location0;
uint ii = (uint(gl_InstanceID) + naga_vs_base_instance);
uint vi = uint(gl_VertexID);
float _e5 = _push_constant_binding_vs.multiplier;
gl_Position = vec4(((float(vi) * _e5) * pos), 0.0, 1.0);
float _e8 = _push_constant_binding_vs.multiplier;
gl_Position = vec4((((float(ii) * float(vi)) * _e8) * pos), 0.0, 1.0);
return;
}

2 changes: 2 additions & 0 deletions naga/tests/out/glsl/quad-vert.main.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

struct gen_gl_PerVertex {
vec4 gen_gl_Position;
float gen_gl_PointSize;
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/out/glsl/quad.vert_main.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

struct VertexOutput {
vec2 uv;
vec4 position;
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/out/glsl/shadow.vs_main.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

struct Globals {
mat4x4 view_proj;
uvec4 num_lights;
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/out/glsl/skybox.vs_main.Vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
precision highp float;
precision highp int;

uniform uint naga_vs_base_instance;

struct VertexOutput {
vec4 position;
vec3 uv;
Expand Down
6 changes: 3 additions & 3 deletions naga/tests/out/hlsl/push-constants.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ struct FragmentInput_main {
float4 color : LOC0;
};

float4 vert_main(float2 pos : LOC0, uint vi : SV_VertexID) : SV_Position
float4 vert_main(float2 pos : LOC0, uint ii : SV_InstanceID, uint vi : SV_VertexID) : SV_Position
{
float _expr5 = pc.multiplier;
return float4(((float((_NagaConstants.base_vertex + vi)) * _expr5) * pos), 0.0, 1.0);
float _expr8 = pc.multiplier;
return float4((((float((_NagaConstants.base_instance + ii)) * float((_NagaConstants.base_vertex + vi))) * _expr8) * pos), 0.0, 1.0);
}

float4 main(FragmentInput_main fragmentinput_main) : SV_Target0
Expand Down
6 changes: 2 additions & 4 deletions tests/tests/vertex_indices/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::num::NonZeroU64;

use wgpu::util::DeviceExt;

use wgpu_test::{gpu_test, FailureCase, GpuTestConfiguration, TestParameters, TestingContext};
use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters, TestingContext};

fn pulling_common(
ctx: TestingContext,
Expand Down Expand Up @@ -186,9 +186,7 @@ static DRAW_INSTANCED_OFFSET: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.test_features_limits()
.features(wgpu::Features::VERTEX_WRITABLE_STORAGE)
// https://github.com/gfx-rs/wgpu/issues/4276
.expect_fail(FailureCase::backend(wgpu::Backends::GL)),
.features(wgpu::Features::VERTEX_WRITABLE_STORAGE),
)
.run_sync(|ctx| {
pulling_common(ctx, &[0, 1, 2, 3, 4, 5], |cmb| {
Expand Down
18 changes: 14 additions & 4 deletions wgpu-hal/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub(super) struct State {
instance_vbuf_mask: usize,
dirty_vbuf_mask: usize,
active_first_instance: u32,
base_instance_location: Option<glow::UniformLocation>,
push_constant_descs: ArrayVec<super::PushConstantDesc, { super::MAX_PUSH_CONSTANT_COMMANDS }>,
// The current state of the push constant data block.
current_push_constant_data: [u32; super::MAX_PUSH_CONSTANTS],
Expand Down Expand Up @@ -57,6 +58,7 @@ impl Default for State {
instance_vbuf_mask: Default::default(),
dirty_vbuf_mask: Default::default(),
active_first_instance: Default::default(),
base_instance_location: Default::default(),
push_constant_descs: Default::default(),
current_push_constant_data: [0; super::MAX_PUSH_CONSTANTS],
end_of_pass_timestamp: Default::default(),
Expand Down Expand Up @@ -203,9 +205,11 @@ impl super::CommandEncoder {
}
}

#[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation
fn set_pipeline_inner(&mut self, inner: &super::PipelineInner) {
self.cmd_buffer.commands.push(C::SetProgram(inner.program));

self.state.base_instance_location = inner.base_instance_location.clone();
self.state.push_constant_descs = inner.push_constant_descs.clone();

// rebind textures, if needed
Expand Down Expand Up @@ -1004,38 +1008,44 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
&mut self,
start_vertex: u32,
vertex_count: u32,
start_instance: u32,
base_instance: u32,
instance_count: u32,
) {
self.prepare_draw(start_instance);
self.prepare_draw(base_instance);
#[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation
self.cmd_buffer.commands.push(C::Draw {
topology: self.state.topology,
start_vertex,
vertex_count,
base_instance,
instance_count,
base_instance_location: self.state.base_instance_location.clone(),
});
}
unsafe fn draw_indexed(
&mut self,
start_index: u32,
index_count: u32,
base_vertex: i32,
start_instance: u32,
base_instance: u32,
instance_count: u32,
) {
self.prepare_draw(start_instance);
self.prepare_draw(base_instance);
let (index_size, index_type) = match self.state.index_format {
wgt::IndexFormat::Uint16 => (2, glow::UNSIGNED_SHORT),
wgt::IndexFormat::Uint32 => (4, glow::UNSIGNED_INT),
};
let index_offset = self.state.index_offset + index_size * start_index as wgt::BufferAddress;
#[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation
self.cmd_buffer.commands.push(C::DrawIndexed {
topology: self.state.topology,
index_type,
index_offset,
index_count,
base_vertex,
base_instance,
instance_count,
base_instance_location: self.state.base_instance_location.clone(),
});
}
unsafe fn draw_indirect(
Expand Down
8 changes: 8 additions & 0 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,9 +467,17 @@ impl super::Device {
}
}

let base_instance_location = if has_stages.contains(wgt::ShaderStages::VERTEX) {
// If this returns none (the uniform isn't active), that's fine, we just won't set it.
unsafe { gl.get_uniform_location(program, naga::back::glsl::BASE_INSTANCE_BINDING) }
} else {
None
};

Ok(Arc::new(super::PipelineInner {
program,
sampler_map,
base_instance_location,
push_constant_descs: uniforms,
}))
}
Expand Down
31 changes: 31 additions & 0 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ type SamplerBindMap = [Option<u8>; MAX_TEXTURE_SLOTS];
struct PipelineInner {
program: glow::Program,
sampler_map: SamplerBindMap,
base_instance_location: Option<glow::UniformLocation>,
push_constant_descs: ArrayVec<PushConstantDesc, MAX_PUSH_CONSTANT_COMMANDS>,
}

Expand Down Expand Up @@ -712,15 +713,19 @@ enum Command {
topology: u32,
start_vertex: u32,
vertex_count: u32,
base_instance: u32,
instance_count: u32,
base_instance_location: Option<glow::UniformLocation>,
},
DrawIndexed {
topology: u32,
index_type: u32,
index_count: u32,
index_offset: wgt::BufferAddress,
base_vertex: i32,
base_instance: u32,
instance_count: u32,
base_instance_location: Option<glow::UniformLocation>,
},
DrawIndirect {
topology: u32,
Expand Down Expand Up @@ -909,6 +914,19 @@ impl fmt::Debug for CommandBuffer {
}
}

#[cfg(all(
target_arch = "wasm32",
feature = "fragile-send-sync-non-atomic-wasm",
not(target_feature = "atomics")
))]
unsafe impl Sync for CommandBuffer {}
#[cfg(all(
target_arch = "wasm32",
feature = "fragile-send-sync-non-atomic-wasm",
not(target_feature = "atomics")
))]
unsafe impl Send for CommandBuffer {}

//TODO: we would have something like `Arc<typed_arena::Arena>`
// here and in the command buffers. So that everything grows
// inside the encoder and stays there until `reset_all`.
Expand All @@ -927,6 +945,19 @@ impl fmt::Debug for CommandEncoder {
}
}

#[cfg(all(
target_arch = "wasm32",
feature = "fragile-send-sync-non-atomic-wasm",
not(target_feature = "atomics")
))]
unsafe impl Sync for CommandEncoder {}
#[cfg(all(
target_arch = "wasm32",
feature = "fragile-send-sync-non-atomic-wasm",
not(target_feature = "atomics")
))]
unsafe impl Send for CommandEncoder {}

#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) {
let source_str = match source {
Expand Down
Loading