Skip to content

Commit

Permalink
[rs] Merge gfx-rs#369
Browse files Browse the repository at this point in the history
369: Implement SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING r=kvark a=cwfitzgerald

This implements gfx-rs#715 in wgpu-rs. I haven't changed the example, as I want to actually think up a better example to use and didn't want that to block this. It will change in the future however.

Co-authored-by: Connor Fitzgerald <[email protected]>
  • Loading branch information
bors[bot] and cwfitzgerald authored Jun 15, 2020
2 parents 4804fe4 + 8b60da5 commit f340882
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 39 deletions.
6 changes: 3 additions & 3 deletions wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ vulkan = ["wgc/gfx-backend-vulkan"]
package = "wgpu-core"
version = "0.5"
git = "https://github.com/gfx-rs/wgpu"
rev = "ad34c37127c8361bc2b07e8775816b2bbf8c0a73"
rev = "2dd3439475de6ea59488a91ea7d66096d3aecbbf"
features = ["raw-window-handle"]

[dependencies.wgt]
package = "wgpu-types"
version = "0.5"
git = "https://github.com/gfx-rs/wgpu"
rev = "ad34c37127c8361bc2b07e8775816b2bbf8c0a73"
rev = "2dd3439475de6ea59488a91ea7d66096d3aecbbf"

[dependencies]
arrayvec = "0.5"
Expand Down Expand Up @@ -73,7 +73,7 @@ test = true
#gfx-backend-vulkan = { version = "0.5.0", path = "../gfx/src/backend/vulkan" }
#gfx-backend-dx12 = { version = "0.5.0", path = "../gfx/src/backend/dx12" }
#gfx-backend-dx11 = { version = "0.5.0", path = "../gfx/src/backend/dx11" }
#gfx-backend-metal = { version = "0.5.0", path = "../gfx/src/backend/dx11" }
#gfx-backend-metal = { version = "0.5.0", path = "../gfx/src/backend/metal" }
#gfx-descriptor = { version = "0.1.0", path = "../gfx-extras/gfx-descriptor" }
#gfx-memory = { version = "0.1.0", path = "../gfx-extras/gfx-memory" }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#version 450

layout(location = 0) in vec2 v_TexCoord;
layout(location = 1) flat in int v_Index;
layout(location = 1) flat in int v_Index; // dynamically non-uniform
layout(location = 0) out vec4 o_Color;

layout(set = 0, binding = 0) uniform texture2D u_Textures[2];
Expand All @@ -13,6 +13,7 @@ void main() {
} else if (v_Index == 1) {
o_Color = vec4(texture(sampler2D(u_Textures[1], u_Sampler), v_TexCoord).rgb, 1.0);
} else {
o_Color = vec4(0.0, 0.0, 1.0, 1.0);
// We need to write something to output color
o_Color = vec4(0.0, 0.0, 1.0, 0.0);
}
}
Binary file not shown.
125 changes: 107 additions & 18 deletions wgpu/examples/texture-arrays/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ struct Vertex {
unsafe impl Pod for Vertex {}
unsafe impl Zeroable for Vertex {}

#[repr(C)]
#[derive(Clone, Copy)]
struct Uniform {
index: u32,
}

unsafe impl Pod for Uniform {}
unsafe impl Zeroable for Uniform {}

struct UniformWorkaroundData {
bind_group_layout: wgpu::BindGroupLayout,
bind_group0: wgpu::BindGroup,
bind_group1: wgpu::BindGroup,
}

fn vertex(pos: [i8; 2], tc: [i8; 2], index: i8) -> Vertex {
Vertex {
_pos: [pos[0] as f32, pos[1] as f32],
Expand Down Expand Up @@ -66,12 +81,13 @@ struct Example {
bind_group: wgpu::BindGroup,
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
uniform_workaround_data: Option<UniformWorkaroundData>,
}

impl framework::Example for Example {
fn needed_extensions() -> (wgpu::Extensions, wgpu::UnsafeExtensions) {
(
wgpu::Extensions::SAMPLED_TEXTURE_BINDING_ARRAY,
wgpu::Extensions::BINDING_INDEXING,
wgpu::UnsafeExtensions::disallow(),
)
}
Expand All @@ -80,12 +96,30 @@ impl framework::Example for Example {
device: &wgpu::Device,
queue: &wgpu::Queue,
) -> (Self, Option<wgpu::CommandBuffer>) {
let device_extensions = device.extensions();

assert!(
device_extensions.contains(wgpu::Extensions::SAMPLED_TEXTURE_BINDING_ARRAY),
"Graphics Device does not support SAMPLED_TEXTURE_BINDING_ARRAY extension"
);
let mut uniform_workaround = false;
let vs_bytes: &[u8] = include_bytes!("shader.vert.spv");
let fs_bytes: &[u8] = match device.capabilities() {
c if c.contains(wgpu::Capabilities::UNSIZED_BINDING_ARRAY) => {
include_bytes!("unsized-non-uniform.frag.spv")
}
c if c.contains(wgpu::Capabilities::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING) => {
include_bytes!("non-uniform.frag.spv")
}
c if c.contains(wgpu::Capabilities::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING) => {
uniform_workaround = true;
include_bytes!("uniform.frag.spv")
}
c if c.contains(wgpu::Capabilities::SAMPLED_TEXTURE_BINDING_ARRAY) => {
include_bytes!("constant.frag.spv")
}
_ => {
panic!("Graphics adapter does not support any of the capabilities needed for this example");
}
};
let vs_module =
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(vs_bytes)).unwrap());
let fs_module =
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(fs_bytes)).unwrap());

let vertex_size = std::mem::size_of::<Vertex>();
let vertex_data = create_vertices();
Expand All @@ -98,6 +132,54 @@ impl framework::Example for Example {
let index_buffer = device
.create_buffer_with_data(bytemuck::cast_slice(&index_data), wgpu::BufferUsage::INDEX);

let uniform_workaround_data = if uniform_workaround {
let buffer0 = device.create_buffer_with_data(
&bytemuck::cast_slice(&[Uniform { index: 0 }]),
wgpu::BufferUsage::UNIFORM,
);
let buffer1 = device.create_buffer_with_data(
&bytemuck::cast_slice(&[Uniform { index: 1 }]),
wgpu::BufferUsage::UNIFORM,
);

let bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
bindings: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
..wgpu::BindGroupLayoutEntry::default()
}],
label: Some("uniform workaround bind group layout"),
});

let bind_group0 = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
bindings: &[wgpu::Binding {
binding: 0,
resource: wgpu::BindingResource::Buffer(buffer0.slice(..)),
}],
label: Some("uniform workaround bind group 0"),
});

let bind_group1 = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
bindings: &[wgpu::Binding {
binding: 0,
resource: wgpu::BindingResource::Buffer(buffer1.slice(..)),
}],
label: Some("uniform workaround bind group 1"),
});

Some(UniformWorkaroundData {
bind_group_layout,
bind_group0,
bind_group1,
})
} else {
None
};

let red_texture_data = create_texture_data(Color::RED);
let green_texture_data = create_texture_data(Color::GREEN);

Expand Down Expand Up @@ -206,16 +288,15 @@ impl framework::Example for Example {
label: Some("bind group"),
});

let vs_bytes = include_bytes!("shader.vert.spv");
let fs_bytes = include_bytes!("shader.frag.spv");
let vs_module = device
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs_bytes[..])).unwrap());
let fs_module = device
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs_bytes[..])).unwrap());

let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout],
});
let pipeline_layout = if let Some(ref workaround) = uniform_workaround_data {
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout, &workaround.bind_group_layout],
})
} else {
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout],
})
};

let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
layout: &pipeline_layout,
Expand Down Expand Up @@ -261,6 +342,7 @@ impl framework::Example for Example {
index_buffer,
bind_group,
pipeline,
uniform_workaround_data,
},
None,
)
Expand Down Expand Up @@ -305,7 +387,14 @@ impl framework::Example for Example {
rpass.set_bind_group(0, &self.bind_group, &[]);
rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
rpass.set_index_buffer(self.index_buffer.slice(..));
rpass.draw_indexed(0..12, 0, 0..1);
if let Some(ref workaround) = self.uniform_workaround_data {
rpass.set_bind_group(1, &workaround.bind_group0, &[]);
rpass.draw_indexed(0..6, 0, 0..1);
rpass.set_bind_group(1, &workaround.bind_group1, &[]);
rpass.draw_indexed(6..12, 0, 0..1);
} else {
rpass.draw_indexed(0..12, 0, 0..1);
}

drop(rpass);

Expand Down
14 changes: 14 additions & 0 deletions wgpu/examples/texture-arrays/non-uniform.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#version 450

#extension GL_EXT_nonuniform_qualifier : require

layout(location = 0) in vec2 v_TexCoord;
layout(location = 1) flat in int v_Index; // dynamically non-uniform
layout(location = 0) out vec4 o_Color;

layout(set = 0, binding = 0) uniform texture2D u_Textures[2];
layout(set = 0, binding = 1) uniform sampler u_Sampler;

void main() {
o_Color = vec4(texture(sampler2D(u_Textures[v_Index], u_Sampler), v_TexCoord).rgb, 1.0);
}
Binary file added wgpu/examples/texture-arrays/non-uniform.frag.spv
Binary file not shown.
15 changes: 15 additions & 0 deletions wgpu/examples/texture-arrays/uniform.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#version 450

layout(location = 0) in vec2 v_TexCoord;
layout(location = 1) flat in int v_Index; // dynamically non-uniform
layout(location = 0) out vec4 o_Color;

layout(set = 0, binding = 0) uniform texture2D u_Textures[2];
layout(set = 0, binding = 1) uniform sampler u_Sampler;
layout(set = 1, binding = 0) uniform Uniforms {
int u_Index; // dynamically uniform
};

void main() {
o_Color = vec4(texture(sampler2D(u_Textures[u_Index], u_Sampler), v_TexCoord).rgb, 1.0);
}
Binary file added wgpu/examples/texture-arrays/uniform.frag.spv
Binary file not shown.
14 changes: 14 additions & 0 deletions wgpu/examples/texture-arrays/unsized-non-uniform.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#version 450

#extension GL_EXT_nonuniform_qualifier : require

layout(location = 0) in vec2 v_TexCoord;
layout(location = 1) flat in int v_Index; // dynamically non-uniform
layout(location = 0) out vec4 o_Color;

layout(set = 0, binding = 0) uniform texture2D u_Textures[];
layout(set = 0, binding = 1) uniform sampler u_Sampler;

void main() {
o_Color = vec4(texture(sampler2D(u_Textures[v_Index], u_Sampler), v_TexCoord).rgb, 1.0);
}
Binary file not shown.
14 changes: 11 additions & 3 deletions wgpu/src/backend/direct.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::{
backend::native_gpu_future, BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource,
BufferDescriptor, CommandEncoderDescriptor, ComputePipelineDescriptor, Extensions, Limits,
MapMode, PipelineLayoutDescriptor, RenderPipelineDescriptor, SamplerDescriptor,
SwapChainStatus, TextureDescriptor, TextureViewDescriptor,
BufferDescriptor, Capabilities, CommandEncoderDescriptor, ComputePipelineDescriptor,
Extensions, Limits, MapMode, PipelineLayoutDescriptor, RenderPipelineDescriptor,
SamplerDescriptor, SwapChainStatus, TextureDescriptor, TextureViewDescriptor,
};

use arrayvec::ArrayVec;
Expand Down Expand Up @@ -354,6 +354,10 @@ impl crate::Context for Context {
gfx_select!(*adapter => self.adapter_limits(*adapter))
}

fn adapter_capabilities(&self, adapter: &Self::AdapterId) -> Capabilities {
gfx_select!(*adapter => self.adapter_capabilities(*adapter))
}

fn device_extensions(&self, device: &Self::DeviceId) -> Extensions {
gfx_select!(*device => self.device_extensions(*device))
}
Expand All @@ -362,6 +366,10 @@ impl crate::Context for Context {
gfx_select!(*device => self.device_limits(*device))
}

fn device_capabilities(&self, device: &Self::DeviceId) -> Capabilities {
gfx_select!(*device => self.device_capabilities(*device))
}

fn device_create_swap_chain(
&self,
device: &Self::DeviceId,
Expand Down
16 changes: 13 additions & 3 deletions wgpu/src/backend/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,11 @@ impl crate::Context for Context {
wgt::Limits::default()
}

fn adapter_capabilities(&self, _adapter: &Self::AdapterId) -> wgt::Capabilities {
// TODO: webgpu doesn't support capabilities, so return an empty set of capabilities
wgt::Capabilities::default()
}

fn device_extensions(&self, _device: &Self::DeviceId) -> wgt::Extensions {
// TODO: web-sys has no way of getting extensions on devices
wgt::Extensions::empty()
Expand All @@ -735,6 +740,11 @@ impl crate::Context for Context {
wgt::Limits::default()
}

fn device_capabilities(&self, _device: &Self::DeviceId) -> wgt::Capabilities {
// TODO: webgpu doesn't support capabilities, so return an empty set of capabilities
wgt::Capabilities::default()
}

fn device_create_swap_chain(
&self,
device: &Self::DeviceId,
Expand Down Expand Up @@ -863,9 +873,9 @@ impl crate::Context for Context {
view: ref texture_view,
read_only_depth_stencil: _,
} => JsValue::from(texture_view.id.0.clone()),
BindingResource::TextureViewArray(..) => {
panic!("Web backend does not support TEXTURE_BINDING_ARRAY extension")
}
BindingResource::TextureViewArray(..) => panic!(
"Web backend does not support SAMPLED_TEXTURE_BINDING_ARRAY extension"
),
};

web_sys::GpuBindGroupEntry::new(binding.binding, &mapped_resource)
Expand Down
Loading

0 comments on commit f340882

Please sign in to comment.