Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ SamplerDescriptor {

- Texture now has `from_custom`. By @R-Cramer4 in [#8315](https://github.com/gfx-rs/wgpu/pull/8315).

### Added/New Features

## General

- Implement shader triangle barycentric coordinate builtins. By @atlv24 in [#8320](https://github.com/gfx-rs/wgpu/pull/8320).

### Bug Fixes

- Fixed bug where mapping sub-ranges of a buffer on web would fail with `OperationError: GPUBuffer.getMappedRange: GetMappedRange range extends beyond buffer's mapped range`. By @ryankaplan in [#8349](https://github.com/gfx-rs/wgpu/pull/8349)
Expand Down
1 change: 1 addition & 0 deletions naga/src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5227,6 +5227,7 @@ const fn glsl_built_in(built_in: crate::BuiltIn, options: VaryingOptions) -> &'s
Bi::PointCoord => "gl_PointCoord",
Bi::FrontFacing => "gl_FrontFacing",
Bi::PrimitiveIndex => "uint(gl_PrimitiveID)",
Bi::Barycentric => "gl_BaryCoordEXT",
Bi::SampleIndex => "gl_SampleID",
Bi::SampleMask => {
if options.output {
Expand Down
1 change: 1 addition & 0 deletions naga/src/back/hlsl/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ impl crate::BuiltIn {
Self::FragDepth => "SV_Depth",
Self::FrontFacing => "SV_IsFrontFace",
Self::PrimitiveIndex => "SV_PrimitiveID",
Self::Barycentric => "SV_Barycentrics",
Self::SampleIndex => "SV_SampleIndex",
Self::SampleMask => "SV_Coverage",
// compute
Expand Down
10 changes: 8 additions & 2 deletions naga/src/back/msl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,15 @@ impl Options {
return Err(Error::UnsupportedAttribute("instance_id".to_string()));
}
// macOS: Since Metal 2.2
// iOS: Since Metal 2.3 (check depends on https://github.com/gfx-rs/naga/issues/2164)
crate::BuiltIn::PrimitiveIndex if self.lang_version < (2, 2) => {
// iOS: Since Metal 2.3 (check depends on https://github.com/gfx-rs/wgpu/issues/4414)
crate::BuiltIn::PrimitiveIndex if self.lang_version < (2, 3) => {
return Err(Error::UnsupportedAttribute("primitive_id".to_string()));
}
// macOS: Since Metal 2.2
// iOS: Since Metal 2.3 (check depends on https://github.com/gfx-rs/wgpu/issues/4414)
crate::BuiltIn::Barycentric if self.lang_version < (2, 3) => {
return Err(Error::UnsupportedAttribute("barycentric_coord".to_string()));
}
_ => {}
}

Expand Down Expand Up @@ -680,6 +685,7 @@ impl ResolvedBinding {
Bi::PointCoord => "point_coord",
Bi::FrontFacing => "front_facing",
Bi::PrimitiveIndex => "primitive_id",
Bi::Barycentric => "barycentric_coord",
Bi::SampleIndex => "sample_id",
Bi::SampleMask => "sample_mask",
// compute
Expand Down
7 changes: 7 additions & 0 deletions naga/src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,13 @@ impl Writer {
)?;
BuiltIn::PrimitiveId
}
Bi::Barycentric => {
self.require_any(
"`barycentric` built-in",
&[spirv::Capability::FragmentBarycentricKHR],
)?;
BuiltIn::BaryCoordKHR
}
Bi::SampleIndex => {
self.require_any(
"`sample_index` built-in",
Expand Down
1 change: 1 addition & 0 deletions naga/src/common/wgsl/to_wgsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ impl TryToWgsl for crate::BuiltIn {
Bi::FragDepth => "frag_depth",
Bi::FrontFacing => "front_facing",
Bi::PrimitiveIndex => "primitive_index",
Bi::Barycentric => "barycentric",
Bi::SampleIndex => "sample_index",
Bi::SampleMask => "sample_mask",
Bi::GlobalInvocationId => "global_invocation_id",
Expand Down
1 change: 1 addition & 0 deletions naga/src/front/glsl/variables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ impl Frontend {
"gl_BaseVertex" => BuiltIn::BaseVertex,
"gl_BaseInstance" => BuiltIn::BaseInstance,
"gl_PrimitiveID" => BuiltIn::PrimitiveIndex,
"gl_BaryCoordEXT" => BuiltIn::Barycentric,
"gl_InstanceIndex" => BuiltIn::InstanceIndex,
"gl_VertexIndex" => BuiltIn::VertexIndex,
"gl_SampleID" => BuiltIn::SampleIndex,
Expand Down
1 change: 1 addition & 0 deletions naga/src/front/spv/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ pub(super) fn map_builtin(word: spirv::Word, invariant: bool) -> Result<crate::B
Some(Bi::PointCoord) => crate::BuiltIn::PointCoord,
Some(Bi::FrontFacing) => crate::BuiltIn::FrontFacing,
Some(Bi::PrimitiveId) => crate::BuiltIn::PrimitiveIndex,
Some(Bi::BaryCoordKHR) => crate::BuiltIn::Barycentric,
Some(Bi::SampleId) => crate::BuiltIn::SampleIndex,
Some(Bi::SampleMask) => crate::BuiltIn::SampleMask,
// compute
Expand Down
4 changes: 4 additions & 0 deletions naga/src/front/spv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6038,6 +6038,10 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
size: crate::VectorSize::Tri,
scalar: crate::Scalar::U32,
}),
crate::BuiltIn::Barycentric => Some(crate::TypeInner::Vector {
size: crate::VectorSize::Tri,
scalar: crate::Scalar::F32,
}),
_ => None,
};
if let (Some(inner), Some(crate::ScalarKind::Sint)) =
Expand Down
1 change: 1 addition & 0 deletions naga/src/front/wgsl/parse/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub fn map_built_in(
"front_facing" => crate::BuiltIn::FrontFacing,
"frag_depth" => crate::BuiltIn::FragDepth,
"primitive_index" => crate::BuiltIn::PrimitiveIndex,
"barycentric" => crate::BuiltIn::Barycentric,
"sample_index" => crate::BuiltIn::SampleIndex,
"sample_mask" => crate::BuiltIn::SampleMask,
// compute
Expand Down
1 change: 1 addition & 0 deletions naga/src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ pub enum BuiltIn {
PointCoord,
FrontFacing,
PrimitiveIndex,
Barycentric,
SampleIndex,
SampleMask,
// compute
Expand Down
9 changes: 9 additions & 0 deletions naga/src/valid/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ impl VaryingContext<'_> {
Bi::ClipDistance => Capabilities::CLIP_DISTANCE,
Bi::CullDistance => Capabilities::CULL_DISTANCE,
Bi::PrimitiveIndex => Capabilities::PRIMITIVE_INDEX,
Bi::Barycentric => Capabilities::SHADER_BARYCENTRICS,
Bi::ViewIndex => Capabilities::MULTIVIEW,
Bi::SampleIndex => Capabilities::MULTISAMPLED_SHADING,
Bi::NumSubgroups
Expand Down Expand Up @@ -267,6 +268,14 @@ impl VaryingContext<'_> {
self.stage == St::Fragment && !self.output,
*ty_inner == Ti::Scalar(crate::Scalar::U32),
),
Bi::Barycentric => (
self.stage == St::Fragment && !self.output,
*ty_inner
== Ti::Vector {
size: Vs::Tri,
scalar: crate::Scalar::F32,
},
),
Bi::SampleIndex => (
self.stage == St::Fragment && !self.output,
*ty_inner == Ti::Scalar(crate::Scalar::U32),
Expand Down
2 changes: 2 additions & 0 deletions naga/src/valid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ bitflags::bitflags! {
/// Support for `quantizeToF16`, `pack2x16float`, and `unpack2x16float`, which store
/// `f16`-precision values in `f32`s.
const SHADER_FLOAT16_IN_FLOAT32 = 1 << 28;
/// Support for fragment shader barycentric coordinates.
const SHADER_BARYCENTRICS = 1 << 29;
}
}

Expand Down
2 changes: 2 additions & 0 deletions tests/tests/wgpu-gpu/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ mod resource_error;
mod samplers;
mod scissor_tests;
mod shader;
mod shader_barycentric;
mod shader_primitive_index;
mod shader_view_format;
mod subgroup_operations;
Expand Down Expand Up @@ -126,6 +127,7 @@ fn all_tests() -> Vec<wgpu_test::GpuTestInitializer> {
samplers::all_tests(&mut tests);
scissor_tests::all_tests(&mut tests);
shader_primitive_index::all_tests(&mut tests);
shader_barycentric::all_tests(&mut tests);
shader_view_format::all_tests(&mut tests);
shader::all_tests(&mut tests);
subgroup_operations::all_tests(&mut tests);
Expand Down
9 changes: 9 additions & 0 deletions tests/tests/wgpu-gpu/shader_barycentric/barycentric.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@vertex
fn vs_main(@location(0) xy: vec2<f32>) -> @builtin(position) vec4<f32> {
return vec4<f32>(xy, 0.0, 1.0);
}

@fragment
fn fs_main(@builtin(barycentric) bary: vec3<f32>) -> @location(0) vec4<f32> {
return vec4<f32>(bary * 1.1 - 0.05, 1.0);
}
164 changes: 164 additions & 0 deletions tests/tests/wgpu-gpu/shader_barycentric/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use wgpu::util::DeviceExt;
use wgpu_test::{gpu_test, GpuTestConfiguration, TestParameters, TestingContext};

pub fn all_tests(vec: &mut Vec<wgpu_test::GpuTestInitializer>) {
vec.push(BARYCENTRIC);
}

//
// This test renders one triangle to a 2x2 render target. The triangle
// covers the bottom-left, bottom-right, and the top-left pixel.
// XY layout of the render target, with the triangle:
//
// (-1,1) (0,1) (1,1)
// +------+------+
// | | |
// | o | |
// | |\ | |
// | | \| |
// (-1,0) +---|--\------+ (1,0)
// | | |\ |
// | | | \ |
// | o--+--o |
// | | |
// +------+------+
// (-1,-1) (0,-1) (1,-1)
//
// The fragment shader outputs color based on builtin(barycentric):
//
// return vec4<f32>(bary * 1.1 - 0.05, 1.0);
//

#[gpu_test]
static BARYCENTRIC: GpuTestConfiguration = GpuTestConfiguration::new()
.parameters(
TestParameters::default()
.test_features_limits()
.features(wgpu::Features::SHADER_BARYCENTRICS),
)
.run_async(barycentric);

async fn barycentric(ctx: TestingContext) {
let shader = ctx
.device
.create_shader_module(wgpu::include_wgsl!("barycentric.wgsl"));

let n = -0.505;
let p = 0.51;
let triangle_xy: [f32; 6] = [n, n, p, n, n, p];
let vertex_buffer = ctx
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None,
contents: bytemuck::cast_slice(&triangle_xy),
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
});

let indices = [0u32, 1, 2];
let index_buffer = ctx
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None,
contents: bytemuck::cast_slice(&indices),
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
});

let pipeline = ctx
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: None,
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_main"),
compilation_options: Default::default(),
buffers: &[wgpu::VertexBufferLayout {
array_stride: 8,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[wgpu::VertexAttribute {
format: wgpu::VertexFormat::Float32x2,
offset: 0,
shader_location: 0,
}],
}],
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_main"),
compilation_options: Default::default(),
targets: &[Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: None,
write_mask: wgpu::ColorWrites::ALL,
})],
}),
multiview: None,
cache: None,
});

let width = 2;
let height = 2;
let texture_size = wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
};
let color_texture = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: None,
size: texture_size,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8Unorm,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
view_formats: &[],
});
let color_view = color_texture.create_view(&wgpu::TextureViewDescriptor::default());

let readback_buffer = wgpu_test::image::ReadbackBuffers::new(&ctx.device, &color_texture);

let mut encoder = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
{
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::WHITE),
store: wgpu::StoreOp::Store,
},
resolve_target: None,
view: &color_view,
depth_slice: None,
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});

rpass.set_pipeline(&pipeline);
rpass.set_index_buffer(index_buffer.slice(..), wgpu::IndexFormat::Uint32);
rpass.set_vertex_buffer(0, vertex_buffer.slice(..));
rpass.draw(0..3, 0..1);
}
readback_buffer.copy_from(&ctx.device, &mut encoder, &color_texture);
ctx.queue.submit(Some(encoder.finish()));

//
// +-----+-----+
// |blue |white|
// +-----+-----+
// | red |green|
// +-----+-----+
//
let expected = [
0, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0, 255, 0, 255,
];
readback_buffer
.assert_buffer_contents(&ctx, &expected)
.await;
}
4 changes: 4 additions & 0 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,10 @@ pub fn create_validator(
Caps::TEXTURE_EXTERNAL,
features.intersects(wgt::Features::EXTERNAL_TEXTURE),
);
caps.set(
Caps::SHADER_BARYCENTRICS,
features.intersects(wgt::Features::SHADER_BARYCENTRICS),
);

naga::valid::Validator::new(flags, caps)
}
17 changes: 17 additions & 0 deletions wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,23 @@ impl super::Adapter {
wgt::Features::EXPERIMENTAL_MESH_SHADER,
mesh_shader_supported,
);
let shader_barycentrics_supported = {
let mut features3 = Direct3D12::D3D12_FEATURE_DATA_D3D12_OPTIONS3::default();
unsafe {
device.CheckFeatureSupport(
Direct3D12::D3D12_FEATURE_D3D12_OPTIONS3,
<*mut _>::cast(&mut features3),
size_of_val(&features3) as u32,
)
}
.is_ok()
&& features3.BarycentricsSupported.as_bool()
&& shader_model >= naga::back::hlsl::ShaderModel::V6_1
};
features.set(
wgt::Features::SHADER_BARYCENTRICS,
shader_barycentrics_supported,
);

// TODO: Determine if IPresentationManager is supported
let presentation_timer = auxil::dxgi::time::PresentationTimer::new_dxgi();
Expand Down
6 changes: 6 additions & 0 deletions wgpu-hal/src/metal/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,7 @@ impl super::PrivateCapabilities {
&& (device.supports_family(MTLGPUFamily::Apple7)
|| device.supports_family(MTLGPUFamily::Mac2)),
supports_shared_event: version.at_least((10, 14), (12, 0), os_is_mac),
shader_barycentrics: device.supports_shader_barycentric_coordinates(),
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf#page=3
supports_memoryless_storage: if family_check {
device.supports_family(MTLGPUFamily::Apple2)
Expand Down Expand Up @@ -1003,6 +1004,11 @@ impl super::PrivateCapabilities {

features.set(F::RG11B10UFLOAT_RENDERABLE, self.format_rg11b10_all);

features.set(
F::SHADER_BARYCENTRICS,
self.shader_barycentrics && self.msl_version >= MTLLanguageVersion::V2_2,
);

if self.supports_simd_scoped_operations {
features.insert(F::SUBGROUP | F::SUBGROUP_BARRIER);
}
Expand Down
Loading
Loading