diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b23d2d920..9e0dde0ec1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ Bottom level categories: ## Unreleased -### Major Changes +### Major Features #### Hashmaps Removed from APIs @@ -51,6 +51,66 @@ also allows more easily creating these structures inline. By @cwfitzgerald in [#7133](https://github.com/gfx-rs/wgpu/pull/7133) +#### `device.poll` Api Reworked + +This release reworked the poll api significantly to allow polling to return errors when polling hits internal timeout limits. + +`Maintain` was renamed `PollType`. Additionally, `poll` now returns a result containing information about what happened during the poll. + +```diff +-pub fn wgpu::Device::poll(&self, maintain: wgpu::Maintain) -> wgpu::MaintainResult ++pub fn wgpu::Device::poll(&self, poll_type: wgpu::PollType) -> Result + +-device.poll(wgpu::Maintain::Poll); ++device.poll(wgpu::PollType::Poll).unwrap(); +``` + +```rust +pub enum PollType { + /// On wgpu-core based backends, block until the given submission has + /// completed execution, and any callbacks have been invoked. + /// + /// On WebGPU, this has no effect. Callbacks are invoked from the + /// window event loop. + WaitForSubmissionIndex(T), + /// Same as WaitForSubmissionIndex but waits for the most recent submission. + Wait, + /// Check the device for a single time without blocking. + Poll, +} + +pub enum PollStatus { + /// There are no active submissions in flight as of the beginning of the poll call. + /// Other submissions may have been queued on other threads during the call. + /// + /// This implies that the given Wait was satisfied before the timeout. + QueueEmpty, + + /// The requested Wait was satisfied before the timeout. + WaitSucceeded, + + /// This was a poll. + Poll, +} + +pub enum PollError { + /// The requested Wait timed out before the submission was completed. + Timeout, +} +``` + +> [!WARNING] +> As part of this change, WebGL's default behavior has changed. Previously `device.poll(Wait)` appeared as though it functioned correctly. This was a quirk caused by the bug that these PRs fixed. Now it will always return `Timeout` if the submission has not already completed. As many people rely on this behavior on WebGL, there is a new options in `BackendOptions`. If you want the old behavior, set the following on instance creation: +> +> ```rust +> instance_desc.backend_options.gl.fence_behavior = wgpu::GlFenceBehavior::AutoFinish; +> ``` +> +> You will lose the ability to know exactly when a submission has completed, but `device.poll(Wait)` will behave the same as it does on native. + +By @cwfitzgerald in [#6942](https://github.com/gfx-rs/wgpu/pull/6942). +By @cwfitzgerald in [#7030](https://github.com/gfx-rs/wgpu/pull/7030). + ### New Features #### General diff --git a/Cargo.lock b/Cargo.lock index 384713520a..ac0a215b6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4734,6 +4734,7 @@ dependencies = [ "log", "serde", "serde_json", + "thiserror 2.0.11", "web-sys", ] diff --git a/benches/benches/bind_groups.rs b/benches/benches/bind_groups.rs index 4594524b8c..6fb23d0a24 100644 --- a/benches/benches/bind_groups.rs +++ b/benches/benches/bind_groups.rs @@ -152,7 +152,11 @@ fn run_bench(ctx: &mut Criterion) { duration += start.elapsed(); drop(bind_group); - state.device_state.device.poll(wgpu::Maintain::Wait); + state + .device_state + .device + .poll(wgpu::PollType::Wait) + .unwrap(); } duration diff --git a/benches/benches/computepass.rs b/benches/benches/computepass.rs index 4248e37b89..9254547a1d 100644 --- a/benches/benches/computepass.rs +++ b/benches/benches/computepass.rs @@ -486,7 +486,11 @@ fn run_bench(ctx: &mut Criterion) { duration += start.elapsed(); } - state.device_state.device.poll(wgpu::Maintain::Wait); + state + .device_state + .device + .poll(wgpu::PollType::Wait) + .unwrap(); } duration @@ -531,7 +535,11 @@ fn run_bench(ctx: &mut Criterion) { duration += start.elapsed(); state.device_state.queue.submit(buffers); - state.device_state.device.poll(wgpu::Maintain::Wait); + state + .device_state + .device + .poll(wgpu::PollType::Wait) + .unwrap(); } duration @@ -573,7 +581,11 @@ fn run_bench(ctx: &mut Criterion) { duration += start.elapsed(); state.device_state.queue.submit([buffer]); - state.device_state.device.poll(wgpu::Maintain::Wait); + state + .device_state + .device + .poll(wgpu::PollType::Wait) + .unwrap(); } duration diff --git a/benches/benches/renderpass.rs b/benches/benches/renderpass.rs index 8e52a97c4b..2eb5667179 100644 --- a/benches/benches/renderpass.rs +++ b/benches/benches/renderpass.rs @@ -492,7 +492,11 @@ fn run_bench(ctx: &mut Criterion) { duration += start.elapsed(); } - state.device_state.device.poll(wgpu::Maintain::Wait); + state + .device_state + .device + .poll(wgpu::PollType::Wait) + .unwrap(); } duration @@ -535,7 +539,11 @@ fn run_bench(ctx: &mut Criterion) { duration += start.elapsed(); state.device_state.queue.submit(buffers); - state.device_state.device.poll(wgpu::Maintain::Wait); + state + .device_state + .device + .poll(wgpu::PollType::Wait) + .unwrap(); } duration @@ -571,7 +579,11 @@ fn run_bench(ctx: &mut Criterion) { duration += start.elapsed(); state.device_state.queue.submit([buffer]); - state.device_state.device.poll(wgpu::Maintain::Wait); + state + .device_state + .device + .poll(wgpu::PollType::Wait) + .unwrap(); } duration diff --git a/benches/benches/resource_creation.rs b/benches/benches/resource_creation.rs index 263fe0c470..bbbfc3d2e3 100644 --- a/benches/benches/resource_creation.rs +++ b/benches/benches/resource_creation.rs @@ -61,7 +61,7 @@ fn run_bench(ctx: &mut Criterion) { drop(buffers); state.queue.submit([]); - state.device.poll(wgpu::Maintain::Wait); + state.device.poll(wgpu::PollType::Wait).unwrap(); } duration diff --git a/deno_webgpu/buffer.rs b/deno_webgpu/buffer.rs index be95e91583..da0b1a52db 100644 --- a/deno_webgpu/buffer.rs +++ b/deno_webgpu/buffer.rs @@ -161,7 +161,7 @@ impl GPUBuffer { while !*done.borrow() { { self.instance - .device_poll(self.device, wgpu_types::Maintain::wait()) + .device_poll(self.device, wgpu_types::PollType::wait()) .unwrap(); } tokio::time::sleep(Duration::from_millis(10)).await; diff --git a/deno_webgpu/device.rs b/deno_webgpu/device.rs index 01f86c4343..77f5966c5f 100644 --- a/deno_webgpu/device.rs +++ b/deno_webgpu/device.rs @@ -615,7 +615,7 @@ impl GPUDevice { #[fast] fn stop_capture(&self) { self.instance - .device_poll(self.id, wgpu_types::Maintain::wait()) + .device_poll(self.id, wgpu_types::PollType::wait()) .unwrap(); self.instance.device_stop_capture(self.id); } diff --git a/examples/features/src/framework.rs b/examples/features/src/framework.rs index be113f7aa1..6acb0e58b1 100644 --- a/examples/features/src/framework.rs +++ b/examples/features/src/framework.rs @@ -592,9 +592,7 @@ impl From> let dst_buffer_slice = dst_buffer.slice(..); dst_buffer_slice.map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let bytes = dst_buffer_slice.get_mapped_range().to_vec(); wgpu_test::image::compare_image_output( diff --git a/examples/features/src/hello_synchronization/mod.rs b/examples/features/src/hello_synchronization/mod.rs index 0828804ea2..737aed7506 100644 --- a/examples/features/src/hello_synchronization/mod.rs +++ b/examples/features/src/hello_synchronization/mod.rs @@ -183,7 +183,7 @@ async fn get_data( let buffer_slice = staging_buffer.slice(..); let (sender, receiver) = flume::bounded(1); buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap()); - device.poll(wgpu::Maintain::wait()).panic_on_timeout(); + device.poll(wgpu::PollType::wait()).unwrap(); receiver.recv_async().await.unwrap().unwrap(); output.copy_from_slice(bytemuck::cast_slice(&buffer_slice.get_mapped_range()[..])); staging_buffer.unmap(); diff --git a/examples/features/src/hello_workgroups/mod.rs b/examples/features/src/hello_workgroups/mod.rs index 13535f79c7..cdddfe98a4 100644 --- a/examples/features/src/hello_workgroups/mod.rs +++ b/examples/features/src/hello_workgroups/mod.rs @@ -172,7 +172,7 @@ async fn get_data( let buffer_slice = staging_buffer.slice(..); let (sender, receiver) = flume::bounded(1); buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap()); - device.poll(wgpu::Maintain::wait()).panic_on_timeout(); + device.poll(wgpu::PollType::wait()).unwrap(); receiver.recv_async().await.unwrap().unwrap(); output.copy_from_slice(bytemuck::cast_slice(&buffer_slice.get_mapped_range()[..])); staging_buffer.unmap(); diff --git a/examples/features/src/mipmap/mod.rs b/examples/features/src/mipmap/mod.rs index 8d50fc27a6..569a99923b 100644 --- a/examples/features/src/mipmap/mod.rs +++ b/examples/features/src/mipmap/mod.rs @@ -410,7 +410,7 @@ impl crate::framework::Example for Example { .slice(..) .map_async(wgpu::MapMode::Read, |_| ()); // Wait for device to be done rendering mipmaps - device.poll(wgpu::Maintain::wait()).panic_on_timeout(); + device.poll(wgpu::PollType::wait()).unwrap(); // This is guaranteed to be ready. let timestamp_view = query_sets .mapping_buffer diff --git a/examples/features/src/ray_shadows/mod.rs b/examples/features/src/ray_shadows/mod.rs index 9b0a3671d7..3e0a57f194 100644 --- a/examples/features/src/ray_shadows/mod.rs +++ b/examples/features/src/ray_shadows/mod.rs @@ -357,7 +357,7 @@ impl crate::framework::Example for Example { rpass.draw_indexed(0..12, 0, 0..1); } queue.submit(Some(encoder.finish())); - device.poll(wgpu::Maintain::Wait); + device.poll(wgpu::PollType::Wait).unwrap(); } } diff --git a/examples/features/src/render_to_texture/mod.rs b/examples/features/src/render_to_texture/mod.rs index 9c4a32395b..eb25d3616a 100644 --- a/examples/features/src/render_to_texture/mod.rs +++ b/examples/features/src/render_to_texture/mod.rs @@ -132,7 +132,7 @@ async fn run(_path: Option) { let buffer_slice = output_staging_buffer.slice(..); let (sender, receiver) = flume::bounded(1); buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap()); - device.poll(wgpu::Maintain::wait()).panic_on_timeout(); + device.poll(wgpu::PollType::wait()).unwrap(); receiver.recv_async().await.unwrap().unwrap(); log::info!("Output buffer mapped."); { diff --git a/examples/features/src/repeated_compute/mod.rs b/examples/features/src/repeated_compute/mod.rs index d5b29c7baa..4f7b37b99f 100644 --- a/examples/features/src/repeated_compute/mod.rs +++ b/examples/features/src/repeated_compute/mod.rs @@ -106,11 +106,8 @@ async fn compute(local_buffer: &mut [u32], context: &WgpuContext) { // In order for the mapping to be completed, one of three things must happen. // One of those can be calling `Device::poll`. This isn't necessary on the web as devices // are polled automatically but natively, we need to make sure this happens manually. - // `Maintain::Wait` will cause the thread to wait on native but not on WebGpu. - context - .device - .poll(wgpu::Maintain::wait()) - .panic_on_timeout(); + // `PollType::Wait` will cause the thread to wait on native but not on WebGpu. + context.device.poll(wgpu::PollType::wait()).unwrap(); log::info!("Device polled."); // Now we await the receiving and panic if anything went wrong because we're lazy. receiver.recv_async().await.unwrap().unwrap(); diff --git a/examples/features/src/storage_texture/mod.rs b/examples/features/src/storage_texture/mod.rs index 7c647835a3..542ea7b843 100644 --- a/examples/features/src/storage_texture/mod.rs +++ b/examples/features/src/storage_texture/mod.rs @@ -143,7 +143,7 @@ async fn run(_path: Option) { let buffer_slice = output_staging_buffer.slice(..); let (sender, receiver) = flume::bounded(1); buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap()); - device.poll(wgpu::Maintain::wait()).panic_on_timeout(); + device.poll(wgpu::PollType::wait()).unwrap(); receiver.recv_async().await.unwrap().unwrap(); log::info!("Output buffer mapped"); { diff --git a/examples/features/src/timestamp_queries/mod.rs b/examples/features/src/timestamp_queries/mod.rs index 43f93f8b80..ef2b89cbc7 100644 --- a/examples/features/src/timestamp_queries/mod.rs +++ b/examples/features/src/timestamp_queries/mod.rs @@ -161,7 +161,7 @@ impl Queries { self.destination_buffer .slice(..) .map_async(wgpu::MapMode::Read, |_| ()); - device.poll(wgpu::Maintain::wait()).panic_on_timeout(); + device.poll(wgpu::PollType::wait()).unwrap(); let timestamps = { let timestamp_view = self diff --git a/examples/standalone/01_hello_compute/src/main.rs b/examples/standalone/01_hello_compute/src/main.rs index 9decdef0df..71f9d2b9b4 100644 --- a/examples/standalone/01_hello_compute/src/main.rs +++ b/examples/standalone/01_hello_compute/src/main.rs @@ -243,7 +243,7 @@ fn main() { // Wait for the GPU to finish working on the submitted work. This doesn't work on WebGPU, so we would need // to rely on the callback to know when the buffer is mapped. - device.poll(wgpu::Maintain::Wait); + device.poll(wgpu::PollType::Wait).unwrap(); // We can now read the data from the buffer. let data = buffer_slice.get_mapped_range(); diff --git a/naga/src/back/hlsl/help.rs b/naga/src/back/hlsl/help.rs index a273812213..7789a4310d 100644 --- a/naga/src/back/hlsl/help.rs +++ b/naga/src/back/hlsl/help.rs @@ -28,7 +28,10 @@ int dim_1d = NagaDimensions1D(image_1d); use super::{ super::FunctionCtx, - writer::{EXTRACT_BITS_FUNCTION, INSERT_BITS_FUNCTION}, + writer::{ + ABS_FUNCTION, DIV_FUNCTION, EXTRACT_BITS_FUNCTION, INSERT_BITS_FUNCTION, MOD_FUNCTION, + NEG_FUNCTION, + }, BackendResult, }; use crate::{arena::Handle, proc::NameKey, ScalarKind}; @@ -75,6 +78,23 @@ pub(super) struct WrappedZeroValue { pub(super) ty: Handle, } +#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] +pub(super) struct WrappedUnaryOp { + pub(super) op: crate::UnaryOperator, + // This can only represent scalar or vector types. If we ever need to wrap + // unary ops with other types, we'll need a better representation. + pub(super) ty: (Option, crate::Scalar), +} + +#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)] +pub(super) struct WrappedBinaryOp { + pub(super) op: crate::BinaryOperator, + // This can only represent scalar or vector types. If we ever need to wrap + // binary ops with other types, we'll need a better representation. + pub(super) left_ty: (Option, crate::Scalar), + pub(super) right_ty: (Option, crate::Scalar), +} + /// HLSL backend requires its own `ImageQuery` enum. /// /// It is used inside `WrappedImageQuery` and should be unique per ImageQuery function. @@ -991,6 +1011,8 @@ impl super::Writer<'_, W> { arg3: _arg3, } = *expression { + let arg_ty = func_ctx.resolve_type(arg, &module.types); + match fun { crate::MathFunction::ExtractBits => { // The behavior of our extractBits polyfill is undefined if offset + count > bit_width. We need @@ -1005,7 +1027,6 @@ impl super::Writer<'_, W> { // c = min(count, w - o) // // bitfieldExtract(x, o, c) - let arg_ty = func_ctx.resolve_type(arg, &module.types); let scalar = arg_ty.scalar().unwrap(); let components = arg_ty.components(); @@ -1048,7 +1069,6 @@ impl super::Writer<'_, W> { crate::MathFunction::InsertBits => { // The behavior of our insertBits polyfill has the same constraints as the extractBits polyfill. - let arg_ty = func_ctx.resolve_type(arg, &module.types); let scalar = arg_ty.scalar().unwrap(); let components = arg_ty.components(); @@ -1105,6 +1125,226 @@ impl super::Writer<'_, W> { // End of function body writeln!(self.out, "}}")?; } + // Taking the absolute value of the minimum value of a two's + // complement signed integer type causes overflow, which is + // undefined behaviour in HLSL. To avoid this, when the value is + // negative we bitcast the value to unsigned and negate it, then + // bitcast back to signed. + // This adheres to the WGSL spec in that the absolute of the type's + // minimum value should equal to the minimum value. + // + // TODO(#7109): asint()/asuint() only support 32-bit integers, so we + // must find another solution for different bit-widths. + crate::MathFunction::Abs + if matches!(arg_ty.scalar(), Some(crate::Scalar::I32)) => + { + let scalar = arg_ty.scalar().unwrap(); + let components = arg_ty.components(); + + let wrapped = WrappedMath { + fun, + scalar, + components, + }; + + if !self.wrapped.math.insert(wrapped) { + continue; + } + + self.write_value_type(module, arg_ty)?; + write!(self.out, " {ABS_FUNCTION}(")?; + self.write_value_type(module, arg_ty)?; + writeln!(self.out, " val) {{")?; + + let level = crate::back::Level(1); + writeln!( + self.out, + "{level}return val >= 0 ? val : asint(-asuint(val));" + )?; + writeln!(self.out, "}}")?; + writeln!(self.out)?; + } + _ => {} + } + } + } + + Ok(()) + } + + pub(super) fn write_wrapped_unary_ops( + &mut self, + module: &crate::Module, + func_ctx: &FunctionCtx, + ) -> BackendResult { + for (_, expression) in func_ctx.expressions.iter() { + if let crate::Expression::Unary { op, expr } = *expression { + let expr_ty = func_ctx.resolve_type(expr, &module.types); + let Some((vector_size, scalar)) = expr_ty.vector_size_and_scalar() else { + continue; + }; + let wrapped = WrappedUnaryOp { + op, + ty: (vector_size, scalar), + }; + + // Negating the minimum value of a two's complement signed integer type + // causes overflow, which is undefined behaviour in HLSL. To avoid this + // we bitcast the value to unsigned and negate it, then bitcast back to + // signed. This adheres to the WGSL spec in that the negative of the + // type's minimum value should equal to the minimum value. + // + // TODO(#7109): asint()/asuint() only support 32-bit integers, so we must + // find another solution for different bit-widths. + match (op, scalar) { + (crate::UnaryOperator::Negate, crate::Scalar::I32) => { + if !self.wrapped.unary_op.insert(wrapped) { + continue; + } + + self.write_value_type(module, expr_ty)?; + write!(self.out, " {NEG_FUNCTION}(")?; + self.write_value_type(module, expr_ty)?; + writeln!(self.out, " val) {{")?; + + let level = crate::back::Level(1); + writeln!(self.out, "{level}return asint(-asuint(val));",)?; + writeln!(self.out, "}}")?; + writeln!(self.out)?; + } + _ => {} + } + } + } + + Ok(()) + } + + pub(super) fn write_wrapped_binary_ops( + &mut self, + module: &crate::Module, + func_ctx: &FunctionCtx, + ) -> BackendResult { + for (expr_handle, expression) in func_ctx.expressions.iter() { + if let crate::Expression::Binary { op, left, right } = *expression { + let expr_ty = func_ctx.resolve_type(expr_handle, &module.types); + let left_ty = func_ctx.resolve_type(left, &module.types); + let right_ty = func_ctx.resolve_type(right, &module.types); + + match (op, expr_ty.scalar()) { + // Signed integer division of the type's minimum representable value + // divided by -1, or signed or unsigned division by zero, is + // undefined behaviour in HLSL. We override the divisor to 1 in these + // cases. + // This adheres to the WGSL spec in that: + // * TYPE_MIN / -1 == TYPE_MIN + // * x / 0 == x + ( + crate::BinaryOperator::Divide, + Some( + scalar @ crate::Scalar { + kind: ScalarKind::Sint | ScalarKind::Uint, + .. + }, + ), + ) => { + let Some(left_wrapped_ty) = left_ty.vector_size_and_scalar() else { + continue; + }; + let Some(right_wrapped_ty) = right_ty.vector_size_and_scalar() else { + continue; + }; + let wrapped = WrappedBinaryOp { + op, + left_ty: left_wrapped_ty, + right_ty: right_wrapped_ty, + }; + if !self.wrapped.binary_op.insert(wrapped) { + continue; + } + + self.write_value_type(module, expr_ty)?; + write!(self.out, " {DIV_FUNCTION}(")?; + self.write_value_type(module, left_ty)?; + write!(self.out, " lhs, ")?; + self.write_value_type(module, right_ty)?; + writeln!(self.out, " rhs) {{")?; + let level = crate::back::Level(1); + match scalar.kind { + ScalarKind::Sint => { + let min = -1i64 << (scalar.width as u32 * 8 - 1); + writeln!(self.out, "{level}return lhs / (((lhs == {min} & rhs == -1) | (rhs == 0)) ? 1 : rhs);")? + } + ScalarKind::Uint => { + writeln!(self.out, "{level}return lhs / (rhs == 0u ? 1u : rhs);")? + } + _ => unreachable!(), + } + writeln!(self.out, "}}")?; + writeln!(self.out)?; + } + // The modulus operator is only defined for integers in HLSL when + // either both sides are positive or both sides are negative. To + // avoid this undefined behaviour we use the following equation: + // + // dividend - (dividend / divisor) * divisor + // + // overriding the divisor to 1 if either it is 0, or it is -1 + // and the dividend is the minimum representable value. + // + // This adheres to the WGSL spec in that: + // * min_value % -1 == 0 + // * x % 0 == 0 + ( + crate::BinaryOperator::Modulo, + Some( + scalar @ crate::Scalar { + kind: ScalarKind::Sint | ScalarKind::Uint, + .. + }, + ), + ) => { + let Some(left_wrapped_ty) = left_ty.vector_size_and_scalar() else { + continue; + }; + let Some(right_wrapped_ty) = right_ty.vector_size_and_scalar() else { + continue; + }; + let wrapped = WrappedBinaryOp { + op, + left_ty: left_wrapped_ty, + right_ty: right_wrapped_ty, + }; + if !self.wrapped.binary_op.insert(wrapped) { + continue; + } + + self.write_value_type(module, expr_ty)?; + write!(self.out, " {MOD_FUNCTION}(")?; + self.write_value_type(module, left_ty)?; + write!(self.out, " lhs, ")?; + self.write_value_type(module, right_ty)?; + writeln!(self.out, " rhs) {{")?; + let level = crate::back::Level(1); + match scalar.kind { + ScalarKind::Sint => { + let min = -1i64 << (scalar.width as u32 * 8 - 1); + write!(self.out, "{level}")?; + self.write_value_type(module, right_ty)?; + writeln!(self.out, " divisor = ((lhs == {min} & rhs == -1) | (rhs == 0)) ? 1 : rhs;")?; + writeln!( + self.out, + "{level}return lhs - (lhs / divisor) * divisor;" + )? + } + ScalarKind::Uint => { + writeln!(self.out, "{level}return lhs % (rhs == 0u ? 1u : rhs);")? + } + _ => unreachable!(), + } + writeln!(self.out, "}}")?; + writeln!(self.out)?; + } _ => {} } } @@ -1120,6 +1360,8 @@ impl super::Writer<'_, W> { func_ctx: &FunctionCtx, ) -> BackendResult { self.write_wrapped_math_functions(module, func_ctx)?; + self.write_wrapped_unary_ops(module, func_ctx)?; + self.write_wrapped_binary_ops(module, func_ctx)?; self.write_wrapped_expression_functions(module, func_ctx.expressions, Some(func_ctx))?; self.write_wrapped_zero_value_functions(module, func_ctx.expressions)?; diff --git a/naga/src/back/hlsl/keywords.rs b/naga/src/back/hlsl/keywords.rs index 2c876c3198..e5be7b6d81 100644 --- a/naga/src/back/hlsl/keywords.rs +++ b/naga/src/back/hlsl/keywords.rs @@ -822,6 +822,10 @@ pub const RESERVED: &[&str] = &[ super::writer::INSERT_BITS_FUNCTION, super::writer::SAMPLER_HEAP_VAR, super::writer::COMPARISON_SAMPLER_HEAP_VAR, + super::writer::ABS_FUNCTION, + super::writer::DIV_FUNCTION, + super::writer::MOD_FUNCTION, + super::writer::NEG_FUNCTION, ]; // DXC scalar types, from https://github.com/microsoft/DirectXShaderCompiler/blob/18c9e114f9c314f93e68fbc72ce207d4ed2e65ae/tools/clang/lib/AST/ASTContextHLSL.cpp#L48-L254 diff --git a/naga/src/back/hlsl/mod.rs b/naga/src/back/hlsl/mod.rs index 572bb4ca59..e5361393b3 100644 --- a/naga/src/back/hlsl/mod.rs +++ b/naga/src/back/hlsl/mod.rs @@ -365,6 +365,8 @@ struct Wrapped { struct_matrix_access: crate::FastHashSet, mat_cx2s: crate::FastHashSet, math: crate::FastHashSet, + unary_op: crate::FastHashSet, + binary_op: crate::FastHashSet, /// If true, the sampler heaps have been written out. sampler_heaps: bool, // Mapping from SamplerIndexBufferKey to the name the namer returned. @@ -379,6 +381,8 @@ impl Wrapped { self.struct_matrix_access.clear(); self.mat_cx2s.clear(); self.math.clear(); + self.unary_op.clear(); + self.binary_op.clear(); } } diff --git a/naga/src/back/hlsl/writer.rs b/naga/src/back/hlsl/writer.rs index 1e43e159e8..35a05191b6 100644 --- a/naga/src/back/hlsl/writer.rs +++ b/naga/src/back/hlsl/writer.rs @@ -27,6 +27,10 @@ pub(crate) const EXTRACT_BITS_FUNCTION: &str = "naga_extractBits"; pub(crate) const INSERT_BITS_FUNCTION: &str = "naga_insertBits"; pub(crate) const SAMPLER_HEAP_VAR: &str = "nagaSamplerHeap"; pub(crate) const COMPARISON_SAMPLER_HEAP_VAR: &str = "nagaComparisonSamplerHeap"; +pub(crate) const ABS_FUNCTION: &str = "naga_abs"; +pub(crate) const DIV_FUNCTION: &str = "naga_div"; +pub(crate) const MOD_FUNCTION: &str = "naga_mod"; +pub(crate) const NEG_FUNCTION: &str = "naga_neg"; struct EpStructMember { name: String, @@ -2631,7 +2635,10 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { crate::Literal::F64(value) => write!(self.out, "{value:?}L")?, crate::Literal::F32(value) => write!(self.out, "{value:?}")?, crate::Literal::U32(value) => write!(self.out, "{value}u")?, - crate::Literal::I32(value) => write!(self.out, "{value}")?, + // HLSL has no suffix for explicit i32 literals, but not using any suffix + // makes the type ambiguous which prevents overload resolution from + // working. So we explicitly use the int() constructor syntax. + crate::Literal::I32(value) => write!(self.out, "int({value})")?, crate::Literal::U64(value) => write!(self.out, "{value}uL")?, crate::Literal::I64(value) => write!(self.out, "{value}L")?, crate::Literal::Bool(value) => write!(self.out, "{value}")?, @@ -2754,6 +2761,30 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { )?; } Expression::Override(_) => return Err(Error::Override), + // Avoid undefined behaviour for addition, subtraction, and + // multiplication of signed integers by casting operands to + // unsigned, performing the operation, then casting the result back + // to signed. + // TODO(#7109): This relies on the asint()/asuint() functions which only work + // for 32-bit types, so we must find another solution for different bit widths. + Expression::Binary { + op: + op @ crate::BinaryOperator::Add + | op @ crate::BinaryOperator::Subtract + | op @ crate::BinaryOperator::Multiply, + left, + right, + } if matches!( + func_ctx.resolve_type(expr, &module.types).scalar(), + Some(Scalar::I32) + ) => + { + write!(self.out, "asint(asuint(",)?; + self.write_expr(module, left, func_ctx)?; + write!(self.out, ") {} asuint(", back::binary_operation_str(op))?; + self.write_expr(module, right, func_ctx)?; + write!(self.out, "))")?; + } // All of the multiplication can be expressed as `mul`, // except vector * vector, which needs to use the "*" operator. Expression::Binary { @@ -2771,18 +2802,48 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { write!(self.out, ")")?; } - // TODO: handle undefined behavior of BinaryOperator::Modulo + // WGSL says that floating-point division by zero should return + // infinity. Microsoft's Direct3D 11 functional specification + // (https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm) + // says: // - // sint: - // if right == 0 return 0 - // if left == min(type_of(left)) && right == -1 return 0 - // if sign(left) != sign(right) return result as defined by WGSL + // Divide by 0 produces +/- INF, except 0/0 which results in NaN. // - // uint: - // if right == 0 return 0 + // which is what we want. The DXIL specification for the FDiv + // instruction corroborates this: // - // float: - // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 + // https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#fdiv + Expression::Binary { + op: crate::BinaryOperator::Divide, + left, + right, + } if matches!( + func_ctx.resolve_type(expr, &module.types).scalar_kind(), + Some(ScalarKind::Sint | ScalarKind::Uint) + ) => + { + write!(self.out, "{DIV_FUNCTION}(")?; + self.write_expr(module, left, func_ctx)?; + write!(self.out, ", ")?; + self.write_expr(module, right, func_ctx)?; + write!(self.out, ")")?; + } + + Expression::Binary { + op: crate::BinaryOperator::Modulo, + left, + right, + } if matches!( + func_ctx.resolve_type(expr, &module.types).scalar_kind(), + Some(ScalarKind::Sint | ScalarKind::Uint) + ) => + { + write!(self.out, "{MOD_FUNCTION}(")?; + self.write_expr(module, left, func_ctx)?; + write!(self.out, ", ")?; + self.write_expr(module, right, func_ctx)?; + write!(self.out, ")")?; + } // While HLSL supports float operands with the % operator it is only // defined in cases where both sides are either positive or negative. @@ -3283,7 +3344,12 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { Expression::Unary { op, expr } => { // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-operators#unary-operators let op_str = match op { - crate::UnaryOperator::Negate => "-", + crate::UnaryOperator::Negate => { + match func_ctx.resolve_type(expr, &module.types).scalar() { + Some(Scalar::I32) => NEG_FUNCTION, + _ => "-", + } + } crate::UnaryOperator::LogicalNot => "!", crate::UnaryOperator::BitwiseNot => "~", }; @@ -3382,7 +3448,10 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { let fun = match fun { // comparison - Mf::Abs => Function::Regular("abs"), + Mf::Abs => match func_ctx.resolve_type(arg, &module.types).scalar() { + Some(Scalar::I32) => Function::Regular(ABS_FUNCTION), + _ => Function::Regular("abs"), + }, Mf::Min => Function::Regular("min"), Mf::Max => Function::Regular("max"), Mf::Clamp => Function::Regular("clamp"), @@ -3668,11 +3737,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { // as non-32bit types are DXC only. Function::MissingIntOverload(fun_name) => { let scalar_kind = func_ctx.resolve_type(arg, &module.types).scalar(); - if let Some(Scalar { - kind: ScalarKind::Sint, - width: 4, - }) = scalar_kind - { + if let Some(Scalar::I32) = scalar_kind { write!(self.out, "asint({fun_name}(asuint(")?; self.write_expr(module, arg, func_ctx)?; write!(self.out, ")))")?; @@ -3686,11 +3751,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { // as non-32bit types are DXC only. Function::MissingIntReturnType(fun_name) => { let scalar_kind = func_ctx.resolve_type(arg, &module.types).scalar(); - if let Some(Scalar { - kind: ScalarKind::Sint, - width: 4, - }) = scalar_kind - { + if let Some(Scalar::I32) = scalar_kind { write!(self.out, "asint({fun_name}(")?; self.write_expr(module, arg, func_ctx)?; write!(self.out, "))")?; diff --git a/naga/src/back/msl/keywords.rs b/naga/src/back/msl/keywords.rs index a4eabab234..674d37067e 100644 --- a/naga/src/back/msl/keywords.rs +++ b/naga/src/back/msl/keywords.rs @@ -341,5 +341,9 @@ pub const RESERVED: &[&str] = &[ "DefaultConstructible", super::writer::FREXP_FUNCTION, super::writer::MODF_FUNCTION, + super::writer::ABS_FUNCTION, + super::writer::DIV_FUNCTION, + super::writer::MOD_FUNCTION, + super::writer::NEG_FUNCTION, super::writer::ARGUMENT_BUFFER_WRAPPER_STRUCT, ]; diff --git a/naga/src/back/msl/writer.rs b/naga/src/back/msl/writer.rs index 2efc9a9cc2..543a61c635 100644 --- a/naga/src/back/msl/writer.rs +++ b/naga/src/back/msl/writer.rs @@ -2,8 +2,7 @@ use super::{sampler as sm, Error, LocationMode, Options, PipelineOptions, Transl use crate::{ arena::{Handle, HandleSet}, back::{self, Baked}, - proc::index, - proc::{self, NameKey, TypeResolution}, + proc::{self, index, ExpressionKindTracker, NameKey, TypeResolution}, valid, FastHashMap, FastHashSet, }; #[cfg(test)] @@ -37,6 +36,10 @@ const RAY_QUERY_FUN_MAP_INTERSECTION: &str = "_map_intersection_type"; pub(crate) const ATOMIC_COMP_EXCH_FUNCTION: &str = "naga_atomic_compare_exchange_weak_explicit"; pub(crate) const MODF_FUNCTION: &str = "naga_modf"; pub(crate) const FREXP_FUNCTION: &str = "naga_frexp"; +pub(crate) const ABS_FUNCTION: &str = "naga_abs"; +pub(crate) const DIV_FUNCTION: &str = "naga_div"; +pub(crate) const MOD_FUNCTION: &str = "naga_mod"; +pub(crate) const NEG_FUNCTION: &str = "naga_neg"; /// For some reason, Metal does not let you have `metal::texture<..>*` as a buffer argument. /// However, if you put that texture inside a struct, everything is totally fine. This /// baffles me to no end. @@ -376,6 +379,23 @@ impl TypedGlobalVariable<'_> { } } +#[derive(Eq, PartialEq, Hash)] +enum WrappedFunction { + UnaryOp { + op: crate::UnaryOperator, + ty: (Option, crate::Scalar), + }, + BinaryOp { + op: crate::BinaryOperator, + left_ty: (Option, crate::Scalar), + right_ty: (Option, crate::Scalar), + }, + Math { + fun: crate::MathFunction, + arg_ty: (Option, crate::Scalar), + }, +} + pub struct Writer { out: W, names: FastHashMap, @@ -383,6 +403,7 @@ pub struct Writer { /// Set of expressions that need to be baked to avoid unnecessary repetition in output need_bake_expressions: back::NeedBakeExpressions, namer: proc::Namer, + wrapped_functions: FastHashSet, #[cfg(test)] put_expression_stack_pointers: FastHashSet<*const ()>, #[cfg(test)] @@ -682,6 +703,7 @@ impl Writer { named_expressions: Default::default(), need_bake_expressions: Default::default(), namer: proc::Namer::default(), + wrapped_functions: FastHashSet::default(), #[cfg(test)] put_expression_stack_pointers: Default::default(), #[cfg(test)] @@ -1755,7 +1777,12 @@ impl Writer { }, crate::Expression::Unary { op, expr } => { let op_str = match op { - crate::UnaryOperator::Negate => "-", + crate::UnaryOperator::Negate => { + match context.resolve_type(expr).scalar_kind() { + Some(crate::ScalarKind::Sint) => NEG_FUNCTION, + _ => "-", + } + } crate::UnaryOperator::LogicalNot => "!", crate::UnaryOperator::BitwiseNot => "~", }; @@ -1769,20 +1796,27 @@ impl Writer { .scalar_kind() .ok_or(Error::UnsupportedBinaryOp(op))?; - // TODO: handle undefined behavior of BinaryOperator::Modulo - // - // sint: - // if right == 0 return 0 - // if left == min(type_of(left)) && right == -1 return 0 - // if sign(left) == -1 || sign(right) == -1 return result as defined by WGSL - // - // uint: - // if right == 0 return 0 - // - // float: - // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 - - if op == crate::BinaryOperator::Modulo && kind == crate::ScalarKind::Float { + if op == crate::BinaryOperator::Divide + && (kind == crate::ScalarKind::Sint || kind == crate::ScalarKind::Uint) + { + write!(self.out, "{DIV_FUNCTION}(")?; + self.put_expression(left, context, true)?; + write!(self.out, ", ")?; + self.put_expression(right, context, true)?; + write!(self.out, ")")?; + } else if op == crate::BinaryOperator::Modulo + && (kind == crate::ScalarKind::Sint || kind == crate::ScalarKind::Uint) + { + write!(self.out, "{MOD_FUNCTION}(")?; + self.put_expression(left, context, true)?; + write!(self.out, ", ")?; + self.put_expression(right, context, true)?; + write!(self.out, ")")?; + } else if op == crate::BinaryOperator::Modulo && kind == crate::ScalarKind::Float { + // TODO: handle undefined behavior of BinaryOperator::Modulo + // + // float: + // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 write!(self.out, "{NAMESPACE}::fmod(")?; self.put_expression(left, context, true)?; write!(self.out, ", ")?; @@ -2044,6 +2078,11 @@ impl Writer { } match fun { + Mf::Abs if arg_type.scalar_kind() == Some(crate::ScalarKind::Sint) => { + write!(self.out, "{ABS_FUNCTION}(")?; + self.put_expression(arg, context, true)?; + write!(self.out, ")")?; + } Mf::Distance if scalar_argument => { write!(self.out, "{NAMESPACE}::abs(")?; self.put_expression(arg, context, false)?; @@ -3761,6 +3800,7 @@ impl Writer { &[CLAMPED_LOD_LOAD_PREFIX], &mut self.names, ); + self.wrapped_functions.clear(); self.struct_member_pads.clear(); writeln!( @@ -5027,6 +5067,269 @@ template } } + pub(super) fn write_wrapped_functions( + &mut self, + module: &crate::Module, + func_ctx: &back::FunctionCtx, + ) -> BackendResult { + for (expr_handle, expr) in func_ctx.expressions.iter() { + match *expr { + crate::Expression::Unary { op, expr: operand } => { + let operand_ty = func_ctx.resolve_type(operand, &module.types); + match op { + // Negating the TYPE_MIN of a two's complement signed integer + // type causes overflow, which is undefined behaviour in MSL. To + // avoid this we bitcast the value to unsigned and negate it, + // then bitcast back to signed. + // This adheres to the WGSL spec in that the negative of the + // type's minimum value should equal to the minimum value. + crate::UnaryOperator::Negate + if operand_ty.scalar_kind() == Some(crate::ScalarKind::Sint) => + { + let Some((vector_size, scalar)) = operand_ty.vector_size_and_scalar() + else { + continue; + }; + let wrapped = WrappedFunction::UnaryOp { + op, + ty: (vector_size, scalar), + }; + if !self.wrapped_functions.insert(wrapped) { + continue; + } + + let unsigned_scalar = crate::Scalar { + kind: crate::ScalarKind::Uint, + ..scalar + }; + let mut type_name = String::new(); + let mut unsigned_type_name = String::new(); + match vector_size { + None => { + put_numeric_type(&mut type_name, scalar, &[])?; + put_numeric_type(&mut unsigned_type_name, unsigned_scalar, &[])? + } + Some(size) => { + put_numeric_type(&mut type_name, scalar, &[size])?; + put_numeric_type( + &mut unsigned_type_name, + unsigned_scalar, + &[size], + )?; + } + }; + + writeln!(self.out, "{type_name} {NEG_FUNCTION}({type_name} val) {{")?; + let level = back::Level(1); + writeln!(self.out, "{level}return as_type<{type_name}>(-as_type<{unsigned_type_name}>(val));")?; + writeln!(self.out, "}}")?; + writeln!(self.out)?; + } + _ => {} + } + } + crate::Expression::Binary { op, left, right } => { + let expr_ty = func_ctx.resolve_type(expr_handle, &module.types); + let left_ty = func_ctx.resolve_type(left, &module.types); + let right_ty = func_ctx.resolve_type(right, &module.types); + match (op, expr_ty.scalar_kind()) { + // Signed integer division of TYPE_MIN / -1, or signed or + // unsigned division by zero, gives an unspecified value in MSL. + // We override the divisor to 1 in these cases. + // This adheres to the WGSL spec in that: + // * TYPE_MIN / -1 == TYPE_MIN + // * x / 0 == x + ( + crate::BinaryOperator::Divide, + Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint), + ) => { + let Some(left_wrapped_ty) = left_ty.vector_size_and_scalar() else { + continue; + }; + let Some(right_wrapped_ty) = right_ty.vector_size_and_scalar() else { + continue; + }; + let wrapped = WrappedFunction::BinaryOp { + op, + left_ty: left_wrapped_ty, + right_ty: right_wrapped_ty, + }; + if !self.wrapped_functions.insert(wrapped) { + continue; + } + + let Some((vector_size, scalar)) = expr_ty.vector_size_and_scalar() + else { + continue; + }; + let mut type_name = String::new(); + match vector_size { + None => put_numeric_type(&mut type_name, scalar, &[])?, + Some(size) => put_numeric_type(&mut type_name, scalar, &[size])?, + }; + writeln!( + self.out, + "{type_name} {DIV_FUNCTION}({type_name} lhs, {type_name} rhs) {{" + )?; + let level = back::Level(1); + match scalar.kind { + crate::ScalarKind::Sint => { + let min = -1i64 << (scalar.width as u32 * 8 - 1); + writeln!(self.out, "{level}return lhs / metal::select(rhs, 1, (lhs == {min} & rhs == -1) | (rhs == 0));")? + } + crate::ScalarKind::Uint => writeln!( + self.out, + "{level}return lhs / metal::select(rhs, 1u, rhs == 0u);" + )?, + _ => unreachable!(), + } + writeln!(self.out, "}}")?; + writeln!(self.out)?; + } + // Integer modulo where one or both operands are negative, or the + // divisor is zero, is undefined behaviour in MSL. To avoid this + // we use the following equation: + // + // dividend - (dividend / divisor) * divisor + // + // overriding the divisor to 1 if either it is 0, or it is -1 + // and the dividend is TYPE_MIN. + // + // This adheres to the WGSL spec in that: + // * TYPE_MIN % -1 == 0 + // * x % 0 == 0 + ( + crate::BinaryOperator::Modulo, + Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint), + ) => { + let Some(left_wrapped_ty) = left_ty.vector_size_and_scalar() else { + continue; + }; + let Some((right_vector_size, right_scalar)) = + right_ty.vector_size_and_scalar() + else { + continue; + }; + let wrapped = WrappedFunction::BinaryOp { + op, + left_ty: left_wrapped_ty, + right_ty: (right_vector_size, right_scalar), + }; + if !self.wrapped_functions.insert(wrapped) { + continue; + } + + let Some((vector_size, scalar)) = expr_ty.vector_size_and_scalar() + else { + continue; + }; + let mut type_name = String::new(); + match vector_size { + None => put_numeric_type(&mut type_name, scalar, &[])?, + Some(size) => put_numeric_type(&mut type_name, scalar, &[size])?, + }; + let mut rhs_type_name = String::new(); + match right_vector_size { + None => put_numeric_type(&mut rhs_type_name, right_scalar, &[])?, + Some(size) => { + put_numeric_type(&mut rhs_type_name, right_scalar, &[size])? + } + }; + + writeln!( + self.out, + "{type_name} {MOD_FUNCTION}({type_name} lhs, {type_name} rhs) {{" + )?; + let level = back::Level(1); + match scalar.kind { + crate::ScalarKind::Sint => { + let min = -1i64 << (scalar.width as u32 * 8 - 1); + writeln!(self.out, "{level}{rhs_type_name} divisor = metal::select(rhs, 1, (lhs == {min} & rhs == -1) | (rhs == 0));")?; + writeln!( + self.out, + "{level}return lhs - (lhs / divisor) * divisor;" + )? + } + crate::ScalarKind::Uint => writeln!( + self.out, + "{level}return lhs % metal::select(rhs, 1u, rhs == 0u);" + )?, + _ => unreachable!(), + } + writeln!(self.out, "}}")?; + writeln!(self.out)?; + } + _ => {} + } + } + crate::Expression::Math { + fun, + arg, + arg1: _, + arg2: _, + arg3: _, + } => { + let arg_ty = func_ctx.resolve_type(arg, &module.types); + match fun { + // Taking the absolute value of the TYPE_MIN of a two's + // complement signed integer type causes overflow, which is + // undefined behaviour in MSL. To avoid this, when the value is + // negative we bitcast the value to unsigned and negate it, then + // bitcast back to signed. + // This adheres to the WGSL spec in that the absolute of the + // type's minimum value should equal to the minimum value. + crate::MathFunction::Abs + if arg_ty.scalar_kind() == Some(crate::ScalarKind::Sint) => + { + let Some((vector_size, scalar)) = arg_ty.vector_size_and_scalar() + else { + continue; + }; + let wrapped = WrappedFunction::Math { + fun, + arg_ty: (vector_size, scalar), + }; + if !self.wrapped_functions.insert(wrapped) { + continue; + } + + let unsigned_scalar = crate::Scalar { + kind: crate::ScalarKind::Uint, + ..scalar + }; + let mut type_name = String::new(); + let mut unsigned_type_name = String::new(); + match vector_size { + None => { + put_numeric_type(&mut type_name, scalar, &[])?; + put_numeric_type(&mut unsigned_type_name, unsigned_scalar, &[])? + } + Some(size) => { + put_numeric_type(&mut type_name, scalar, &[size])?; + put_numeric_type( + &mut unsigned_type_name, + unsigned_scalar, + &[size], + )?; + } + }; + + writeln!(self.out, "{type_name} {ABS_FUNCTION}({type_name} val) {{")?; + let level = back::Level(1); + writeln!(self.out, "{level}return metal::select(as_type<{type_name}>(-as_type<{unsigned_type_name}>(val)), val, val >= 0);")?; + writeln!(self.out, "}}")?; + writeln!(self.out)?; + } + _ => {} + } + } + _ => {} + } + } + + Ok(()) + } + // Returns the array of mapped entry point names. fn write_functions( &mut self, @@ -5138,6 +5441,17 @@ template fun_handle ); + let ctx = back::FunctionCtx { + ty: back::FunctionType::Function(fun_handle), + info: &mod_info[fun_handle], + expressions: &fun.expressions, + named_expressions: &fun.named_expressions, + expr_kind_tracker: ExpressionKindTracker::from_arena(&fun.expressions), + }; + + writeln!(self.out)?; + self.write_wrapped_functions(module, &ctx)?; + let fun_info = &mod_info[fun_handle]; pass_through_globals.clear(); let mut needs_buffer_sizes = false; @@ -5150,7 +5464,6 @@ template } } - writeln!(self.out)?; let fun_name = &self.names[&NameKey::Function(fun_handle)]; match fun.result { Some(ref result) => { @@ -5288,6 +5601,16 @@ template ep_index ); + let ctx = back::FunctionCtx { + ty: back::FunctionType::EntryPoint(ep_index as u16), + info: fun_info, + expressions: &fun.expressions, + named_expressions: &fun.named_expressions, + expr_kind_tracker: ExpressionKindTracker::from_arena(&fun.expressions), + }; + + self.write_wrapped_functions(module, &ctx)?; + let (em_str, in_mode, out_mode, can_vertex_pull) = match ep.stage { crate::ShaderStage::Vertex => ( "vertex", diff --git a/naga/src/back/spv/block.rs b/naga/src/back/spv/block.rs index b4cceb8b48..0035797d56 100644 --- a/naga/src/back/spv/block.rs +++ b/naga/src/back/spv/block.rs @@ -4,7 +4,8 @@ Implementations for `BlockContext` methods. use super::{ index::BoundsCheckResult, selection::Selection, Block, BlockContext, Dimension, Error, - Instruction, LocalType, LookupType, NumericType, ResultMember, Writer, WriterFlags, + Instruction, LocalType, LookupType, NumericType, ResultMember, WrappedFunction, Writer, + WriterFlags, }; use crate::{arena::Handle, proc::index::GuardedIndex, Statement}; use spirv::Word; @@ -577,201 +578,227 @@ impl BlockContext<'_> { let id = self.gen_id(); let left_id = self.cached[left]; let right_id = self.cached[right]; + let left_type_id = self.get_expression_type_id(&self.fun_info[left].ty); + let right_type_id = self.get_expression_type_id(&self.fun_info[right].ty); - let left_ty_inner = self.fun_info[left].ty.inner_with(&self.ir_module.types); - let right_ty_inner = self.fun_info[right].ty.inner_with(&self.ir_module.types); + if let Some(function_id) = + self.writer + .wrapped_functions + .get(&WrappedFunction::BinaryOp { + op, + left_type_id, + right_type_id, + }) + { + block.body.push(Instruction::function_call( + result_type_id, + id, + *function_id, + &[left_id, right_id], + )); + } else { + let left_ty_inner = self.fun_info[left].ty.inner_with(&self.ir_module.types); + let right_ty_inner = self.fun_info[right].ty.inner_with(&self.ir_module.types); - let left_dimension = get_dimension(left_ty_inner); - let right_dimension = get_dimension(right_ty_inner); + let left_dimension = get_dimension(left_ty_inner); + let right_dimension = get_dimension(right_ty_inner); - let mut reverse_operands = false; + let mut reverse_operands = false; - let spirv_op = match op { - crate::BinaryOperator::Add => match *left_ty_inner { - crate::TypeInner::Scalar(scalar) - | crate::TypeInner::Vector { scalar, .. } => match scalar.kind { - crate::ScalarKind::Float => spirv::Op::FAdd, - _ => spirv::Op::IAdd, - }, - crate::TypeInner::Matrix { - columns, - rows, - scalar, - } => { - self.write_matrix_matrix_column_op( - block, - id, - result_type_id, - left_id, - right_id, + let spirv_op = match op { + crate::BinaryOperator::Add => match *left_ty_inner { + crate::TypeInner::Scalar(scalar) + | crate::TypeInner::Vector { scalar, .. } => match scalar.kind { + crate::ScalarKind::Float => spirv::Op::FAdd, + _ => spirv::Op::IAdd, + }, + crate::TypeInner::Matrix { columns, rows, - scalar.width, - spirv::Op::FAdd, - ); + scalar, + } => { + self.write_matrix_matrix_column_op( + block, + id, + result_type_id, + left_id, + right_id, + columns, + rows, + scalar.width, + spirv::Op::FAdd, + ); - self.cached[expr_handle] = id; - return Ok(()); - } - _ => unimplemented!(), - }, - crate::BinaryOperator::Subtract => match *left_ty_inner { - crate::TypeInner::Scalar(scalar) - | crate::TypeInner::Vector { scalar, .. } => match scalar.kind { - crate::ScalarKind::Float => spirv::Op::FSub, - _ => spirv::Op::ISub, + self.cached[expr_handle] = id; + return Ok(()); + } + _ => unimplemented!(), }, - crate::TypeInner::Matrix { - columns, - rows, - scalar, - } => { - self.write_matrix_matrix_column_op( - block, - id, - result_type_id, - left_id, - right_id, + crate::BinaryOperator::Subtract => match *left_ty_inner { + crate::TypeInner::Scalar(scalar) + | crate::TypeInner::Vector { scalar, .. } => match scalar.kind { + crate::ScalarKind::Float => spirv::Op::FSub, + _ => spirv::Op::ISub, + }, + crate::TypeInner::Matrix { columns, rows, - scalar.width, - spirv::Op::FSub, - ); + scalar, + } => { + self.write_matrix_matrix_column_op( + block, + id, + result_type_id, + left_id, + right_id, + columns, + rows, + scalar.width, + spirv::Op::FSub, + ); - self.cached[expr_handle] = id; - return Ok(()); - } - _ => unimplemented!(), - }, - crate::BinaryOperator::Multiply => match (left_dimension, right_dimension) { - (Dimension::Scalar, Dimension::Vector) => { - self.write_vector_scalar_mult( - block, - id, - result_type_id, - right_id, - left_id, - right_ty_inner, - ); + self.cached[expr_handle] = id; + return Ok(()); + } + _ => unimplemented!(), + }, + crate::BinaryOperator::Multiply => { + match (left_dimension, right_dimension) { + (Dimension::Scalar, Dimension::Vector) => { + self.write_vector_scalar_mult( + block, + id, + result_type_id, + right_id, + left_id, + right_ty_inner, + ); - self.cached[expr_handle] = id; - return Ok(()); - } - (Dimension::Vector, Dimension::Scalar) => { - self.write_vector_scalar_mult( - block, - id, - result_type_id, - left_id, - right_id, - left_ty_inner, - ); + self.cached[expr_handle] = id; + return Ok(()); + } + (Dimension::Vector, Dimension::Scalar) => { + self.write_vector_scalar_mult( + block, + id, + result_type_id, + left_id, + right_id, + left_ty_inner, + ); - self.cached[expr_handle] = id; - return Ok(()); - } - (Dimension::Vector, Dimension::Matrix) => spirv::Op::VectorTimesMatrix, - (Dimension::Matrix, Dimension::Scalar) => spirv::Op::MatrixTimesScalar, - (Dimension::Scalar, Dimension::Matrix) => { - reverse_operands = true; - spirv::Op::MatrixTimesScalar - } - (Dimension::Matrix, Dimension::Vector) => spirv::Op::MatrixTimesVector, - (Dimension::Matrix, Dimension::Matrix) => spirv::Op::MatrixTimesMatrix, - (Dimension::Vector, Dimension::Vector) - | (Dimension::Scalar, Dimension::Scalar) - if left_ty_inner.scalar_kind() == Some(crate::ScalarKind::Float) => - { - spirv::Op::FMul - } - (Dimension::Vector, Dimension::Vector) - | (Dimension::Scalar, Dimension::Scalar) => spirv::Op::IMul, - }, - crate::BinaryOperator::Divide => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Sint) => spirv::Op::SDiv, - Some(crate::ScalarKind::Uint) => spirv::Op::UDiv, - Some(crate::ScalarKind::Float) => spirv::Op::FDiv, - _ => unimplemented!(), - }, - crate::BinaryOperator::Modulo => match left_ty_inner.scalar_kind() { - // TODO: handle undefined behavior - // if right == 0 return 0 - // if left == min(type_of(left)) && right == -1 return 0 - Some(crate::ScalarKind::Sint) => spirv::Op::SRem, - // TODO: handle undefined behavior - // if right == 0 return 0 - Some(crate::ScalarKind::Uint) => spirv::Op::UMod, - // TODO: handle undefined behavior - // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 - Some(crate::ScalarKind::Float) => spirv::Op::FRem, - _ => unimplemented!(), - }, - crate::BinaryOperator::Equal => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => { - spirv::Op::IEqual - } - Some(crate::ScalarKind::Float) => spirv::Op::FOrdEqual, - Some(crate::ScalarKind::Bool) => spirv::Op::LogicalEqual, - _ => unimplemented!(), - }, - crate::BinaryOperator::NotEqual => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => { - spirv::Op::INotEqual + self.cached[expr_handle] = id; + return Ok(()); + } + (Dimension::Vector, Dimension::Matrix) => { + spirv::Op::VectorTimesMatrix + } + (Dimension::Matrix, Dimension::Scalar) => { + spirv::Op::MatrixTimesScalar + } + (Dimension::Scalar, Dimension::Matrix) => { + reverse_operands = true; + spirv::Op::MatrixTimesScalar + } + (Dimension::Matrix, Dimension::Vector) => { + spirv::Op::MatrixTimesVector + } + (Dimension::Matrix, Dimension::Matrix) => { + spirv::Op::MatrixTimesMatrix + } + (Dimension::Vector, Dimension::Vector) + | (Dimension::Scalar, Dimension::Scalar) + if left_ty_inner.scalar_kind() + == Some(crate::ScalarKind::Float) => + { + spirv::Op::FMul + } + (Dimension::Vector, Dimension::Vector) + | (Dimension::Scalar, Dimension::Scalar) => spirv::Op::IMul, + } } - Some(crate::ScalarKind::Float) => spirv::Op::FOrdNotEqual, - Some(crate::ScalarKind::Bool) => spirv::Op::LogicalNotEqual, - _ => unimplemented!(), - }, - crate::BinaryOperator::Less => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Sint) => spirv::Op::SLessThan, - Some(crate::ScalarKind::Uint) => spirv::Op::ULessThan, - Some(crate::ScalarKind::Float) => spirv::Op::FOrdLessThan, - _ => unimplemented!(), - }, - crate::BinaryOperator::LessEqual => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Sint) => spirv::Op::SLessThanEqual, - Some(crate::ScalarKind::Uint) => spirv::Op::ULessThanEqual, - Some(crate::ScalarKind::Float) => spirv::Op::FOrdLessThanEqual, - _ => unimplemented!(), - }, - crate::BinaryOperator::Greater => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Sint) => spirv::Op::SGreaterThan, - Some(crate::ScalarKind::Uint) => spirv::Op::UGreaterThan, - Some(crate::ScalarKind::Float) => spirv::Op::FOrdGreaterThan, - _ => unimplemented!(), - }, - crate::BinaryOperator::GreaterEqual => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Sint) => spirv::Op::SGreaterThanEqual, - Some(crate::ScalarKind::Uint) => spirv::Op::UGreaterThanEqual, - Some(crate::ScalarKind::Float) => spirv::Op::FOrdGreaterThanEqual, - _ => unimplemented!(), - }, - crate::BinaryOperator::And => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Bool) => spirv::Op::LogicalAnd, - _ => spirv::Op::BitwiseAnd, - }, - crate::BinaryOperator::ExclusiveOr => spirv::Op::BitwiseXor, - crate::BinaryOperator::InclusiveOr => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Bool) => spirv::Op::LogicalOr, - _ => spirv::Op::BitwiseOr, - }, - crate::BinaryOperator::LogicalAnd => spirv::Op::LogicalAnd, - crate::BinaryOperator::LogicalOr => spirv::Op::LogicalOr, - crate::BinaryOperator::ShiftLeft => spirv::Op::ShiftLeftLogical, - crate::BinaryOperator::ShiftRight => match left_ty_inner.scalar_kind() { - Some(crate::ScalarKind::Sint) => spirv::Op::ShiftRightArithmetic, - Some(crate::ScalarKind::Uint) => spirv::Op::ShiftRightLogical, - _ => unimplemented!(), - }, - }; + crate::BinaryOperator::Divide => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Sint) => spirv::Op::SDiv, + Some(crate::ScalarKind::Uint) => spirv::Op::UDiv, + Some(crate::ScalarKind::Float) => spirv::Op::FDiv, + _ => unimplemented!(), + }, + crate::BinaryOperator::Modulo => match left_ty_inner.scalar_kind() { + // TODO: handle undefined behavior + // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 + Some(crate::ScalarKind::Float) => spirv::Op::FRem, + Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => { + unreachable!("Should have been handled by wrapped function") + } + _ => unimplemented!(), + }, + crate::BinaryOperator::Equal => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => { + spirv::Op::IEqual + } + Some(crate::ScalarKind::Float) => spirv::Op::FOrdEqual, + Some(crate::ScalarKind::Bool) => spirv::Op::LogicalEqual, + _ => unimplemented!(), + }, + crate::BinaryOperator::NotEqual => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Sint | crate::ScalarKind::Uint) => { + spirv::Op::INotEqual + } + Some(crate::ScalarKind::Float) => spirv::Op::FOrdNotEqual, + Some(crate::ScalarKind::Bool) => spirv::Op::LogicalNotEqual, + _ => unimplemented!(), + }, + crate::BinaryOperator::Less => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Sint) => spirv::Op::SLessThan, + Some(crate::ScalarKind::Uint) => spirv::Op::ULessThan, + Some(crate::ScalarKind::Float) => spirv::Op::FOrdLessThan, + _ => unimplemented!(), + }, + crate::BinaryOperator::LessEqual => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Sint) => spirv::Op::SLessThanEqual, + Some(crate::ScalarKind::Uint) => spirv::Op::ULessThanEqual, + Some(crate::ScalarKind::Float) => spirv::Op::FOrdLessThanEqual, + _ => unimplemented!(), + }, + crate::BinaryOperator::Greater => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Sint) => spirv::Op::SGreaterThan, + Some(crate::ScalarKind::Uint) => spirv::Op::UGreaterThan, + Some(crate::ScalarKind::Float) => spirv::Op::FOrdGreaterThan, + _ => unimplemented!(), + }, + crate::BinaryOperator::GreaterEqual => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Sint) => spirv::Op::SGreaterThanEqual, + Some(crate::ScalarKind::Uint) => spirv::Op::UGreaterThanEqual, + Some(crate::ScalarKind::Float) => spirv::Op::FOrdGreaterThanEqual, + _ => unimplemented!(), + }, + crate::BinaryOperator::And => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Bool) => spirv::Op::LogicalAnd, + _ => spirv::Op::BitwiseAnd, + }, + crate::BinaryOperator::ExclusiveOr => spirv::Op::BitwiseXor, + crate::BinaryOperator::InclusiveOr => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Bool) => spirv::Op::LogicalOr, + _ => spirv::Op::BitwiseOr, + }, + crate::BinaryOperator::LogicalAnd => spirv::Op::LogicalAnd, + crate::BinaryOperator::LogicalOr => spirv::Op::LogicalOr, + crate::BinaryOperator::ShiftLeft => spirv::Op::ShiftLeftLogical, + crate::BinaryOperator::ShiftRight => match left_ty_inner.scalar_kind() { + Some(crate::ScalarKind::Sint) => spirv::Op::ShiftRightArithmetic, + Some(crate::ScalarKind::Uint) => spirv::Op::ShiftRightLogical, + _ => unimplemented!(), + }, + }; - block.body.push(Instruction::binary( - spirv_op, - result_type_id, - id, - if reverse_operands { right_id } else { left_id }, - if reverse_operands { left_id } else { right_id }, - )); + block.body.push(Instruction::binary( + spirv_op, + result_type_id, + id, + if reverse_operands { right_id } else { left_id }, + if reverse_operands { left_id } else { right_id }, + )); + } id } crate::Expression::Math { diff --git a/naga/src/back/spv/mod.rs b/naga/src/back/spv/mod.rs index 518d240ed6..b79ed355a2 100644 --- a/naga/src/back/spv/mod.rs +++ b/naga/src/back/spv/mod.rs @@ -302,6 +302,26 @@ impl NumericType { _ => None, } } + + const fn scalar(self) -> crate::Scalar { + match self { + NumericType::Scalar(scalar) + | NumericType::Vector { scalar, .. } + | NumericType::Matrix { scalar, .. } => scalar, + } + } + + const fn with_scalar(self, scalar: crate::Scalar) -> Self { + match self { + NumericType::Scalar(_) => NumericType::Scalar(scalar), + NumericType::Vector { size, .. } => NumericType::Vector { size, scalar }, + NumericType::Matrix { columns, rows, .. } => NumericType::Matrix { + columns, + rows, + scalar, + }, + } + } } /// A SPIR-V type constructed during code generation. @@ -481,6 +501,18 @@ enum Dimension { Matrix, } +/// Key used to look up an operation which we have wrapped in a helper +/// function, which should be called instead of directly emitting code +/// for the expression. See [`Writer::wrapped_functions`]. +#[derive(Debug, Eq, PartialEq, Hash)] +enum WrappedFunction { + BinaryOp { + op: crate::BinaryOperator, + left_type_id: Word, + right_type_id: Word, + }, +} + /// A map from evaluated [`Expression`](crate::Expression)s to their SPIR-V ids. /// /// When we emit code to evaluate a given `Expression`, we record the @@ -758,6 +790,10 @@ pub struct Writer { lookup_type: crate::FastHashMap, lookup_function: crate::FastHashMap, Word>, lookup_function_type: crate::FastHashMap, + /// Operations which have been wrapped in a helper function. The value is + /// the ID of the function, which should be called instead of emitting code + /// for the operation directly. + wrapped_functions: crate::FastHashMap, /// Indexed by const-expression handle indexes constant_ids: HandleVec, cached_constants: crate::FastHashMap, diff --git a/naga/src/back/spv/writer.rs b/naga/src/back/spv/writer.rs index b68d9af2f3..95d2e8cea7 100644 --- a/naga/src/back/spv/writer.rs +++ b/naga/src/back/spv/writer.rs @@ -8,7 +8,7 @@ use super::{ }; use crate::{ arena::{Handle, HandleVec, UniqueArena}, - back::spv::BindingInfo, + back::spv::{BindingInfo, WrappedFunction}, proc::{Alignment, TypeResolution}, valid::{FunctionInfo, ModuleInfo}, }; @@ -74,6 +74,7 @@ impl Writer { lookup_type: crate::FastHashMap::default(), lookup_function: crate::FastHashMap::default(), lookup_function_type: crate::FastHashMap::default(), + wrapped_functions: crate::FastHashMap::default(), constant_ids: HandleVec::new(), cached_constants: crate::FastHashMap::default(), global_variables: HandleVec::new(), @@ -127,6 +128,7 @@ impl Writer { lookup_type: take(&mut self.lookup_type).recycle(), lookup_function: take(&mut self.lookup_function).recycle(), lookup_function_type: take(&mut self.lookup_function_type).recycle(), + wrapped_functions: take(&mut self.wrapped_functions).recycle(), constant_ids: take(&mut self.constant_ids).recycle(), cached_constants: take(&mut self.cached_constants).recycle(), global_variables: take(&mut self.global_variables).recycle(), @@ -221,6 +223,10 @@ impl Writer { self.get_type_id(lookup_ty) } + pub(super) fn get_localtype_id(&mut self, local: LocalType) -> Word { + self.get_type_id(LookupType::Local(local)) + } + pub(super) fn get_pointer_id( &mut self, handle: Handle, @@ -305,6 +311,243 @@ impl Writer { .push(Instruction::decorate(id, decoration, operands)); } + /// Emits code for any wrapper functions required by the expressions in ir_function. + /// The IDs of any emitted functions will be stored in [`Self::wrapped_functions`]. + fn write_wrapped_functions( + &mut self, + ir_function: &crate::Function, + info: &FunctionInfo, + ir_module: &crate::Module, + ) -> Result<(), Error> { + log::trace!("Generating wrapped functions for {:?}", ir_function.name); + + for (expr_handle, expr) in ir_function.expressions.iter() { + match *expr { + crate::Expression::Binary { op, left, right } => { + let expr_ty_inner = info[expr_handle].ty.inner_with(&ir_module.types); + if let Some(expr_ty) = NumericType::from_inner(expr_ty_inner) { + match (op, expr_ty.scalar().kind) { + // Division and modulo are undefined behaviour when the + // dividend is the minimum representable value and the divisor + // is negative one, or when the divisor is zero. These wrapped + // functions override the divisor to one in these cases, + // matching the WGSL spec. + ( + crate::BinaryOperator::Divide | crate::BinaryOperator::Modulo, + crate::ScalarKind::Sint | crate::ScalarKind::Uint, + ) => { + self.write_wrapped_binary_op( + op, + expr_ty, + &info[left].ty, + &info[right].ty, + )?; + } + _ => {} + } + } + } + _ => {} + } + } + + Ok(()) + } + + /// Write a SPIR-V function that performs the operator `op` with Naga IR semantics. + /// + /// Define a function that performs an integer division or modulo operation, + /// except that using a divisor of zero or causing signed overflow with a + /// divisor of -1 returns the numerator unchanged, rather than exhibiting + /// undefined behavior. + /// + /// Store the generated function's id in the [`wrapped_functions`] table. + /// + /// The operator `op` must be either [`Divide`] or [`Modulo`]. + /// + /// # Panics + /// + /// The `return_type`, `left_type` or `right_type` arguments must all be + /// integer scalars or vectors. If not, this function panics. + /// + /// [`wrapped_functions`]: Writer::wrapped_functions + /// [`Divide`]: crate::BinaryOperator::Divide + /// [`Modulo`]: crate::BinaryOperator::Modulo + fn write_wrapped_binary_op( + &mut self, + op: crate::BinaryOperator, + return_type: NumericType, + left_type: &TypeResolution, + right_type: &TypeResolution, + ) -> Result<(), Error> { + let return_type_id = self.get_localtype_id(LocalType::Numeric(return_type)); + let left_type_id = self.get_expression_type_id(left_type); + let right_type_id = self.get_expression_type_id(right_type); + + // Check if we've already emitted this function. + let wrapped = WrappedFunction::BinaryOp { + op, + left_type_id, + right_type_id, + }; + let function_id = match self.wrapped_functions.entry(wrapped) { + Entry::Occupied(_) => return Ok(()), + Entry::Vacant(e) => *e.insert(self.id_gen.next()), + }; + + let scalar = return_type.scalar(); + + if self.flags.contains(WriterFlags::DEBUG) { + let function_name = match op { + crate::BinaryOperator::Divide => "naga_div", + crate::BinaryOperator::Modulo => "naga_mod", + _ => unreachable!(), + }; + self.debugs + .push(Instruction::name(function_id, function_name)); + } + let mut function = Function::default(); + + let function_type_id = self.get_function_type(LookupFunctionType { + parameter_type_ids: vec![left_type_id, right_type_id], + return_type_id, + }); + function.signature = Some(Instruction::function( + return_type_id, + function_id, + spirv::FunctionControl::empty(), + function_type_id, + )); + + let lhs_id = self.id_gen.next(); + let rhs_id = self.id_gen.next(); + if self.flags.contains(WriterFlags::DEBUG) { + self.debugs.push(Instruction::name(lhs_id, "lhs")); + self.debugs.push(Instruction::name(rhs_id, "rhs")); + } + let left_par = Instruction::function_parameter(left_type_id, lhs_id); + let right_par = Instruction::function_parameter(right_type_id, rhs_id); + for instruction in [left_par, right_par] { + function.parameters.push(FunctionArgument { + instruction, + handle_id: 0, + }); + } + + let label_id = self.id_gen.next(); + let mut block = Block::new(label_id); + + let bool_type = return_type.with_scalar(crate::Scalar::BOOL); + let bool_type_id = self.get_type_id(LookupType::Local(LocalType::Numeric(bool_type))); + + let maybe_splat_const = |writer: &mut Self, const_id| match return_type { + NumericType::Scalar(_) => const_id, + NumericType::Vector { size, .. } => { + let constituent_ids = [const_id; crate::VectorSize::MAX]; + writer.get_constant_composite( + LookupType::Local(LocalType::Numeric(return_type)), + &constituent_ids[..size as usize], + ) + } + NumericType::Matrix { .. } => unreachable!(), + }; + + let const_zero_id = self.get_constant_scalar_with(0, scalar)?; + let composite_zero_id = maybe_splat_const(self, const_zero_id); + let rhs_eq_zero_id = self.id_gen.next(); + block.body.push(Instruction::binary( + spirv::Op::IEqual, + bool_type_id, + rhs_eq_zero_id, + rhs_id, + composite_zero_id, + )); + let divisor_selector_id = match scalar.kind { + crate::ScalarKind::Sint => { + let (const_min_id, const_neg_one_id) = match scalar.width { + 4 => Ok(( + self.get_constant_scalar(crate::Literal::I32(i32::MIN)), + self.get_constant_scalar(crate::Literal::I32(-1i32)), + )), + 8 => Ok(( + self.get_constant_scalar(crate::Literal::I64(i64::MIN)), + self.get_constant_scalar(crate::Literal::I64(-1i64)), + )), + _ => Err(Error::Validation("Unexpected scalar width")), + }?; + let composite_min_id = maybe_splat_const(self, const_min_id); + let composite_neg_one_id = maybe_splat_const(self, const_neg_one_id); + + let lhs_eq_int_min_id = self.id_gen.next(); + block.body.push(Instruction::binary( + spirv::Op::IEqual, + bool_type_id, + lhs_eq_int_min_id, + lhs_id, + composite_min_id, + )); + let rhs_eq_neg_one_id = self.id_gen.next(); + block.body.push(Instruction::binary( + spirv::Op::IEqual, + bool_type_id, + rhs_eq_neg_one_id, + rhs_id, + composite_neg_one_id, + )); + let lhs_eq_int_min_and_rhs_eq_neg_one_id = self.id_gen.next(); + block.body.push(Instruction::binary( + spirv::Op::LogicalAnd, + bool_type_id, + lhs_eq_int_min_and_rhs_eq_neg_one_id, + lhs_eq_int_min_id, + rhs_eq_neg_one_id, + )); + let rhs_eq_zero_or_lhs_eq_int_min_and_rhs_eq_neg_one_id = self.id_gen.next(); + block.body.push(Instruction::binary( + spirv::Op::LogicalOr, + bool_type_id, + rhs_eq_zero_or_lhs_eq_int_min_and_rhs_eq_neg_one_id, + rhs_eq_zero_id, + lhs_eq_int_min_and_rhs_eq_neg_one_id, + )); + rhs_eq_zero_or_lhs_eq_int_min_and_rhs_eq_neg_one_id + } + crate::ScalarKind::Uint => rhs_eq_zero_id, + _ => unreachable!(), + }; + + let const_one_id = self.get_constant_scalar_with(1, scalar)?; + let composite_one_id = maybe_splat_const(self, const_one_id); + let divisor_id = self.id_gen.next(); + block.body.push(Instruction::select( + right_type_id, + divisor_id, + divisor_selector_id, + composite_one_id, + rhs_id, + )); + let op = match (op, scalar.kind) { + (crate::BinaryOperator::Divide, crate::ScalarKind::Sint) => spirv::Op::SDiv, + (crate::BinaryOperator::Divide, crate::ScalarKind::Uint) => spirv::Op::UDiv, + (crate::BinaryOperator::Modulo, crate::ScalarKind::Sint) => spirv::Op::SRem, + (crate::BinaryOperator::Modulo, crate::ScalarKind::Uint) => spirv::Op::UMod, + _ => unreachable!(), + }; + let return_id = self.id_gen.next(); + block.body.push(Instruction::binary( + op, + return_type_id, + return_id, + lhs_id, + divisor_id, + )); + + function.consume(block, Instruction::return_value(return_id)); + function.to_words(&mut self.logical_layout.function_definitions); + Instruction::function_end().to_words(&mut self.logical_layout.function_definitions); + Ok(()) + } + fn write_function( &mut self, ir_function: &crate::Function, @@ -313,6 +556,8 @@ impl Writer { mut interface: Option, debug_info: &Option, ) -> Result { + self.write_wrapped_functions(ir_function, info, ir_module)?; + log::trace!("Generating code for {:?}", ir_function.name); let mut function = Function::default(); @@ -935,7 +1180,7 @@ impl Writer { } LocalType::Image(image) => { let local_type = LocalType::Numeric(NumericType::Scalar(image.sampled_type)); - let type_id = self.get_type_id(LookupType::Local(local_type)); + let type_id = self.get_localtype_id(local_type); Instruction::type_image(id, type_id, image.dim, image.flags, image.image_format) } LocalType::Sampler => Instruction::type_sampler(id), diff --git a/naga/src/proc/type_methods.rs b/naga/src/proc/type_methods.rs index 6276c6bcf1..407b5b4b50 100644 --- a/naga/src/proc/type_methods.rs +++ b/naga/src/proc/type_methods.rs @@ -259,4 +259,26 @@ impl crate::TypeInner { _ => return None, }) } + + /// If the type is a Vector or a Scalar return a tuple of the vector size (or None + /// for Scalars), and the scalar kind. Returns (None, None) for other types. + pub const fn vector_size_and_scalar( + &self, + ) -> Option<(Option, crate::Scalar)> { + match *self { + crate::TypeInner::Scalar(scalar) => Some((None, scalar)), + crate::TypeInner::Vector { size, scalar } => Some((Some(size), scalar)), + crate::TypeInner::Matrix { .. } + | crate::TypeInner::Atomic(_) + | crate::TypeInner::Pointer { .. } + | crate::TypeInner::ValuePointer { .. } + | crate::TypeInner::Array { .. } + | crate::TypeInner::Struct { .. } + | crate::TypeInner::Image { .. } + | crate::TypeInner::Sampler { .. } + | crate::TypeInner::AccelerationStructure + | crate::TypeInner::RayQuery + | crate::TypeInner::BindingArray { .. } => None, + } + } } diff --git a/naga/tests/in/operators.wgsl b/naga/tests/in/operators.wgsl index 293b84ab11..5b621988e9 100644 --- a/naga/tests/in/operators.wgsl +++ b/naga/tests/in/operators.wgsl @@ -293,13 +293,23 @@ fn main(@builtin(workgroup_id) id: vec3) { } fn negation_avoids_prefix_decrement() { - let x = 1; - let p0 = -x; - let p1 = - -x; - let p2 = -(-x); - let p3 = -(- x); - let p4 = - - -x; - let p5 = - - - - x; - let p6 = - - -(- -x); - let p7 = (- - - - -x); + let i = 1; + let i0 = -i; + let i1 = - -i; + let i2 = -(-i); + let i3 = -(- i); + let i4 = - - -i; + let i5 = - - - - i; + let i6 = - - -(- -i); + let i7 = (- - - - -i); + + let f = 1.0; + let f0 = -f; + let f1 = - -f; + let f2 = -(-f); + let f3 = -(- f); + let f4 = - - -f; + let f5 = - - - - f; + let f6 = - - -(- -f); + let f7 = (- - - - -f); } diff --git a/naga/tests/out/glsl/operators.main.Compute.glsl b/naga/tests/out/glsl/operators.main.Compute.glsl index 1c2824495f..3e38d43202 100644 --- a/naga/tests/out/glsl/operators.main.Compute.glsl +++ b/naga/tests/out/glsl/operators.main.Compute.glsl @@ -240,14 +240,22 @@ void assignment() { } void negation_avoids_prefix_decrement() { - int p0_ = -(1); - int p1_ = -(-(1)); - int p2_ = -(-(1)); - int p3_ = -(-(1)); - int p4_ = -(-(-(1))); - int p5_ = -(-(-(-(1)))); - int p6_ = -(-(-(-(-(1))))); - int p7_ = -(-(-(-(-(1))))); + int i0_ = -(1); + int i1_ = -(-(1)); + int i2_ = -(-(1)); + int i3_ = -(-(1)); + int i4_ = -(-(-(1))); + int i5_ = -(-(-(-(1)))); + int i6_ = -(-(-(-(-(1))))); + int i7_ = -(-(-(-(-(1))))); + float f0_ = -(1.0); + float f1_ = -(-(1.0)); + float f2_ = -(-(1.0)); + float f3_ = -(-(1.0)); + float f4_ = -(-(-(1.0))); + float f5_ = -(-(-(-(1.0)))); + float f6_ = -(-(-(-(-(1.0))))); + float f7_ = -(-(-(-(-(1.0))))); return; } diff --git a/naga/tests/out/hlsl/6772-unpack-expr-accesses.hlsl b/naga/tests/out/hlsl/6772-unpack-expr-accesses.hlsl index c6d6c3f150..be62edc89f 100644 --- a/naga/tests/out/hlsl/6772-unpack-expr-accesses.hlsl +++ b/naga/tests/out/hlsl/6772-unpack-expr-accesses.hlsl @@ -1,7 +1,7 @@ [numthreads(1, 1, 1)] void main() { - int phony = (int4(12u, 12u >> 8, 12u >> 16, 12u >> 24) << 24 >> 24)[2]; + int phony = (int4(12u, 12u >> 8, 12u >> 16, 12u >> 24) << 24 >> 24)[int(2)]; uint phony_1 = (uint4(12u, 12u >> 8, 12u >> 16, 12u >> 24) << 24 >> 24).y; return; } diff --git a/naga/tests/out/hlsl/abstract-types-return.hlsl b/naga/tests/out/hlsl/abstract-types-return.hlsl index fe2de29aee..77a09e8c9a 100644 --- a/naga/tests/out/hlsl/abstract-types-return.hlsl +++ b/naga/tests/out/hlsl/abstract-types-return.hlsl @@ -1,6 +1,6 @@ int return_i32_ai() { - return 1; + return int(1); } uint return_u32_ai() diff --git a/naga/tests/out/hlsl/access.hlsl b/naga/tests/out/hlsl/access.hlsl index dcb62ae2af..167046fb30 100644 --- a/naga/tests/out/hlsl/access.hlsl +++ b/naga/tests/out/hlsl/access.hlsl @@ -93,7 +93,7 @@ GlobalConst ConstructGlobalConst(uint arg0, uint3 arg1, int arg2) { return ret; } -static GlobalConst global_const = ConstructGlobalConst(0u, uint3(0u, 0u, 0u), 0); +static GlobalConst global_const = ConstructGlobalConst(0u, uint3(0u, 0u, 0u), int(0)); RWByteAddressBuffer bar : register(u0); cbuffer baz : register(b1) { Baz baz; } RWByteAddressBuffer qux : register(u2); @@ -135,11 +135,11 @@ void SetMatScalarmOnBaz(Baz obj, float scalar, uint mat_idx, uint vec_idx) { void test_matrix_within_struct_accesses() { - int idx = 1; + int idx = int(1); Baz t = ConstructBaz(float3x2((1.0).xx, (2.0).xx, (3.0).xx)); int _e3 = idx; - idx = (_e3 - 1); + idx = asint(asuint(_e3) - asuint(int(1))); float3x2 l0_ = GetMatmOnBaz(baz); float2 l1_ = GetMatmOnBaz(baz)[0]; int _e14 = idx; @@ -153,7 +153,7 @@ void test_matrix_within_struct_accesses() int _e38 = idx; float l6_ = GetMatmOnBaz(baz)[_e36][_e38]; int _e51 = idx; - idx = (_e51 + 1); + idx = asint(asuint(_e51) + asuint(int(1))); SetMatmOnBaz(t, float3x2((6.0).xx, (5.0).xx, (4.0).xx)); t.m_0 = (9.0).xx; int _e66 = idx; @@ -182,11 +182,11 @@ ret_ZeroValuearray2_float4x2_ ZeroValuearray2_float4x2_() { void test_matrix_within_array_within_struct_accesses() { - int idx_1 = 1; + int idx_1 = int(1); MatCx2InArray t_1 = ConstructMatCx2InArray(ZeroValuearray2_float4x2_()); int _e3 = idx_1; - idx_1 = (_e3 - 1); + idx_1 = asint(asuint(_e3) - asuint(int(1))); float4x2 l0_1[2] = ((float4x2[2])nested_mat_cx2_.am); float4x2 l1_1 = ((float4x2)nested_mat_cx2_.am[0]); float2 l2_1 = nested_mat_cx2_.am[0]._0; @@ -201,7 +201,7 @@ void test_matrix_within_array_within_struct_accesses() int _e48 = idx_1; float l7_ = __get_col_of_mat4x2(nested_mat_cx2_.am[0], _e46)[_e48]; int _e55 = idx_1; - idx_1 = (_e55 + 1); + idx_1 = asint(asuint(_e55) + asuint(int(1))); t_1.am = (__mat4x2[2])ZeroValuearray2_float4x2_(); t_1.am[0] = (__mat4x2)float4x2((8.0).xx, (7.0).xx, (6.0).xx, (5.0).xx); t_1.am[0]._0 = (9.0).xx; @@ -294,7 +294,7 @@ S ConstructS(int arg0) { int member_ptr() { - S s = ConstructS(42); + S s = ConstructS(int(42)); int _e4 = s.m; return _e4; @@ -370,8 +370,8 @@ float4 foo_vert(uint vi : SV_VertexID) : SV_Position int a_2 = asint(bar.Load(0+(((NagaBufferLengthRW(bar) - 160) / 8) - 2u)*8+160)); int2 c = asint(qux.Load2(0)); const float _e33 = read_from_private(foo); - c2_ = Constructarray5_int_(a_2, int(b), 3, 4, 5); - c2_[min(uint((vi + 1u)), 4u)] = 42; + c2_ = Constructarray5_int_(a_2, int(b), int(3), int(4), int(5)); + c2_[min(uint((vi + 1u)), 4u)] = int(42); int value_1 = c2_[min(uint(vi), 4u)]; const float _e47 = test_arr_as_arg(ZeroValuearray5_array10_float__()); return float4(mul(float4((value_1).xxxx), _matrix), 2.0); @@ -396,7 +396,7 @@ float4 foo_frag() : SV_Target0 bar.Store2(144+0, asuint(_value2[0])); bar.Store2(144+8, asuint(_value2[1])); } - bar.Store(0+8+160, asuint(1)); + bar.Store(0+8+160, asuint(int(1))); qux.Store2(0, asuint(ZeroValueint2())); return (0.0).xxxx; } diff --git a/naga/tests/out/hlsl/atomicOps.hlsl b/naga/tests/out/hlsl/atomicOps.hlsl index 640972a2fa..52d11aa325 100644 --- a/naga/tests/out/hlsl/atomicOps.hlsl +++ b/naga/tests/out/hlsl/atomicOps.hlsl @@ -20,13 +20,13 @@ void cs_main(uint3 id : SV_GroupThreadID, uint3 __local_invocation_id : SV_Group } GroupMemoryBarrierWithGroupSync(); storage_atomic_scalar.Store(0, asuint(1u)); - storage_atomic_arr.Store(4, asuint(1)); + storage_atomic_arr.Store(4, asuint(int(1))); storage_struct.Store(0, asuint(1u)); - storage_struct.Store(4+4, asuint(1)); + storage_struct.Store(4+4, asuint(int(1))); workgroup_atomic_scalar = 1u; - workgroup_atomic_arr[1] = 1; + workgroup_atomic_arr[1] = int(1); workgroup_struct.atomic_scalar = 1u; - workgroup_struct.atomic_arr[1] = 1; + workgroup_struct.atomic_arr[1] = int(1); GroupMemoryBarrierWithGroupSync(); uint l0_ = asuint(storage_atomic_scalar.Load(0)); int l1_ = asint(storage_atomic_arr.Load(4)); @@ -38,74 +38,74 @@ void cs_main(uint3 id : SV_GroupThreadID, uint3 __local_invocation_id : SV_Group int l7_ = workgroup_struct.atomic_arr[1]; GroupMemoryBarrierWithGroupSync(); uint _e51; storage_atomic_scalar.InterlockedAdd(0, 1u, _e51); - int _e55; storage_atomic_arr.InterlockedAdd(4, 1, _e55); + int _e55; storage_atomic_arr.InterlockedAdd(4, int(1), _e55); uint _e59; storage_struct.InterlockedAdd(0, 1u, _e59); - int _e64; storage_struct.InterlockedAdd(4+4, 1, _e64); + int _e64; storage_struct.InterlockedAdd(4+4, int(1), _e64); uint _e67; InterlockedAdd(workgroup_atomic_scalar, 1u, _e67); - int _e71; InterlockedAdd(workgroup_atomic_arr[1], 1, _e71); + int _e71; InterlockedAdd(workgroup_atomic_arr[1], int(1), _e71); uint _e75; InterlockedAdd(workgroup_struct.atomic_scalar, 1u, _e75); - int _e80; InterlockedAdd(workgroup_struct.atomic_arr[1], 1, _e80); + int _e80; InterlockedAdd(workgroup_struct.atomic_arr[1], int(1), _e80); GroupMemoryBarrierWithGroupSync(); uint _e83; storage_atomic_scalar.InterlockedAdd(0, -1u, _e83); - int _e87; storage_atomic_arr.InterlockedAdd(4, -1, _e87); + int _e87; storage_atomic_arr.InterlockedAdd(4, -int(1), _e87); uint _e91; storage_struct.InterlockedAdd(0, -1u, _e91); - int _e96; storage_struct.InterlockedAdd(4+4, -1, _e96); + int _e96; storage_struct.InterlockedAdd(4+4, -int(1), _e96); uint _e99; InterlockedAdd(workgroup_atomic_scalar, -1u, _e99); - int _e103; InterlockedAdd(workgroup_atomic_arr[1], -1, _e103); + int _e103; InterlockedAdd(workgroup_atomic_arr[1], -int(1), _e103); uint _e107; InterlockedAdd(workgroup_struct.atomic_scalar, -1u, _e107); - int _e112; InterlockedAdd(workgroup_struct.atomic_arr[1], -1, _e112); + int _e112; InterlockedAdd(workgroup_struct.atomic_arr[1], -int(1), _e112); GroupMemoryBarrierWithGroupSync(); uint _e115; storage_atomic_scalar.InterlockedMax(0, 1u, _e115); - int _e119; storage_atomic_arr.InterlockedMax(4, 1, _e119); + int _e119; storage_atomic_arr.InterlockedMax(4, int(1), _e119); uint _e123; storage_struct.InterlockedMax(0, 1u, _e123); - int _e128; storage_struct.InterlockedMax(4+4, 1, _e128); + int _e128; storage_struct.InterlockedMax(4+4, int(1), _e128); uint _e131; InterlockedMax(workgroup_atomic_scalar, 1u, _e131); - int _e135; InterlockedMax(workgroup_atomic_arr[1], 1, _e135); + int _e135; InterlockedMax(workgroup_atomic_arr[1], int(1), _e135); uint _e139; InterlockedMax(workgroup_struct.atomic_scalar, 1u, _e139); - int _e144; InterlockedMax(workgroup_struct.atomic_arr[1], 1, _e144); + int _e144; InterlockedMax(workgroup_struct.atomic_arr[1], int(1), _e144); GroupMemoryBarrierWithGroupSync(); uint _e147; storage_atomic_scalar.InterlockedMin(0, 1u, _e147); - int _e151; storage_atomic_arr.InterlockedMin(4, 1, _e151); + int _e151; storage_atomic_arr.InterlockedMin(4, int(1), _e151); uint _e155; storage_struct.InterlockedMin(0, 1u, _e155); - int _e160; storage_struct.InterlockedMin(4+4, 1, _e160); + int _e160; storage_struct.InterlockedMin(4+4, int(1), _e160); uint _e163; InterlockedMin(workgroup_atomic_scalar, 1u, _e163); - int _e167; InterlockedMin(workgroup_atomic_arr[1], 1, _e167); + int _e167; InterlockedMin(workgroup_atomic_arr[1], int(1), _e167); uint _e171; InterlockedMin(workgroup_struct.atomic_scalar, 1u, _e171); - int _e176; InterlockedMin(workgroup_struct.atomic_arr[1], 1, _e176); + int _e176; InterlockedMin(workgroup_struct.atomic_arr[1], int(1), _e176); GroupMemoryBarrierWithGroupSync(); uint _e179; storage_atomic_scalar.InterlockedAnd(0, 1u, _e179); - int _e183; storage_atomic_arr.InterlockedAnd(4, 1, _e183); + int _e183; storage_atomic_arr.InterlockedAnd(4, int(1), _e183); uint _e187; storage_struct.InterlockedAnd(0, 1u, _e187); - int _e192; storage_struct.InterlockedAnd(4+4, 1, _e192); + int _e192; storage_struct.InterlockedAnd(4+4, int(1), _e192); uint _e195; InterlockedAnd(workgroup_atomic_scalar, 1u, _e195); - int _e199; InterlockedAnd(workgroup_atomic_arr[1], 1, _e199); + int _e199; InterlockedAnd(workgroup_atomic_arr[1], int(1), _e199); uint _e203; InterlockedAnd(workgroup_struct.atomic_scalar, 1u, _e203); - int _e208; InterlockedAnd(workgroup_struct.atomic_arr[1], 1, _e208); + int _e208; InterlockedAnd(workgroup_struct.atomic_arr[1], int(1), _e208); GroupMemoryBarrierWithGroupSync(); uint _e211; storage_atomic_scalar.InterlockedOr(0, 1u, _e211); - int _e215; storage_atomic_arr.InterlockedOr(4, 1, _e215); + int _e215; storage_atomic_arr.InterlockedOr(4, int(1), _e215); uint _e219; storage_struct.InterlockedOr(0, 1u, _e219); - int _e224; storage_struct.InterlockedOr(4+4, 1, _e224); + int _e224; storage_struct.InterlockedOr(4+4, int(1), _e224); uint _e227; InterlockedOr(workgroup_atomic_scalar, 1u, _e227); - int _e231; InterlockedOr(workgroup_atomic_arr[1], 1, _e231); + int _e231; InterlockedOr(workgroup_atomic_arr[1], int(1), _e231); uint _e235; InterlockedOr(workgroup_struct.atomic_scalar, 1u, _e235); - int _e240; InterlockedOr(workgroup_struct.atomic_arr[1], 1, _e240); + int _e240; InterlockedOr(workgroup_struct.atomic_arr[1], int(1), _e240); GroupMemoryBarrierWithGroupSync(); uint _e243; storage_atomic_scalar.InterlockedXor(0, 1u, _e243); - int _e247; storage_atomic_arr.InterlockedXor(4, 1, _e247); + int _e247; storage_atomic_arr.InterlockedXor(4, int(1), _e247); uint _e251; storage_struct.InterlockedXor(0, 1u, _e251); - int _e256; storage_struct.InterlockedXor(4+4, 1, _e256); + int _e256; storage_struct.InterlockedXor(4+4, int(1), _e256); uint _e259; InterlockedXor(workgroup_atomic_scalar, 1u, _e259); - int _e263; InterlockedXor(workgroup_atomic_arr[1], 1, _e263); + int _e263; InterlockedXor(workgroup_atomic_arr[1], int(1), _e263); uint _e267; InterlockedXor(workgroup_struct.atomic_scalar, 1u, _e267); - int _e272; InterlockedXor(workgroup_struct.atomic_arr[1], 1, _e272); + int _e272; InterlockedXor(workgroup_struct.atomic_arr[1], int(1), _e272); uint _e275; storage_atomic_scalar.InterlockedExchange(0, 1u, _e275); - int _e279; storage_atomic_arr.InterlockedExchange(4, 1, _e279); + int _e279; storage_atomic_arr.InterlockedExchange(4, int(1), _e279); uint _e283; storage_struct.InterlockedExchange(0, 1u, _e283); - int _e288; storage_struct.InterlockedExchange(4+4, 1, _e288); + int _e288; storage_struct.InterlockedExchange(4+4, int(1), _e288); uint _e291; InterlockedExchange(workgroup_atomic_scalar, 1u, _e291); - int _e295; InterlockedExchange(workgroup_atomic_arr[1], 1, _e295); + int _e295; InterlockedExchange(workgroup_atomic_arr[1], int(1), _e295); uint _e299; InterlockedExchange(workgroup_struct.atomic_scalar, 1u, _e299); - int _e304; InterlockedExchange(workgroup_struct.atomic_arr[1], 1, _e304); + int _e304; InterlockedExchange(workgroup_struct.atomic_arr[1], int(1), _e304); return; } diff --git a/naga/tests/out/hlsl/atomicTexture-int64.hlsl b/naga/tests/out/hlsl/atomicTexture-int64.hlsl index 056489c790..ed9e57dd62 100644 --- a/naga/tests/out/hlsl/atomicTexture-int64.hlsl +++ b/naga/tests/out/hlsl/atomicTexture-int64.hlsl @@ -10,8 +10,8 @@ RWTexture2D image : register(u0); [numthreads(2, 1, 1)] void cs_main(uint3 id : SV_GroupThreadID) { - InterlockedMax(image[int2(0, 0)],1uL); + InterlockedMax(image[int2(int(0), int(0))],1uL); GroupMemoryBarrierWithGroupSync(); - InterlockedMin(image[int2(0, 0)],1uL); + InterlockedMin(image[int2(int(0), int(0))],1uL); return; } diff --git a/naga/tests/out/hlsl/atomicTexture.hlsl b/naga/tests/out/hlsl/atomicTexture.hlsl index 241cdab678..d598be925d 100644 --- a/naga/tests/out/hlsl/atomicTexture.hlsl +++ b/naga/tests/out/hlsl/atomicTexture.hlsl @@ -11,17 +11,17 @@ RWTexture2D image_s : register(u1); [numthreads(2, 1, 1)] void cs_main(uint3 id : SV_GroupThreadID) { - InterlockedMax(image_u[int2(0, 0)],1u); - InterlockedMin(image_u[int2(0, 0)],1u); - InterlockedAdd(image_u[int2(0, 0)],1u); - InterlockedAnd(image_u[int2(0, 0)],1u); - InterlockedOr(image_u[int2(0, 0)],1u); - InterlockedXor(image_u[int2(0, 0)],1u); - InterlockedMax(image_s[int2(0, 0)],1); - InterlockedMin(image_s[int2(0, 0)],1); - InterlockedAdd(image_s[int2(0, 0)],1); - InterlockedAnd(image_s[int2(0, 0)],1); - InterlockedOr(image_s[int2(0, 0)],1); - InterlockedXor(image_s[int2(0, 0)],1); + InterlockedMax(image_u[int2(int(0), int(0))],1u); + InterlockedMin(image_u[int2(int(0), int(0))],1u); + InterlockedAdd(image_u[int2(int(0), int(0))],1u); + InterlockedAnd(image_u[int2(int(0), int(0))],1u); + InterlockedOr(image_u[int2(int(0), int(0))],1u); + InterlockedXor(image_u[int2(int(0), int(0))],1u); + InterlockedMax(image_s[int2(int(0), int(0))],int(1)); + InterlockedMin(image_s[int2(int(0), int(0))],int(1)); + InterlockedAdd(image_s[int2(int(0), int(0))],int(1)); + InterlockedAnd(image_s[int2(int(0), int(0))],int(1)); + InterlockedOr(image_s[int2(int(0), int(0))],int(1)); + InterlockedXor(image_s[int2(int(0), int(0))],int(1)); return; } diff --git a/naga/tests/out/hlsl/binding-arrays.hlsl b/naga/tests/out/hlsl/binding-arrays.hlsl index 3f0a533b6c..2f16123199 100644 --- a/naga/tests/out/hlsl/binding-arrays.hlsl +++ b/naga/tests/out/hlsl/binding-arrays.hlsl @@ -62,7 +62,7 @@ float4 main(FragmentInput_main fragmentinput_main) : SV_Target0 uint uniform_index = uni.index; uint non_uniform_index = fragment_in.index; float2 uv = (0.0).xx; - int2 pix = (0).xx; + int2 pix = (int(0)).xx; uint2 _e22 = u2_; u2_ = (_e22 + NagaDimensions2D(texture_array_unbounded[0])); uint2 _e27 = u2_; @@ -87,13 +87,13 @@ float4 main(FragmentInput_main fragmentinput_main) : SV_Target0 float4 _e76 = texture_array_depth[NonUniformResourceIndex(non_uniform_index)].GatherCmp(nagaComparisonSamplerHeap[NonUniformResourceIndex(nagaGroup0SamplerIndexArray[samp_comp + non_uniform_index])], uv, 0.0); float4 _e77 = v4_; v4_ = (_e77 + _e76); - float4 _e82 = texture_array_unbounded[0].Load(int3(pix, 0)); + float4 _e82 = texture_array_unbounded[0].Load(int3(pix, int(0))); float4 _e83 = v4_; v4_ = (_e83 + _e82); - float4 _e88 = texture_array_unbounded[uniform_index].Load(int3(pix, 0)); + float4 _e88 = texture_array_unbounded[uniform_index].Load(int3(pix, int(0))); float4 _e89 = v4_; v4_ = (_e89 + _e88); - float4 _e94 = texture_array_unbounded[NonUniformResourceIndex(non_uniform_index)].Load(int3(pix, 0)); + float4 _e94 = texture_array_unbounded[NonUniformResourceIndex(non_uniform_index)].Load(int3(pix, int(0))); float4 _e95 = v4_; v4_ = (_e95 + _e94); uint _e100 = u1_; diff --git a/naga/tests/out/hlsl/bitcast.hlsl b/naga/tests/out/hlsl/bitcast.hlsl index b21408dda5..420f39dd94 100644 --- a/naga/tests/out/hlsl/bitcast.hlsl +++ b/naga/tests/out/hlsl/bitcast.hlsl @@ -1,9 +1,9 @@ [numthreads(1, 1, 1)] void main() { - int2 i2_ = (0).xx; - int3 i3_ = (0).xxx; - int4 i4_ = (0).xxxx; + int2 i2_ = (int(0)).xx; + int3 i3_ = (int(0)).xxx; + int4 i4_ = (int(0)).xxxx; uint2 u2_ = (0u).xx; uint3 u3_ = (0u).xxx; uint4 u4_ = (0u).xxxx; diff --git a/naga/tests/out/hlsl/bits.hlsl b/naga/tests/out/hlsl/bits.hlsl index 1987e15514..f75cba90b6 100644 --- a/naga/tests/out/hlsl/bits.hlsl +++ b/naga/tests/out/hlsl/bits.hlsl @@ -177,10 +177,10 @@ uint4 naga_extractBits( [numthreads(1, 1, 1)] void main() { - int i = 0; - int2 i2_ = (0).xx; - int3 i3_ = (0).xxx; - int4 i4_ = (0).xxxx; + int i = int(0); + int2 i2_ = (int(0)).xx; + int3 i3_ = (int(0)).xxx; + int4 i4_ = (int(0)).xxxx; uint u = 0u; uint2 u2_ = (0u).xx; uint3 u3_ = (0u).xxx; diff --git a/naga/tests/out/hlsl/boids.hlsl b/naga/tests/out/hlsl/boids.hlsl index 8934a9bca2..58d444706b 100644 --- a/naga/tests/out/hlsl/boids.hlsl +++ b/naga/tests/out/hlsl/boids.hlsl @@ -27,8 +27,8 @@ void main(uint3 global_invocation_id : SV_DispatchThreadID) float2 cMass = float2(0.0, 0.0); float2 cVel = float2(0.0, 0.0); float2 colVel = float2(0.0, 0.0); - int cMassCount = 0; - int cVelCount = 0; + int cMassCount = int(0); + int cVelCount = int(0); float2 pos = (float2)0; float2 vel = (float2)0; uint i = 0u; @@ -73,7 +73,7 @@ void main(uint3 global_invocation_id : SV_DispatchThreadID) float2 _e61 = pos; cMass = (_e60 + _e61); int _e63 = cMassCount; - cMassCount = (_e63 + 1); + cMassCount = asint(asuint(_e63) + asuint(int(1))); } float2 _e66 = pos; float2 _e67 = vPos; @@ -92,18 +92,18 @@ void main(uint3 global_invocation_id : SV_DispatchThreadID) float2 _e86 = vel; cVel = (_e85 + _e86); int _e88 = cVelCount; - cVelCount = (_e88 + 1); + cVelCount = asint(asuint(_e88) + asuint(int(1))); } } int _e94 = cMassCount; - if ((_e94 > 0)) { + if ((_e94 > int(0))) { float2 _e97 = cMass; int _e98 = cMassCount; float2 _e102 = vPos; cMass = ((_e97 / (float(_e98)).xx) - _e102); } int _e104 = cVelCount; - if ((_e104 > 0)) { + if ((_e104 > int(0))) { float2 _e107 = cVel; int _e108 = cVelCount; cVel = (_e107 / (float(_e108)).xx); diff --git a/naga/tests/out/hlsl/collatz.hlsl b/naga/tests/out/hlsl/collatz.hlsl index 3a250a4f25..926ddaf932 100644 --- a/naga/tests/out/hlsl/collatz.hlsl +++ b/naga/tests/out/hlsl/collatz.hlsl @@ -1,5 +1,13 @@ RWByteAddressBuffer v_indices : register(u0); +uint naga_mod(uint lhs, uint rhs) { + return lhs % (rhs == 0u ? 1u : rhs); +} + +uint naga_div(uint lhs, uint rhs) { + return lhs / (rhs == 0u ? 1u : rhs); +} + uint collatz_iterations(uint n_base) { uint n = (uint)0; @@ -17,9 +25,9 @@ uint collatz_iterations(uint n_base) } { uint _e7 = n; - if (((_e7 % 2u) == 0u)) { + if ((naga_mod(_e7, 2u) == 0u)) { uint _e12 = n; - n = (_e12 / 2u); + n = naga_div(_e12, 2u); } else { uint _e16 = n; n = ((3u * _e16) + 1u); diff --git a/naga/tests/out/hlsl/const-exprs.hlsl b/naga/tests/out/hlsl/const-exprs.hlsl index 9d62504f78..ab2160cb19 100644 --- a/naga/tests/out/hlsl/const-exprs.hlsl +++ b/naga/tests/out/hlsl/const-exprs.hlsl @@ -1,45 +1,45 @@ static const uint TWO = 2u; -static const int THREE = 3; -static const int FOUR = 4; -static const int FOUR_ALIAS = 4; -static const int TEST_CONSTANT_ADDITION = 8; -static const int TEST_CONSTANT_ALIAS_ADDITION = 8; +static const int THREE = int(3); +static const int FOUR = int(4); +static const int FOUR_ALIAS = int(4); +static const int TEST_CONSTANT_ADDITION = int(8); +static const int TEST_CONSTANT_ALIAS_ADDITION = int(8); static const float PI = 3.141; static const float phi_sun = 6.282; static const float4 DIV = float4(0.44444445, 0.0, 0.0, 0.0); -static const int TEXTURE_KIND_REGULAR = 0; -static const int TEXTURE_KIND_WARP = 1; -static const int TEXTURE_KIND_SKY = 2; +static const int TEXTURE_KIND_REGULAR = int(0); +static const int TEXTURE_KIND_WARP = int(1); +static const int TEXTURE_KIND_SKY = int(2); static const float2 add_vec = float2(4.0, 5.0); static const bool2 compare_vec = bool2(true, false); void swizzle_of_compose() { - int4 out_ = int4(4, 3, 2, 1); + int4 out_ = int4(int(4), int(3), int(2), int(1)); return; } void index_of_compose() { - int out_1 = 2; + int out_1 = int(2); return; } void compose_three_deep() { - int out_2 = 6; + int out_2 = int(6); return; } void non_constant_initializers() { - int w = 30; + int w = int(30); int x = (int)0; int y = (int)0; - int z = 70; + int z = int(70); int4 out_3 = (int4)0; int _e2 = w; @@ -56,14 +56,14 @@ void non_constant_initializers() void splat_of_constant() { - int4 out_4 = int4(-4, -4, -4, -4); + int4 out_4 = int4(int(-4), int(-4), int(-4), int(-4)); return; } void compose_of_constant() { - int4 out_5 = int4(-4, -4, -4, -4); + int4 out_5 = int4(int(-4), int(-4), int(-4), int(-4)); return; } @@ -95,9 +95,9 @@ uint map_texture_kind(int texture_kind) void compose_vector_zero_val_binop() { - int3 a = int3(1, 1, 1); - int3 b = int3(0, 1, 2); - int3 c = int3(1, 0, 2); + int3 a = int3(int(1), int(1), int(1)); + int3 b = int3(int(0), int(1), int(2)); + int3 c = int3(int(1), int(0), int(2)); return; } diff --git a/naga/tests/out/hlsl/constructors.hlsl b/naga/tests/out/hlsl/constructors.hlsl index c354737114..5cc3702630 100644 --- a/naga/tests/out/hlsl/constructors.hlsl +++ b/naga/tests/out/hlsl/constructors.hlsl @@ -62,7 +62,7 @@ static const uint2 cz4_ = ZeroValueuint2(); static const float2x2 cz5_ = ZeroValuefloat2x2(); static const Foo cz6_[3] = ZeroValuearray3_Foo_(); static const Foo cz7_ = ZeroValueFoo(); -static const int cp3_[4] = Constructarray4_int_(0, 1, 2, 3); +static const int cp3_[4] = Constructarray4_int_(int(0), int(1), int(2), int(3)); Foo ConstructFoo(float4 arg0, int arg1) { Foo ret = (Foo)0; @@ -80,12 +80,12 @@ void main() { Foo foo = (Foo)0; - foo = ConstructFoo((1.0).xxxx, 1); + foo = ConstructFoo((1.0).xxxx, int(1)); float2x2 m0_ = float2x2(float2(1.0, 0.0), float2(0.0, 1.0)); float4x4 m1_ = float4x4(float4(1.0, 0.0, 0.0, 0.0), float4(0.0, 1.0, 0.0, 0.0), float4(0.0, 0.0, 1.0, 0.0), float4(0.0, 0.0, 0.0, 1.0)); uint2 cit0_ = (0u).xx; float2x2 cit1_ = float2x2((0.0).xx, (0.0).xx); - int cit2_[4] = Constructarray4_int_(0, 1, 2, 3); + int cit2_[4] = Constructarray4_int_(int(0), int(1), int(2), int(3)); uint2 ic4_ = uint2(0u, 0u); float2x3 ic5_ = float2x3(float3(0.0, 0.0, 0.0), float3(0.0, 0.0, 0.0)); return; diff --git a/naga/tests/out/hlsl/control-flow.hlsl b/naga/tests/out/hlsl/control-flow.hlsl index 7a8cb73779..ad36cc6201 100644 --- a/naga/tests/out/hlsl/control-flow.hlsl +++ b/naga/tests/out/hlsl/control-flow.hlsl @@ -7,7 +7,7 @@ void switch_default_break(int i) void switch_case_break() { - switch(0) { + switch(int(0)) { case 0: { break; } @@ -125,7 +125,7 @@ void loop_switch_continue_nesting(int x_1, int y, int z) void loop_switch_omit_continue_variable_checks(int x_2, int y_1, int z_1, int w) { - int pos_1 = 0; + int pos_1 = int(0); uint2 loop_bound_4 = uint2(0u, 0u); while(true) { @@ -134,7 +134,7 @@ void loop_switch_omit_continue_variable_checks(int x_2, int y_1, int z_1, int w) bool should_continue_5 = false; switch(x_2) { case 1: { - pos_1 = 1; + pos_1 = int(1); break; } default: { @@ -160,7 +160,7 @@ void loop_switch_omit_continue_variable_checks(int x_2, int y_1, int z_1, int w) default: { switch(z_1) { case 1: { - pos_1 = 2; + pos_1 = int(2); break; } default: { @@ -194,30 +194,30 @@ void main(uint3 global_id : SV_DispatchThreadID) DeviceMemoryBarrierWithGroupSync(); GroupMemoryBarrierWithGroupSync(); do { - pos = 1; + pos = int(1); } while(false); int _e4 = pos; switch(_e4) { case 1: { - pos = 0; + pos = int(0); break; } case 2: { - pos = 1; + pos = int(1); break; } case 3: case 4: { - pos = 2; + pos = int(2); break; } case 5: { - pos = 3; + pos = int(3); break; } default: case 6: { - pos = 4; + pos = int(4); break; } } @@ -232,22 +232,22 @@ void main(uint3 global_id : SV_DispatchThreadID) int _e11 = pos; switch(_e11) { case 1: { - pos = 0; + pos = int(0); break; } case 2: { - pos = 1; + pos = int(1); return; } case 3: { - pos = 2; + pos = int(2); return; } case 4: { return; } default: { - pos = 3; + pos = int(3); return; } } diff --git a/naga/tests/out/hlsl/empty-global-name.hlsl b/naga/tests/out/hlsl/empty-global-name.hlsl index 64227b0bc7..4f45d94749 100644 --- a/naga/tests/out/hlsl/empty-global-name.hlsl +++ b/naga/tests/out/hlsl/empty-global-name.hlsl @@ -7,7 +7,7 @@ RWByteAddressBuffer unnamed : register(u0); void function() { int _e3 = asint(unnamed.Load(0)); - unnamed.Store(0, asuint((_e3 + 1))); + unnamed.Store(0, asuint(asint(asuint(_e3) + asuint(int(1))))); return; } diff --git a/naga/tests/out/hlsl/fetch_depth.hlsl b/naga/tests/out/hlsl/fetch_depth.hlsl index 04a1f51353..71788135f1 100644 --- a/naga/tests/out/hlsl/fetch_depth.hlsl +++ b/naga/tests/out/hlsl/fetch_depth.hlsl @@ -13,7 +13,7 @@ Texture2D global_2 : register(t2); void function() { uint2 _e6 = asuint(global_1.Load2(0)); - float _e7 = global_2.Load(int3(_e6, 0)).x; + float _e7 = global_2.Load(int3(_e6, int(0))).x; global.Store(0, asuint((_e7).xxxx.x)); return; } diff --git a/naga/tests/out/hlsl/fragment-output.hlsl b/naga/tests/out/hlsl/fragment-output.hlsl index f1f0a82ae8..bc11c8518e 100644 --- a/naga/tests/out/hlsl/fragment-output.hlsl +++ b/naga/tests/out/hlsl/fragment-output.hlsl @@ -21,10 +21,10 @@ FragmentOutputVec4Vec3_ main_vec4vec3_() FragmentOutputVec4Vec3_ output = (FragmentOutputVec4Vec3_)0; output.vec4f = (0.0).xxxx; - output.vec4i = (0).xxxx; + output.vec4i = (int(0)).xxxx; output.vec4u = (0u).xxxx; output.vec3f = (0.0).xxx; - output.vec3i = (0).xxx; + output.vec3i = (int(0)).xxx; output.vec3u = (0u).xxx; FragmentOutputVec4Vec3_ _e19 = output; const FragmentOutputVec4Vec3_ fragmentoutputvec4vec3_ = _e19; @@ -36,10 +36,10 @@ FragmentOutputVec2Scalar main_vec2scalar() FragmentOutputVec2Scalar output_1 = (FragmentOutputVec2Scalar)0; output_1.vec2f = (0.0).xx; - output_1.vec2i = (0).xx; + output_1.vec2i = (int(0)).xx; output_1.vec2u = (0u).xx; output_1.scalarf = 0.0; - output_1.scalari = 0; + output_1.scalari = int(0); output_1.scalaru = 0u; FragmentOutputVec2Scalar _e16 = output_1; const FragmentOutputVec2Scalar fragmentoutputvec2scalar = _e16; diff --git a/naga/tests/out/hlsl/functions.hlsl b/naga/tests/out/hlsl/functions.hlsl index 6d7e210307..c2341fb43a 100644 --- a/naga/tests/out/hlsl/functions.hlsl +++ b/naga/tests/out/hlsl/functions.hlsl @@ -8,13 +8,13 @@ float2 test_fma() int test_integer_dot_product() { - int2 a_2_ = (1).xx; - int2 b_2_ = (1).xx; + int2 a_2_ = (int(1)).xx; + int2 b_2_ = (int(1)).xx; int c_2_ = dot(a_2_, b_2_); uint3 a_3_ = (1u).xxx; uint3 b_3_ = (1u).xxx; uint c_3_ = dot(a_3_, b_3_); - int c_4_ = dot((4).xxxx, (2).xxxx); + int c_4_ = dot((int(4)).xxxx, (int(2)).xxxx); return c_4_; } diff --git a/naga/tests/out/hlsl/globals.hlsl b/naga/tests/out/hlsl/globals.hlsl index d320899b89..af2951a334 100644 --- a/naga/tests/out/hlsl/globals.hlsl +++ b/naga/tests/out/hlsl/globals.hlsl @@ -84,7 +84,7 @@ FooStruct ConstructFooStruct(float3 arg0, float arg1) { void test_msl_packed_vec3_() { - int idx = 1; + int idx = int(1); alignment.Store3(0, asuint((1.0).xxx)); alignment.Store(0+0, asuint(1.0)); diff --git a/naga/tests/out/hlsl/image.hlsl b/naga/tests/out/hlsl/image.hlsl index 30bfd86aeb..97eb0ab748 100644 --- a/naga/tests/out/hlsl/image.hlsl +++ b/naga/tests/out/hlsl/image.hlsl @@ -24,6 +24,11 @@ Texture2D image_2d_depth : register(t2, space1); Texture2DArray image_2d_array_depth : register(t3, space1); TextureCube image_cube_depth : register(t4, space1); +int2 naga_mod(int2 lhs, int2 rhs) { + int2 divisor = ((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs; + return lhs - (lhs / divisor) * divisor; +} + uint2 NagaRWDimensions2D(RWTexture2D tex) { uint4 ret; @@ -35,18 +40,18 @@ uint2 NagaRWDimensions2D(RWTexture2D tex) void main(uint3 local_id : SV_GroupThreadID) { uint2 dim = NagaRWDimensions2D(image_storage_src); - int2 itc = (int2((dim * local_id.xy)) % int2(10, 20)); + int2 itc = naga_mod(int2((dim * local_id.xy)), int2(int(10), int(20))); uint4 value1_ = image_mipmapped_src.Load(int3(itc, int(local_id.z))); uint4 value2_ = image_multisampled_src.Load(itc, int(local_id.z)); uint4 value4_ = image_storage_src.Load(itc); - uint4 value5_ = image_array_src.Load(int4(itc, local_id.z, (int(local_id.z) + 1))); - uint4 value6_ = image_array_src.Load(int4(itc, int(local_id.z), (int(local_id.z) + 1))); + uint4 value5_ = image_array_src.Load(int4(itc, local_id.z, asint(asuint(int(local_id.z)) + asuint(int(1))))); + uint4 value6_ = image_array_src.Load(int4(itc, int(local_id.z), asint(asuint(int(local_id.z)) + asuint(int(1))))); uint4 value7_ = image_1d_src.Load(int2(int(local_id.x), int(local_id.z))); uint4 value1u = image_mipmapped_src.Load(int3(uint2(itc), int(local_id.z))); uint4 value2u = image_multisampled_src.Load(uint2(itc), int(local_id.z)); uint4 value4u = image_storage_src.Load(uint2(itc)); - uint4 value5u = image_array_src.Load(int4(uint2(itc), local_id.z, (int(local_id.z) + 1))); - uint4 value6u = image_array_src.Load(int4(uint2(itc), int(local_id.z), (int(local_id.z) + 1))); + uint4 value5u = image_array_src.Load(int4(uint2(itc), local_id.z, asint(asuint(int(local_id.z)) + asuint(int(1))))); + uint4 value6u = image_array_src.Load(int4(uint2(itc), int(local_id.z), asint(asuint(int(local_id.z)) + asuint(int(1))))); uint4 value7u = image_1d_src.Load(int2(uint(local_id.x), int(local_id.z))); image_dst[itc.x] = ((((value1_ + value2_) + value4_) + value5_) + value6_); image_dst[uint(itc.x)] = ((((value1u + value2u) + value4u) + value5u) + value6u); @@ -57,7 +62,7 @@ void main(uint3 local_id : SV_GroupThreadID) void depth_load(uint3 local_id_1 : SV_GroupThreadID) { uint2 dim_1 = NagaRWDimensions2D(image_storage_src); - int2 itc_1 = (int2((dim_1 * local_id_1.xy)) % int2(10, 20)); + int2 itc_1 = naga_mod(int2((dim_1 * local_id_1.xy)), int2(int(10), int(20))); float val = image_depth_multisampled_src.Load(itc_1, int(local_id_1.z)).x; image_dst[itc_1.x] = (uint(val)).xxxx; return; @@ -159,15 +164,15 @@ float4 queries() : SV_Position uint dim_1d = NagaDimensions1D(image_1d); uint dim_1d_lod = NagaMipDimensions1D(image_1d, int(dim_1d)); uint2 dim_2d = NagaDimensions2D(image_2d); - uint2 dim_2d_lod = NagaMipDimensions2D(image_2d, 1); + uint2 dim_2d_lod = NagaMipDimensions2D(image_2d, int(1)); uint2 dim_2d_array = NagaDimensions2DArray(image_2d_array); - uint2 dim_2d_array_lod = NagaMipDimensions2DArray(image_2d_array, 1); + uint2 dim_2d_array_lod = NagaMipDimensions2DArray(image_2d_array, int(1)); uint2 dim_cube = NagaDimensionsCube(image_cube); - uint2 dim_cube_lod = NagaMipDimensionsCube(image_cube, 1); + uint2 dim_cube_lod = NagaMipDimensionsCube(image_cube, int(1)); uint2 dim_cube_array = NagaDimensionsCubeArray(image_cube_array); - uint2 dim_cube_array_lod = NagaMipDimensionsCubeArray(image_cube_array, 1); + uint2 dim_cube_array_lod = NagaMipDimensionsCubeArray(image_cube_array, int(1)); uint3 dim_3d = NagaDimensions3D(image_3d); - uint3 dim_3d_lod = NagaMipDimensions3D(image_3d, 1); + uint3 dim_3d_lod = NagaMipDimensions3D(image_3d, int(1)); uint2 dim_2s_ms = NagaMSDimensions2D(image_aa); uint sum = ((((((((((dim_1d + dim_2d.y) + dim_2d_lod.y) + dim_2d_array.y) + dim_2d_array_lod.y) + dim_cube.y) + dim_cube_lod.y) + dim_cube_array.y) + dim_cube_array_lod.y) + dim_3d.z) + dim_3d_lod.z); return (float(sum)).xxxx; @@ -256,46 +261,46 @@ float4 texture_sample() : SV_Target0 float4 _e14 = image_2d.Sample(sampler_reg, tc); float4 _e15 = a; a = (_e15 + _e14); - float4 _e19 = image_2d.Sample(sampler_reg, tc, int2(int2(3, 1))); + float4 _e19 = image_2d.Sample(sampler_reg, tc, int2(int2(int(3), int(1)))); float4 _e20 = a; a = (_e20 + _e19); float4 _e24 = image_2d.SampleLevel(sampler_reg, tc, 2.3); float4 _e25 = a; a = (_e25 + _e24); - float4 _e29 = image_2d.SampleLevel(sampler_reg, tc, 2.3, int2(int2(3, 1))); + float4 _e29 = image_2d.SampleLevel(sampler_reg, tc, 2.3, int2(int2(int(3), int(1)))); float4 _e30 = a; a = (_e30 + _e29); - float4 _e35 = image_2d.SampleBias(sampler_reg, tc, 2.0, int2(int2(3, 1))); + float4 _e35 = image_2d.SampleBias(sampler_reg, tc, 2.0, int2(int2(int(3), int(1)))); float4 _e36 = a; a = (_e36 + _e35); float4 _e41 = image_2d_array.Sample(sampler_reg, float3(tc, 0u)); float4 _e42 = a; a = (_e42 + _e41); - float4 _e47 = image_2d_array.Sample(sampler_reg, float3(tc, 0u), int2(int2(3, 1))); + float4 _e47 = image_2d_array.Sample(sampler_reg, float3(tc, 0u), int2(int2(int(3), int(1)))); float4 _e48 = a; a = (_e48 + _e47); float4 _e53 = image_2d_array.SampleLevel(sampler_reg, float3(tc, 0u), 2.3); float4 _e54 = a; a = (_e54 + _e53); - float4 _e59 = image_2d_array.SampleLevel(sampler_reg, float3(tc, 0u), 2.3, int2(int2(3, 1))); + float4 _e59 = image_2d_array.SampleLevel(sampler_reg, float3(tc, 0u), 2.3, int2(int2(int(3), int(1)))); float4 _e60 = a; a = (_e60 + _e59); - float4 _e66 = image_2d_array.SampleBias(sampler_reg, float3(tc, 0u), 2.0, int2(int2(3, 1))); + float4 _e66 = image_2d_array.SampleBias(sampler_reg, float3(tc, 0u), 2.0, int2(int2(int(3), int(1)))); float4 _e67 = a; a = (_e67 + _e66); - float4 _e72 = image_2d_array.Sample(sampler_reg, float3(tc, 0)); + float4 _e72 = image_2d_array.Sample(sampler_reg, float3(tc, int(0))); float4 _e73 = a; a = (_e73 + _e72); - float4 _e78 = image_2d_array.Sample(sampler_reg, float3(tc, 0), int2(int2(3, 1))); + float4 _e78 = image_2d_array.Sample(sampler_reg, float3(tc, int(0)), int2(int2(int(3), int(1)))); float4 _e79 = a; a = (_e79 + _e78); - float4 _e84 = image_2d_array.SampleLevel(sampler_reg, float3(tc, 0), 2.3); + float4 _e84 = image_2d_array.SampleLevel(sampler_reg, float3(tc, int(0)), 2.3); float4 _e85 = a; a = (_e85 + _e84); - float4 _e90 = image_2d_array.SampleLevel(sampler_reg, float3(tc, 0), 2.3, int2(int2(3, 1))); + float4 _e90 = image_2d_array.SampleLevel(sampler_reg, float3(tc, int(0)), 2.3, int2(int2(int(3), int(1)))); float4 _e91 = a; a = (_e91 + _e90); - float4 _e97 = image_2d_array.SampleBias(sampler_reg, float3(tc, 0), 2.0, int2(int2(3, 1))); + float4 _e97 = image_2d_array.SampleBias(sampler_reg, float3(tc, int(0)), 2.0, int2(int2(int(3), int(1)))); float4 _e98 = a; a = (_e98 + _e97); float4 _e103 = image_cube_array.Sample(sampler_reg, float4(tc3_, 0u)); @@ -307,13 +312,13 @@ float4 texture_sample() : SV_Target0 float4 _e116 = image_cube_array.SampleBias(sampler_reg, float4(tc3_, 0u), 2.0); float4 _e117 = a; a = (_e117 + _e116); - float4 _e122 = image_cube_array.Sample(sampler_reg, float4(tc3_, 0)); + float4 _e122 = image_cube_array.Sample(sampler_reg, float4(tc3_, int(0))); float4 _e123 = a; a = (_e123 + _e122); - float4 _e128 = image_cube_array.SampleLevel(sampler_reg, float4(tc3_, 0), 2.3); + float4 _e128 = image_cube_array.SampleLevel(sampler_reg, float4(tc3_, int(0)), 2.3); float4 _e129 = a; a = (_e129 + _e128); - float4 _e135 = image_cube_array.SampleBias(sampler_reg, float4(tc3_, 0), 2.0); + float4 _e135 = image_cube_array.SampleBias(sampler_reg, float4(tc3_, int(0)), 2.0); float4 _e136 = a; a = (_e136 + _e135); float4 _e138 = a; @@ -332,7 +337,7 @@ float texture_sample_comparison() : SV_Target0 float _e14 = image_2d_array_depth.SampleCmp(sampler_cmp, float3(tc_1, 0u), 0.5); float _e15 = a_1; a_1 = (_e15 + _e14); - float _e20 = image_2d_array_depth.SampleCmp(sampler_cmp, float3(tc_1, 0), 0.5); + float _e20 = image_2d_array_depth.SampleCmp(sampler_cmp, float3(tc_1, int(0)), 0.5); float _e21 = a_1; a_1 = (_e21 + _e20); float _e25 = image_cube_depth.SampleCmp(sampler_cmp, tc3_1, 0.5); @@ -344,7 +349,7 @@ float texture_sample_comparison() : SV_Target0 float _e36 = image_2d_array_depth.SampleCmpLevelZero(sampler_cmp, float3(tc_1, 0u), 0.5); float _e37 = a_1; a_1 = (_e37 + _e36); - float _e42 = image_2d_array_depth.SampleCmpLevelZero(sampler_cmp, float3(tc_1, 0), 0.5); + float _e42 = image_2d_array_depth.SampleCmpLevelZero(sampler_cmp, float3(tc_1, int(0)), 0.5); float _e43 = a_1; a_1 = (_e43 + _e42); float _e47 = image_cube_depth.SampleCmpLevelZero(sampler_cmp, tc3_1, 0.5); @@ -358,9 +363,9 @@ float4 gather() : SV_Target0 { float2 tc_2 = (0.5).xx; float4 s2d = image_2d.GatherGreen(sampler_reg, tc_2); - float4 s2d_offset = image_2d.GatherAlpha(sampler_reg, tc_2, int2(int2(3, 1))); + float4 s2d_offset = image_2d.GatherAlpha(sampler_reg, tc_2, int2(int2(int(3), int(1)))); float4 s2d_depth = image_2d_depth.GatherCmp(sampler_cmp, tc_2, 0.5); - float4 s2d_depth_offset = image_2d_depth.GatherCmp(sampler_cmp, tc_2, 0.5, int2(int2(3, 1))); + float4 s2d_depth_offset = image_2d_depth.GatherCmp(sampler_cmp, tc_2, 0.5, int2(int2(int(3), int(1)))); uint4 u = image_2d_u32_.Gather(sampler_reg, tc_2); int4 i = image_2d_i32_.Gather(sampler_reg, tc_2); float4 f = (float4(u) + float4(i)); @@ -372,6 +377,6 @@ float4 depth_no_comparison() : SV_Target0 float2 tc_3 = (0.5).xx; float s2d_1 = image_2d_depth.Sample(sampler_reg, tc_3); float4 s2d_gather = image_2d_depth.Gather(sampler_reg, tc_3); - float s2d_level = image_2d_depth.SampleLevel(sampler_reg, tc_3, 1); + float s2d_level = image_2d_depth.SampleLevel(sampler_reg, tc_3, int(1)); return (((s2d_1).xxxx + s2d_gather) + (s2d_level).xxxx); } diff --git a/naga/tests/out/hlsl/int64.hlsl b/naga/tests/out/hlsl/int64.hlsl index 26441380b1..84ff643070 100644 --- a/naga/tests/out/hlsl/int64.hlsl +++ b/naga/tests/out/hlsl/int64.hlsl @@ -75,7 +75,7 @@ int64_t int64_function(int64_t x) int _e26 = input_uniform.val_i32_; int64_t _e27 = val; int64_t _e31 = val; - val = (_e31 + int64_t((_e26 + int(_e27)))); + val = (_e31 + int64_t(asint(asuint(_e26) + asuint(int(_e27))))); float _e35 = input_uniform.val_f32_; int64_t _e36 = val; int64_t _e40 = val; @@ -162,7 +162,7 @@ uint64_t uint64_function(uint64_t x_1) int _e26 = input_uniform.val_i32_; uint64_t _e27 = val_1; uint64_t _e31 = val_1; - val_1 = (_e31 + uint64_t((_e26 + int(_e27)))); + val_1 = (_e31 + uint64_t(asint(asuint(_e26) + asuint(int(_e27))))); float _e35 = input_uniform.val_f32_; uint64_t _e36 = val_1; uint64_t _e40 = val_1; diff --git a/naga/tests/out/hlsl/math-functions.hlsl b/naga/tests/out/hlsl/math-functions.hlsl index b8ace15b3c..b31d804a7b 100644 --- a/naga/tests/out/hlsl/math-functions.hlsl +++ b/naga/tests/out/hlsl/math-functions.hlsl @@ -76,21 +76,21 @@ void main() float4 d = radians(v); float4 e = saturate(v); float4 g = refract(v, v, 1.0); - int4 sign_b = int4(-1, -1, -1, -1); + int4 sign_b = int4(int(-1), int(-1), int(-1), int(-1)); float4 sign_d = float4(-1.0, -1.0, -1.0, -1.0); int const_dot = dot(ZeroValueint2(), ZeroValueint2()); - int2 flb_b = int2(-1, -1); + int2 flb_b = int2(int(-1), int(-1)); uint2 flb_c = uint2(0u, 0u); - int2 ftb_c = int2(0, 0); + int2 ftb_c = int2(int(0), int(0)); uint2 ftb_d = uint2(0u, 0u); uint2 ctz_e = uint2(32u, 32u); - int2 ctz_f = int2(32, 32); + int2 ctz_f = int2(int(32), int(32)); uint2 ctz_g = uint2(0u, 0u); - int2 ctz_h = int2(0, 0); - int2 clz_c = int2(0, 0); + int2 ctz_h = int2(int(0), int(0)); + int2 clz_c = int2(int(0), int(0)); uint2 clz_d = uint2(31u, 31u); - float lde_a = ldexp(1.0, 2); - float2 lde_b = ldexp(float2(1.0, 2.0), int2(3, 4)); + float lde_a = ldexp(1.0, int(2)); + float2 lde_b = ldexp(float2(1.0, 2.0), int2(int(3), int(4))); _modf_result_f32_ modf_a = naga_modf(1.5); float modf_b = naga_modf(1.5).fract; float modf_c = naga_modf(1.5).whole; diff --git a/naga/tests/out/hlsl/operators.hlsl b/naga/tests/out/hlsl/operators.hlsl index a4a381f7e7..0e74dc54fa 100644 --- a/naga/tests/out/hlsl/operators.hlsl +++ b/naga/tests/out/hlsl/operators.hlsl @@ -1,25 +1,30 @@ static const float4 v_f32_one = float4(1.0, 1.0, 1.0, 1.0); static const float4 v_f32_zero = float4(0.0, 0.0, 0.0, 0.0); static const float4 v_f32_half = float4(0.5, 0.5, 0.5, 0.5); -static const int4 v_i32_one = int4(1, 1, 1, 1); +static const int4 v_i32_one = int4(int(1), int(1), int(1), int(1)); float4 builtins() { - int s1_ = (true ? 1 : 0); + int s1_ = (true ? int(1) : int(0)); float4 s2_ = (true ? v_f32_one : v_f32_zero); float4 s3_ = (bool4(false, false, false, false) ? v_f32_zero : v_f32_one); float4 m1_ = lerp(v_f32_zero, v_f32_one, v_f32_half); float4 m2_ = lerp(v_f32_zero, v_f32_one, 0.1); - float b1_ = asfloat(1); + float b1_ = asfloat(int(1)); float4 b2_ = asfloat(v_i32_one); - int4 v_i32_zero = int4(0, 0, 0, 0); - return (((((float4(((s1_).xxxx + v_i32_zero)) + s2_) + m1_) + m2_) + (b1_).xxxx) + b2_); + int4 v_i32_zero = int4(int(0), int(0), int(0), int(0)); + return (((((float4(asint(asuint((s1_).xxxx) + asuint(v_i32_zero))) + s2_) + m1_) + m2_) + (b1_).xxxx) + b2_); +} + +int4 naga_mod(int4 lhs, int4 rhs) { + int4 divisor = ((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs; + return lhs - (lhs / divisor) * divisor; } float4 splat(float m, int n) { float2 a_2 = ((((2.0).xx + (m).xx) - (4.0).xx) / (8.0).xx); - int4 b = ((n).xxxx % (2).xxxx); + int4 b = naga_mod((n).xxxx, (int(2)).xxxx); return (a_2.xyxy + float4(b)); } @@ -56,6 +61,52 @@ void logical() return; } +int2 naga_neg(int2 val) { + return asint(-asuint(val)); +} + +int naga_div(int lhs, int rhs) { + return lhs / (((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs); +} + +uint naga_div(uint lhs, uint rhs) { + return lhs / (rhs == 0u ? 1u : rhs); +} + +int2 naga_div(int2 lhs, int2 rhs) { + return lhs / (((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs); +} + +uint3 naga_div(uint3 lhs, uint3 rhs) { + return lhs / (rhs == 0u ? 1u : rhs); +} + +int naga_mod(int lhs, int rhs) { + int divisor = ((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs; + return lhs - (lhs / divisor) * divisor; +} + +uint naga_mod(uint lhs, uint rhs) { + return lhs % (rhs == 0u ? 1u : rhs); +} + +int2 naga_mod(int2 lhs, int2 rhs) { + int2 divisor = ((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs; + return lhs - (lhs / divisor) * divisor; +} + +uint3 naga_mod(uint3 lhs, uint3 rhs) { + return lhs % (rhs == 0u ? 1u : rhs); +} + +uint2 naga_div(uint2 lhs, uint2 rhs) { + return lhs / (rhs == 0u ? 1u : rhs); +} + +uint2 naga_mod(uint2 lhs, uint2 rhs) { + return lhs % (rhs == 0u ? 1u : rhs); +} + float3x3 ZeroValuefloat3x3() { return (float3x3)0; } @@ -71,67 +122,67 @@ float3x4 ZeroValuefloat3x4() { void arithmetic() { float neg0_1 = -(1.0); - int2 neg1_1 = -((1).xx); + int2 neg1_1 = naga_neg((int(1)).xx); float2 neg2_ = -((1.0).xx); - int add0_ = (2 + 1); + int add0_ = asint(asuint(int(2)) + asuint(int(1))); uint add1_ = (2u + 1u); float add2_ = (2.0 + 1.0); - int2 add3_ = ((2).xx + (1).xx); + int2 add3_ = asint(asuint((int(2)).xx) + asuint((int(1)).xx)); uint3 add4_ = ((2u).xxx + (1u).xxx); float4 add5_ = ((2.0).xxxx + (1.0).xxxx); - int sub0_ = (2 - 1); + int sub0_ = asint(asuint(int(2)) - asuint(int(1))); uint sub1_ = (2u - 1u); float sub2_ = (2.0 - 1.0); - int2 sub3_ = ((2).xx - (1).xx); + int2 sub3_ = asint(asuint((int(2)).xx) - asuint((int(1)).xx)); uint3 sub4_ = ((2u).xxx - (1u).xxx); float4 sub5_ = ((2.0).xxxx - (1.0).xxxx); - int mul0_ = (2 * 1); + int mul0_ = asint(asuint(int(2)) * asuint(int(1))); uint mul1_ = (2u * 1u); float mul2_ = (2.0 * 1.0); - int2 mul3_ = ((2).xx * (1).xx); + int2 mul3_ = asint(asuint((int(2)).xx) * asuint((int(1)).xx)); uint3 mul4_ = ((2u).xxx * (1u).xxx); float4 mul5_ = ((2.0).xxxx * (1.0).xxxx); - int div0_ = (2 / 1); - uint div1_ = (2u / 1u); + int div0_ = naga_div(int(2), int(1)); + uint div1_ = naga_div(2u, 1u); float div2_ = (2.0 / 1.0); - int2 div3_ = ((2).xx / (1).xx); - uint3 div4_ = ((2u).xxx / (1u).xxx); + int2 div3_ = naga_div((int(2)).xx, (int(1)).xx); + uint3 div4_ = naga_div((2u).xxx, (1u).xxx); float4 div5_ = ((2.0).xxxx / (1.0).xxxx); - int rem0_ = (2 % 1); - uint rem1_ = (2u % 1u); + int rem0_ = naga_mod(int(2), int(1)); + uint rem1_ = naga_mod(2u, 1u); float rem2_ = fmod(2.0, 1.0); - int2 rem3_ = ((2).xx % (1).xx); - uint3 rem4_ = ((2u).xxx % (1u).xxx); + int2 rem3_ = naga_mod((int(2)).xx, (int(1)).xx); + uint3 rem4_ = naga_mod((2u).xxx, (1u).xxx); float4 rem5_ = fmod((2.0).xxxx, (1.0).xxxx); { - int2 add0_1 = ((2).xx + (1).xx); - int2 add1_1 = ((2).xx + (1).xx); + int2 add0_1 = asint(asuint((int(2)).xx) + asuint((int(1)).xx)); + int2 add1_1 = asint(asuint((int(2)).xx) + asuint((int(1)).xx)); uint2 add2_1 = ((2u).xx + (1u).xx); uint2 add3_1 = ((2u).xx + (1u).xx); float2 add4_1 = ((2.0).xx + (1.0).xx); float2 add5_1 = ((2.0).xx + (1.0).xx); - int2 sub0_1 = ((2).xx - (1).xx); - int2 sub1_1 = ((2).xx - (1).xx); + int2 sub0_1 = asint(asuint((int(2)).xx) - asuint((int(1)).xx)); + int2 sub1_1 = asint(asuint((int(2)).xx) - asuint((int(1)).xx)); uint2 sub2_1 = ((2u).xx - (1u).xx); uint2 sub3_1 = ((2u).xx - (1u).xx); float2 sub4_1 = ((2.0).xx - (1.0).xx); float2 sub5_1 = ((2.0).xx - (1.0).xx); - int2 mul0_1 = ((2).xx * 1); - int2 mul1_1 = (2 * (1).xx); + int2 mul0_1 = asint(asuint((int(2)).xx) * asuint(int(1))); + int2 mul1_1 = asint(asuint(int(2)) * asuint((int(1)).xx)); uint2 mul2_1 = ((2u).xx * 1u); uint2 mul3_1 = (2u * (1u).xx); float2 mul4_1 = ((2.0).xx * 1.0); float2 mul5_1 = (2.0 * (1.0).xx); - int2 div0_1 = ((2).xx / (1).xx); - int2 div1_1 = ((2).xx / (1).xx); - uint2 div2_1 = ((2u).xx / (1u).xx); - uint2 div3_1 = ((2u).xx / (1u).xx); + int2 div0_1 = naga_div((int(2)).xx, (int(1)).xx); + int2 div1_1 = naga_div((int(2)).xx, (int(1)).xx); + uint2 div2_1 = naga_div((2u).xx, (1u).xx); + uint2 div3_1 = naga_div((2u).xx, (1u).xx); float2 div4_1 = ((2.0).xx / (1.0).xx); float2 div5_1 = ((2.0).xx / (1.0).xx); - int2 rem0_1 = ((2).xx % (1).xx); - int2 rem1_1 = ((2).xx % (1).xx); - uint2 rem2_1 = ((2u).xx % (1u).xx); - uint2 rem3_1 = ((2u).xx % (1u).xx); + int2 rem0_1 = naga_mod((int(2)).xx, (int(1)).xx); + int2 rem1_1 = naga_mod((int(2)).xx, (int(1)).xx); + uint2 rem2_1 = naga_mod((2u).xx, (1u).xx); + uint2 rem3_1 = naga_mod((2u).xx, (1u).xx); float2 rem4_1 = fmod((2.0).xx, (1.0).xx); float2 rem5_1 = fmod((2.0).xx, (1.0).xx); } @@ -147,69 +198,69 @@ void arithmetic() void bit() { - int flip0_ = ~(1); + int flip0_ = ~(int(1)); uint flip1_ = ~(1u); - int2 flip2_ = ~((1).xx); + int2 flip2_ = ~((int(1)).xx); uint3 flip3_ = ~((1u).xxx); - int or0_ = (2 | 1); + int or0_ = (int(2) | int(1)); uint or1_ = (2u | 1u); - int2 or2_ = ((2).xx | (1).xx); + int2 or2_ = ((int(2)).xx | (int(1)).xx); uint3 or3_ = ((2u).xxx | (1u).xxx); - int and0_ = (2 & 1); + int and0_ = (int(2) & int(1)); uint and1_ = (2u & 1u); - int2 and2_ = ((2).xx & (1).xx); + int2 and2_ = ((int(2)).xx & (int(1)).xx); uint3 and3_ = ((2u).xxx & (1u).xxx); - int xor0_ = (2 ^ 1); + int xor0_ = (int(2) ^ int(1)); uint xor1_ = (2u ^ 1u); - int2 xor2_ = ((2).xx ^ (1).xx); + int2 xor2_ = ((int(2)).xx ^ (int(1)).xx); uint3 xor3_ = ((2u).xxx ^ (1u).xxx); - int shl0_ = (2 << 1u); + int shl0_ = (int(2) << 1u); uint shl1_ = (2u << 1u); - int2 shl2_ = ((2).xx << (1u).xx); + int2 shl2_ = ((int(2)).xx << (1u).xx); uint3 shl3_ = ((2u).xxx << (1u).xxx); - int shr0_ = (2 >> 1u); + int shr0_ = (int(2) >> 1u); uint shr1_ = (2u >> 1u); - int2 shr2_ = ((2).xx >> (1u).xx); + int2 shr2_ = ((int(2)).xx >> (1u).xx); uint3 shr3_ = ((2u).xxx >> (1u).xxx); return; } void comparison() { - bool eq0_ = (2 == 1); + bool eq0_ = (int(2) == int(1)); bool eq1_ = (2u == 1u); bool eq2_ = (2.0 == 1.0); - bool2 eq3_ = ((2).xx == (1).xx); + bool2 eq3_ = ((int(2)).xx == (int(1)).xx); bool3 eq4_ = ((2u).xxx == (1u).xxx); bool4 eq5_ = ((2.0).xxxx == (1.0).xxxx); - bool neq0_ = (2 != 1); + bool neq0_ = (int(2) != int(1)); bool neq1_ = (2u != 1u); bool neq2_ = (2.0 != 1.0); - bool2 neq3_ = ((2).xx != (1).xx); + bool2 neq3_ = ((int(2)).xx != (int(1)).xx); bool3 neq4_ = ((2u).xxx != (1u).xxx); bool4 neq5_ = ((2.0).xxxx != (1.0).xxxx); - bool lt0_ = (2 < 1); + bool lt0_ = (int(2) < int(1)); bool lt1_ = (2u < 1u); bool lt2_ = (2.0 < 1.0); - bool2 lt3_ = ((2).xx < (1).xx); + bool2 lt3_ = ((int(2)).xx < (int(1)).xx); bool3 lt4_ = ((2u).xxx < (1u).xxx); bool4 lt5_ = ((2.0).xxxx < (1.0).xxxx); - bool lte0_ = (2 <= 1); + bool lte0_ = (int(2) <= int(1)); bool lte1_ = (2u <= 1u); bool lte2_ = (2.0 <= 1.0); - bool2 lte3_ = ((2).xx <= (1).xx); + bool2 lte3_ = ((int(2)).xx <= (int(1)).xx); bool3 lte4_ = ((2u).xxx <= (1u).xxx); bool4 lte5_ = ((2.0).xxxx <= (1.0).xxxx); - bool gt0_ = (2 > 1); + bool gt0_ = (int(2) > int(1)); bool gt1_ = (2u > 1u); bool gt2_ = (2.0 > 1.0); - bool2 gt3_ = ((2).xx > (1).xx); + bool2 gt3_ = ((int(2)).xx > (int(1)).xx); bool3 gt4_ = ((2u).xxx > (1u).xxx); bool4 gt5_ = ((2.0).xxxx > (1.0).xxxx); - bool gte0_ = (2 >= 1); + bool gte0_ = (int(2) >= int(1)); bool gte1_ = (2u >= 1u); bool gte2_ = (2.0 >= 1.0); - bool2 gte3_ = ((2).xx >= (1).xx); + bool2 gte3_ = ((int(2)).xx >= (int(1)).xx); bool3 gte4_ = ((2u).xxx >= (1u).xxx); bool4 gte5_ = ((2.0).xxxx >= (1.0).xxxx); return; @@ -224,50 +275,62 @@ void assignment() int a_1 = (int)0; int3 vec0_ = ZeroValueint3(); - a_1 = 1; + a_1 = int(1); int _e5 = a_1; - a_1 = (_e5 + 1); + a_1 = asint(asuint(_e5) + asuint(int(1))); int _e7 = a_1; - a_1 = (_e7 - 1); + a_1 = asint(asuint(_e7) - asuint(int(1))); int _e9 = a_1; int _e10 = a_1; - a_1 = (_e10 * _e9); + a_1 = asint(asuint(_e10) * asuint(_e9)); int _e12 = a_1; int _e13 = a_1; - a_1 = (_e13 / _e12); + a_1 = naga_div(_e13, _e12); int _e15 = a_1; - a_1 = (_e15 % 1); + a_1 = naga_mod(_e15, int(1)); int _e17 = a_1; - a_1 = (_e17 & 0); + a_1 = (_e17 & int(0)); int _e19 = a_1; - a_1 = (_e19 | 0); + a_1 = (_e19 | int(0)); int _e21 = a_1; - a_1 = (_e21 ^ 0); + a_1 = (_e21 ^ int(0)); int _e23 = a_1; a_1 = (_e23 << 2u); int _e25 = a_1; a_1 = (_e25 >> 1u); int _e28 = a_1; - a_1 = (_e28 + 1); + a_1 = asint(asuint(_e28) + asuint(int(1))); int _e31 = a_1; - a_1 = (_e31 - 1); - int _e37 = vec0_[1]; - vec0_[1] = (_e37 + 1); - int _e41 = vec0_[1]; - vec0_[1] = (_e41 - 1); + a_1 = asint(asuint(_e31) - asuint(int(1))); + int _e37 = vec0_[int(1)]; + vec0_[int(1)] = asint(asuint(_e37) + asuint(int(1))); + int _e41 = vec0_[int(1)]; + vec0_[int(1)] = asint(asuint(_e41) - asuint(int(1))); return; } +int naga_neg(int val) { + return asint(-asuint(val)); +} + void negation_avoids_prefix_decrement() { - int p0_ = -(1); - int p1_ = -(-(1)); - int p2_ = -(-(1)); - int p3_ = -(-(1)); - int p4_ = -(-(-(1))); - int p5_ = -(-(-(-(1)))); - int p6_ = -(-(-(-(-(1))))); - int p7_ = -(-(-(-(-(1))))); + int i0_ = naga_neg(int(1)); + int i1_ = naga_neg(naga_neg(int(1))); + int i2_ = naga_neg(naga_neg(int(1))); + int i3_ = naga_neg(naga_neg(int(1))); + int i4_ = naga_neg(naga_neg(naga_neg(int(1)))); + int i5_ = naga_neg(naga_neg(naga_neg(naga_neg(int(1))))); + int i6_ = naga_neg(naga_neg(naga_neg(naga_neg(naga_neg(int(1)))))); + int i7_ = naga_neg(naga_neg(naga_neg(naga_neg(naga_neg(int(1)))))); + float f0_ = -(1.0); + float f1_ = -(-(1.0)); + float f2_ = -(-(1.0)); + float f3_ = -(-(1.0)); + float f4_ = -(-(-(1.0))); + float f5_ = -(-(-(-(1.0)))); + float f6_ = -(-(-(-(-(1.0))))); + float f7_ = -(-(-(-(-(1.0))))); return; } diff --git a/naga/tests/out/hlsl/phony_assignment.hlsl b/naga/tests/out/hlsl/phony_assignment.hlsl index dbe587e5c8..02348c87df 100644 --- a/naga/tests/out/hlsl/phony_assignment.hlsl +++ b/naga/tests/out/hlsl/phony_assignment.hlsl @@ -2,7 +2,7 @@ cbuffer binding : register(b0) { float binding; } int five() { - return 5; + return int(5); } [numthreads(1, 1, 1)] diff --git a/naga/tests/out/hlsl/skybox.hlsl b/naga/tests/out/hlsl/skybox.hlsl index f1d77c3c50..9c890953b2 100644 --- a/naga/tests/out/hlsl/skybox.hlsl +++ b/naga/tests/out/hlsl/skybox.hlsl @@ -32,6 +32,10 @@ struct FragmentInput_fs_main { float4 position_1 : SV_Position; }; +int naga_div(int lhs, int rhs) { + return lhs / (((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs); +} + VertexOutput ConstructVertexOutput(float4 arg0, float3 arg1) { VertexOutput ret = (VertexOutput)0; ret.position = arg0; @@ -44,8 +48,8 @@ VertexOutput_vs_main vs_main(uint vertex_index : SV_VertexID) int tmp1_ = (int)0; int tmp2_ = (int)0; - tmp1_ = (int((_NagaConstants.first_vertex + vertex_index)) / 2); - tmp2_ = (int((_NagaConstants.first_vertex + vertex_index)) & 1); + tmp1_ = naga_div(int((_NagaConstants.first_vertex + vertex_index)), int(2)); + tmp2_ = (int((_NagaConstants.first_vertex + vertex_index)) & int(1)); int _e9 = tmp1_; int _e15 = tmp2_; float4 pos = float4(((float(_e9) * 4.0) - 1.0), ((float(_e15) * 4.0) - 1.0), 0.0, 1.0); diff --git a/naga/tests/out/hlsl/unnamed-gl-per-vertex.hlsl b/naga/tests/out/hlsl/unnamed-gl-per-vertex.hlsl index 6564f71f72..9b2ac0864e 100644 --- a/naga/tests/out/hlsl/unnamed-gl-per-vertex.hlsl +++ b/naga/tests/out/hlsl/unnamed-gl-per-vertex.hlsl @@ -26,7 +26,7 @@ static int global_1 = (int)0; void function() { int _e9 = global_1; - global.member = float4(((_e9 == 0) ? -4.0 : 1.0), ((_e9 == 2) ? 4.0 : -1.0), 0.0, 1.0); + global.member = float4(((_e9 == int(0)) ? -4.0 : 1.0), ((_e9 == int(2)) ? 4.0 : -1.0), 0.0, 1.0); return; } diff --git a/naga/tests/out/hlsl/workgroup-uniform-load.hlsl b/naga/tests/out/hlsl/workgroup-uniform-load.hlsl index a8dba16b9a..0bfb55cb6c 100644 --- a/naga/tests/out/hlsl/workgroup-uniform-load.hlsl +++ b/naga/tests/out/hlsl/workgroup-uniform-load.hlsl @@ -12,7 +12,7 @@ void test_workgroupUniformLoad(uint3 workgroup_id : SV_GroupID, uint3 __local_in GroupMemoryBarrierWithGroupSync(); int _e4 = arr_i32_[min(uint(workgroup_id.x), 127u)]; GroupMemoryBarrierWithGroupSync(); - if ((_e4 > 10)) { + if ((_e4 > int(10))) { GroupMemoryBarrierWithGroupSync(); return; } else { diff --git a/naga/tests/out/msl/collatz.msl b/naga/tests/out/msl/collatz.msl index eef2c83c34..e190d16da6 100644 --- a/naga/tests/out/msl/collatz.msl +++ b/naga/tests/out/msl/collatz.msl @@ -13,6 +13,14 @@ struct PrimeIndices { type_1 data; }; +uint naga_mod(uint lhs, uint rhs) { + return lhs % metal::select(rhs, 1u, rhs == 0u); +} + +uint naga_div(uint lhs, uint rhs) { + return lhs / metal::select(rhs, 1u, rhs == 0u); +} + uint collatz_iterations( uint n_base ) { @@ -30,9 +38,9 @@ uint collatz_iterations( } { uint _e7 = n; - if ((_e7 % 2u) == 0u) { + if (naga_mod(_e7, 2u) == 0u) { uint _e12 = n; - n = _e12 / 2u; + n = naga_div(_e12, 2u); } else { uint _e16 = n; n = (3u * _e16) + 1u; diff --git a/naga/tests/out/msl/image.msl b/naga/tests/out/msl/image.msl index 1a8567a0ca..b2b3bda4e5 100644 --- a/naga/tests/out/msl/image.msl +++ b/naga/tests/out/msl/image.msl @@ -4,6 +4,11 @@ using metal::uint; +metal::int2 naga_mod(metal::int2 lhs, metal::int2 rhs) { + metal::int2 divisor = metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0)); + return lhs - (lhs / divisor) * divisor; +} + struct main_Input { }; @@ -17,7 +22,7 @@ kernel void main_( , metal::texture1d image_dst [[user(fake0)]] ) { metal::uint2 dim = metal::uint2(image_storage_src.get_width(), image_storage_src.get_height()); - metal::int2 itc = static_cast(dim * local_id.xy) % metal::int2(10, 20); + metal::int2 itc = naga_mod(static_cast(dim * local_id.xy), metal::int2(10, 20)); metal::uint4 value1_ = image_mipmapped_src.read(metal::uint2(itc), static_cast(local_id.z)); metal::uint4 value2_ = image_multisampled_src.read(metal::uint2(itc), static_cast(local_id.z)); metal::uint4 value4_ = image_storage_src.read(metal::uint2(itc)); @@ -45,7 +50,7 @@ kernel void depth_load( , metal::texture1d image_dst [[user(fake0)]] ) { metal::uint2 dim_1 = metal::uint2(image_storage_src.get_width(), image_storage_src.get_height()); - metal::int2 itc_1 = static_cast(dim_1 * local_id_1.xy) % metal::int2(10, 20); + metal::int2 itc_1 = naga_mod(static_cast(dim_1 * local_id_1.xy), metal::int2(10, 20)); float val = image_depth_multisampled_src.read(metal::uint2(itc_1), static_cast(local_id_1.z)); image_dst.write(metal::uint4(static_cast(val)), uint(itc_1.x)); return; diff --git a/naga/tests/out/msl/int64.msl b/naga/tests/out/msl/int64.msl index 369eb01c6f..d563b41d7b 100644 --- a/naga/tests/out/msl/int64.msl +++ b/naga/tests/out/msl/int64.msl @@ -34,6 +34,10 @@ struct StorageCompatible { }; constant ulong constant_variable = 20uL; +long naga_abs(long val) { + return metal::select(as_type(-as_type(val)), val, val >= 0); +} + long int64_function( long x, constant UniformCompatible& input_uniform, @@ -91,7 +95,7 @@ long int64_function( output_arrays.val_i64_array_2_ = _e116; long _e117 = val; long _e119 = val; - val = as_type(as_type(_e119) + as_type(metal::abs(_e117))); + val = as_type(as_type(_e119) + as_type(naga_abs(_e117))); long _e121 = val; long _e122 = val; long _e123 = val; diff --git a/naga/tests/out/msl/operators.msl b/naga/tests/out/msl/operators.msl index 9b9b916cb2..1d2d81834a 100644 --- a/naga/tests/out/msl/operators.msl +++ b/naga/tests/out/msl/operators.msl @@ -22,12 +22,17 @@ metal::float4 builtins( return ((((static_cast(as_type(as_type(metal::int4(s1_)) + as_type(v_i32_zero))) + s2_) + m1_) + m2_) + metal::float4(b1_)) + b2_; } +metal::int4 naga_mod(metal::int4 lhs, metal::int4 rhs) { + metal::int4 divisor = metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0)); + return lhs - (lhs / divisor) * divisor; +} + metal::float4 splat( float m, int n ) { metal::float2 a_2 = ((metal::float2(2.0) + metal::float2(m)) - metal::float2(4.0)) / metal::float2(8.0); - metal::int4 b = metal::int4(n) % metal::int4(2); + metal::int4 b = naga_mod(metal::int4(n), metal::int4(2)); return a_2.xyxy + static_cast(b); } @@ -64,10 +69,56 @@ void logical( return; } +metal::int2 naga_neg(metal::int2 val) { + return as_type(-as_type(val)); +} + +int naga_div(int lhs, int rhs) { + return lhs / metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0)); +} + +uint naga_div(uint lhs, uint rhs) { + return lhs / metal::select(rhs, 1u, rhs == 0u); +} + +metal::int2 naga_div(metal::int2 lhs, metal::int2 rhs) { + return lhs / metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0)); +} + +metal::uint3 naga_div(metal::uint3 lhs, metal::uint3 rhs) { + return lhs / metal::select(rhs, 1u, rhs == 0u); +} + +int naga_mod(int lhs, int rhs) { + int divisor = metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0)); + return lhs - (lhs / divisor) * divisor; +} + +uint naga_mod(uint lhs, uint rhs) { + return lhs % metal::select(rhs, 1u, rhs == 0u); +} + +metal::int2 naga_mod(metal::int2 lhs, metal::int2 rhs) { + metal::int2 divisor = metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0)); + return lhs - (lhs / divisor) * divisor; +} + +metal::uint3 naga_mod(metal::uint3 lhs, metal::uint3 rhs) { + return lhs % metal::select(rhs, 1u, rhs == 0u); +} + +metal::uint2 naga_div(metal::uint2 lhs, metal::uint2 rhs) { + return lhs / metal::select(rhs, 1u, rhs == 0u); +} + +metal::uint2 naga_mod(metal::uint2 lhs, metal::uint2 rhs) { + return lhs % metal::select(rhs, 1u, rhs == 0u); +} + void arithmetic( ) { float neg0_1 = -(1.0); - metal::int2 neg1_1 = -(metal::int2(1)); + metal::int2 neg1_1 = naga_neg(metal::int2(1)); metal::float2 neg2_ = -(metal::float2(1.0)); int add0_ = as_type(as_type(2) + as_type(1)); uint add1_ = 2u + 1u; @@ -87,17 +138,17 @@ void arithmetic( metal::int2 mul3_ = as_type(as_type(metal::int2(2)) * as_type(metal::int2(1))); metal::uint3 mul4_ = metal::uint3(2u) * metal::uint3(1u); metal::float4 mul5_ = metal::float4(2.0) * metal::float4(1.0); - int div0_ = 2 / 1; - uint div1_ = 2u / 1u; + int div0_ = naga_div(2, 1); + uint div1_ = naga_div(2u, 1u); float div2_ = 2.0 / 1.0; - metal::int2 div3_ = metal::int2(2) / metal::int2(1); - metal::uint3 div4_ = metal::uint3(2u) / metal::uint3(1u); + metal::int2 div3_ = naga_div(metal::int2(2), metal::int2(1)); + metal::uint3 div4_ = naga_div(metal::uint3(2u), metal::uint3(1u)); metal::float4 div5_ = metal::float4(2.0) / metal::float4(1.0); - int rem0_ = 2 % 1; - uint rem1_ = 2u % 1u; + int rem0_ = naga_mod(2, 1); + uint rem1_ = naga_mod(2u, 1u); float rem2_ = metal::fmod(2.0, 1.0); - metal::int2 rem3_ = metal::int2(2) % metal::int2(1); - metal::uint3 rem4_ = metal::uint3(2u) % metal::uint3(1u); + metal::int2 rem3_ = naga_mod(metal::int2(2), metal::int2(1)); + metal::uint3 rem4_ = naga_mod(metal::uint3(2u), metal::uint3(1u)); metal::float4 rem5_ = metal::fmod(metal::float4(2.0), metal::float4(1.0)); { metal::int2 add0_1 = as_type(as_type(metal::int2(2)) + as_type(metal::int2(1))); @@ -118,16 +169,16 @@ void arithmetic( metal::uint2 mul3_1 = 2u * metal::uint2(1u); metal::float2 mul4_1 = metal::float2(2.0) * 1.0; metal::float2 mul5_1 = 2.0 * metal::float2(1.0); - metal::int2 div0_1 = metal::int2(2) / metal::int2(1); - metal::int2 div1_1 = metal::int2(2) / metal::int2(1); - metal::uint2 div2_1 = metal::uint2(2u) / metal::uint2(1u); - metal::uint2 div3_1 = metal::uint2(2u) / metal::uint2(1u); + metal::int2 div0_1 = naga_div(metal::int2(2), metal::int2(1)); + metal::int2 div1_1 = naga_div(metal::int2(2), metal::int2(1)); + metal::uint2 div2_1 = naga_div(metal::uint2(2u), metal::uint2(1u)); + metal::uint2 div3_1 = naga_div(metal::uint2(2u), metal::uint2(1u)); metal::float2 div4_1 = metal::float2(2.0) / metal::float2(1.0); metal::float2 div5_1 = metal::float2(2.0) / metal::float2(1.0); - metal::int2 rem0_1 = metal::int2(2) % metal::int2(1); - metal::int2 rem1_1 = metal::int2(2) % metal::int2(1); - metal::uint2 rem2_1 = metal::uint2(2u) % metal::uint2(1u); - metal::uint2 rem3_1 = metal::uint2(2u) % metal::uint2(1u); + metal::int2 rem0_1 = naga_mod(metal::int2(2), metal::int2(1)); + metal::int2 rem1_1 = naga_mod(metal::int2(2), metal::int2(1)); + metal::uint2 rem2_1 = naga_mod(metal::uint2(2u), metal::uint2(1u)); + metal::uint2 rem3_1 = naga_mod(metal::uint2(2u), metal::uint2(1u)); metal::float2 rem4_1 = metal::fmod(metal::float2(2.0), metal::float2(1.0)); metal::float2 rem5_1 = metal::fmod(metal::float2(2.0), metal::float2(1.0)); } @@ -225,9 +276,9 @@ void assignment( a_1 = as_type(as_type(_e10) * as_type(_e9)); int _e12 = a_1; int _e13 = a_1; - a_1 = _e13 / _e12; + a_1 = naga_div(_e13, _e12); int _e15 = a_1; - a_1 = _e15 % 1; + a_1 = naga_mod(_e15, 1); int _e17 = a_1; a_1 = _e17 & 0; int _e19 = a_1; @@ -249,16 +300,28 @@ void assignment( return; } +int naga_neg(int val) { + return as_type(-as_type(val)); +} + void negation_avoids_prefix_decrement( ) { - int p0_ = -(1); - int p1_ = -(-(1)); - int p2_ = -(-(1)); - int p3_ = -(-(1)); - int p4_ = -(-(-(1))); - int p5_ = -(-(-(-(1)))); - int p6_ = -(-(-(-(-(1))))); - int p7_ = -(-(-(-(-(1))))); + int i0_ = naga_neg(1); + int i1_ = naga_neg(naga_neg(1)); + int i2_ = naga_neg(naga_neg(1)); + int i3_ = naga_neg(naga_neg(1)); + int i4_ = naga_neg(naga_neg(naga_neg(1))); + int i5_ = naga_neg(naga_neg(naga_neg(naga_neg(1)))); + int i6_ = naga_neg(naga_neg(naga_neg(naga_neg(naga_neg(1))))); + int i7_ = naga_neg(naga_neg(naga_neg(naga_neg(naga_neg(1))))); + float f0_ = -(1.0); + float f1_ = -(-(1.0)); + float f2_ = -(-(1.0)); + float f3_ = -(-(1.0)); + float f4_ = -(-(-(1.0))); + float f5_ = -(-(-(-(1.0)))); + float f6_ = -(-(-(-(-(1.0))))); + float f7_ = -(-(-(-(-(1.0))))); return; } diff --git a/naga/tests/out/msl/skybox.msl b/naga/tests/out/msl/skybox.msl index 7b10ea23e7..b5f51c946b 100644 --- a/naga/tests/out/msl/skybox.msl +++ b/naga/tests/out/msl/skybox.msl @@ -12,6 +12,10 @@ struct Data { metal::float4x4 proj_inv; metal::float4x4 view; }; +int naga_div(int lhs, int rhs) { + return lhs / metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0)); +} + struct vs_mainInput { }; @@ -25,7 +29,7 @@ vertex vs_mainOutput vs_main( ) { int tmp1_ = {}; int tmp2_ = {}; - tmp1_ = static_cast(vertex_index) / 2; + tmp1_ = naga_div(static_cast(vertex_index), 2); tmp2_ = static_cast(vertex_index) & 1; int _e9 = tmp1_; int _e15 = tmp2_; diff --git a/naga/tests/out/spv/collatz.spvasm b/naga/tests/out/spv/collatz.spvasm index 5c77a52269..6c6cfb4f91 100644 --- a/naga/tests/out/spv/collatz.spvasm +++ b/naga/tests/out/spv/collatz.spvasm @@ -1,28 +1,34 @@ ; SPIR-V ; Version: 1.0 ; Generator: rspirv -; Bound: 62 +; Bound: 77 OpCapability Shader OpExtension "SPV_KHR_storage_buffer_storage_class" %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %51 "main" %48 -OpExecutionMode %51 LocalSize 1 1 1 +OpEntryPoint GLCompute %66 "main" %63 +OpExecutionMode %66 LocalSize 1 1 1 OpMemberName %5 0 "data" OpName %5 "PrimeIndices" OpName %7 "v_indices" -OpName %10 "n_base" -OpName %11 "collatz_iterations" -OpName %17 "n" -OpName %20 "i" -OpName %48 "global_id" -OpName %51 "main" +OpName %9 "naga_mod" +OpName %11 "lhs" +OpName %12 "rhs" +OpName %20 "naga_div" +OpName %21 "lhs" +OpName %22 "rhs" +OpName %28 "n_base" +OpName %29 "collatz_iterations" +OpName %33 "n" +OpName %36 "i" +OpName %63 "global_id" +OpName %66 "main" OpDecorate %4 ArrayStride 4 OpMemberDecorate %5 0 Offset 0 OpDecorate %5 Block OpDecorate %7 DescriptorSet 0 OpDecorate %7 Binding 0 -OpDecorate %48 BuiltIn GlobalInvocationId +OpDecorate %63 BuiltIn GlobalInvocationId %2 = OpTypeVoid %3 = OpTypeInt 32 0 %4 = OpTypeRuntimeArray %3 @@ -30,81 +36,100 @@ OpDecorate %48 BuiltIn GlobalInvocationId %6 = OpTypeVector %3 3 %8 = OpTypePointer StorageBuffer %5 %7 = OpVariable %8 StorageBuffer -%12 = OpTypeFunction %3 %3 -%13 = OpConstant %3 0 -%14 = OpConstant %3 1 -%15 = OpConstant %3 2 -%16 = OpConstant %3 3 -%18 = OpTypePointer Function %3 -%19 = OpConstantNull %3 -%27 = OpTypeBool -%49 = OpTypePointer Input %6 -%48 = OpVariable %49 Input -%52 = OpTypeFunction %2 -%54 = OpTypePointer StorageBuffer %4 -%56 = OpTypePointer StorageBuffer %3 -%11 = OpFunction %3 None %12 -%10 = OpFunctionParameter %3 -%9 = OpLabel -%17 = OpVariable %18 Function %19 -%20 = OpVariable %18 Function %13 -OpBranch %21 -%21 = OpLabel -OpStore %17 %10 -OpBranch %22 -%22 = OpLabel -OpLoopMerge %23 %25 None -OpBranch %24 -%24 = OpLabel -%26 = OpLoad %3 %17 -%28 = OpUGreaterThan %27 %26 %14 -OpSelectionMerge %29 None -OpBranchConditional %28 %29 %30 -%30 = OpLabel -OpBranch %23 -%29 = OpLabel -OpBranch %31 -%31 = OpLabel -%33 = OpLoad %3 %17 -%34 = OpUMod %3 %33 %15 -%35 = OpIEqual %27 %34 %13 -OpSelectionMerge %36 None -OpBranchConditional %35 %37 %38 -%37 = OpLabel -%39 = OpLoad %3 %17 -%40 = OpUDiv %3 %39 %15 -OpStore %17 %40 -OpBranch %36 -%38 = OpLabel -%41 = OpLoad %3 %17 -%42 = OpIMul %3 %16 %41 -%43 = OpIAdd %3 %42 %14 -OpStore %17 %43 -OpBranch %36 -%36 = OpLabel -%44 = OpLoad %3 %20 -%45 = OpIAdd %3 %44 %14 -OpStore %20 %45 -OpBranch %32 -%32 = OpLabel -OpBranch %25 -%25 = OpLabel -OpBranch %22 +%10 = OpTypeFunction %3 %3 %3 +%14 = OpTypeBool +%15 = OpConstant %3 0 +%17 = OpConstant %3 1 +%30 = OpTypeFunction %3 %3 +%31 = OpConstant %3 2 +%32 = OpConstant %3 3 +%34 = OpTypePointer Function %3 +%35 = OpConstantNull %3 +%64 = OpTypePointer Input %6 +%63 = OpVariable %64 Input +%67 = OpTypeFunction %2 +%69 = OpTypePointer StorageBuffer %4 +%71 = OpTypePointer StorageBuffer %3 +%9 = OpFunction %3 None %10 +%11 = OpFunctionParameter %3 +%12 = OpFunctionParameter %3 +%13 = OpLabel +%16 = OpIEqual %14 %12 %15 +%18 = OpSelect %3 %16 %17 %12 +%19 = OpUMod %3 %11 %18 +OpReturnValue %19 +OpFunctionEnd +%20 = OpFunction %3 None %10 +%21 = OpFunctionParameter %3 +%22 = OpFunctionParameter %3 %23 = OpLabel -%46 = OpLoad %3 %20 -OpReturnValue %46 +%24 = OpIEqual %14 %22 %15 +%25 = OpSelect %3 %24 %17 %22 +%26 = OpUDiv %3 %21 %25 +OpReturnValue %26 OpFunctionEnd -%51 = OpFunction %2 None %52 -%47 = OpLabel -%50 = OpLoad %6 %48 -OpBranch %53 +%29 = OpFunction %3 None %30 +%28 = OpFunctionParameter %3 +%27 = OpLabel +%33 = OpVariable %34 Function %35 +%36 = OpVariable %34 Function %15 +OpBranch %37 +%37 = OpLabel +OpStore %33 %28 +OpBranch %38 +%38 = OpLabel +OpLoopMerge %39 %41 None +OpBranch %40 +%40 = OpLabel +%42 = OpLoad %3 %33 +%43 = OpUGreaterThan %14 %42 %17 +OpSelectionMerge %44 None +OpBranchConditional %43 %44 %45 +%45 = OpLabel +OpBranch %39 +%44 = OpLabel +OpBranch %46 +%46 = OpLabel +%48 = OpLoad %3 %33 +%49 = OpFunctionCall %3 %9 %48 %31 +%50 = OpIEqual %14 %49 %15 +OpSelectionMerge %51 None +OpBranchConditional %50 %52 %53 +%52 = OpLabel +%54 = OpLoad %3 %33 +%55 = OpFunctionCall %3 %20 %54 %31 +OpStore %33 %55 +OpBranch %51 %53 = OpLabel -%55 = OpCompositeExtract %3 %50 0 -%57 = OpCompositeExtract %3 %50 0 -%58 = OpAccessChain %56 %7 %13 %57 -%59 = OpLoad %3 %58 -%60 = OpFunctionCall %3 %11 %59 -%61 = OpAccessChain %56 %7 %13 %55 -OpStore %61 %60 +%56 = OpLoad %3 %33 +%57 = OpIMul %3 %32 %56 +%58 = OpIAdd %3 %57 %17 +OpStore %33 %58 +OpBranch %51 +%51 = OpLabel +%59 = OpLoad %3 %36 +%60 = OpIAdd %3 %59 %17 +OpStore %36 %60 +OpBranch %47 +%47 = OpLabel +OpBranch %41 +%41 = OpLabel +OpBranch %38 +%39 = OpLabel +%61 = OpLoad %3 %36 +OpReturnValue %61 +OpFunctionEnd +%66 = OpFunction %2 None %67 +%62 = OpLabel +%65 = OpLoad %6 %63 +OpBranch %68 +%68 = OpLabel +%70 = OpCompositeExtract %3 %65 0 +%72 = OpCompositeExtract %3 %65 0 +%73 = OpAccessChain %71 %7 %15 %72 +%74 = OpLoad %3 %73 +%75 = OpFunctionCall %3 %29 %74 +%76 = OpAccessChain %71 %7 %15 %70 +OpStore %76 %75 OpReturn OpFunctionEnd \ No newline at end of file diff --git a/naga/tests/out/spv/debug-symbol-large-source.spvasm b/naga/tests/out/spv/debug-symbol-large-source.spvasm index 15e95cf2a5..c761e6cdac 100644 --- a/naga/tests/out/spv/debug-symbol-large-source.spvasm +++ b/naga/tests/out/spv/debug-symbol-large-source.spvasm @@ -1,19 +1,19 @@ ; SPIR-V ; Version: 1.1 ; Generator: rspirv -; Bound: 644 +; Bound: 659 OpCapability Shader OpExtension "SPV_KHR_storage_buffer_storage_class" %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %345 "gen_terrain_compute" %342 -OpEntryPoint Vertex %415 "gen_terrain_vertex" %406 %409 %411 %413 -OpEntryPoint Fragment %465 "gen_terrain_fragment" %455 %457 %460 %463 %464 -OpEntryPoint Vertex %558 "vs_main" %549 %552 %554 %555 %557 -OpEntryPoint Fragment %583 "fs_main" %576 %578 %580 %582 -OpExecutionMode %345 LocalSize 64 1 1 -OpExecutionMode %465 OriginUpperLeft -OpExecutionMode %583 OriginUpperLeft +OpEntryPoint GLCompute %353 "gen_terrain_compute" %350 +OpEntryPoint Vertex %430 "gen_terrain_vertex" %421 %424 %426 %428 +OpEntryPoint Fragment %480 "gen_terrain_fragment" %470 %472 %475 %478 %479 +OpEntryPoint Vertex %573 "vs_main" %564 %567 %569 %570 %572 +OpEntryPoint Fragment %598 "fs_main" %591 %593 %595 %597 +OpExecutionMode %353 LocalSize 64 1 1 +OpExecutionMode %480 OriginUpperLeft +OpExecutionMode %598 OriginUpperLeft %3 = OpString "debug-symbol-large-source.wgsl" OpSource Unknown 0 %3 "//This is a test 这是测试 これはテストだ 테스트입니다 This is a test 这是测试 これはテストだ 테스트입니다 This is a test 这是测试 これはテストだ 테스트입니다 //This is a test 这是测试 これはテストだ 테스트입니다 This is a test 这是测试 これはテストだ 테스트입니다 This is a test 这是测试 これはテストだ 테스트입니다 @@ -7541,38 +7541,44 @@ OpName %257 "terrain_point" OpName %268 "p" OpName %269 "min_max_height" OpName %270 "terrain_vertex" -OpName %300 "vert_index" -OpName %301 "chunk_size" -OpName %302 "chunk_corner" -OpName %303 "index_to_p" -OpName %319 "p" -OpName %320 "color23" -OpName %342 "gid" -OpName %345 "gen_terrain_compute" -OpName %406 "vindex" -OpName %409 "index" -OpName %411 "position" -OpName %413 "uv" -OpName %415 "gen_terrain_vertex" -OpName %455 "index" -OpName %457 "position" -OpName %460 "uv" -OpName %463 "vert_component" -OpName %464 "index" -OpName %465 "gen_terrain_fragment" -OpName %468 "vert_component" -OpName %469 "index" -OpName %549 "position" -OpName %552 "normal" -OpName %554 "clip_position" -OpName %555 "normal" -OpName %557 "world_pos" -OpName %558 "vs_main" -OpName %576 "clip_position" -OpName %578 "normal" -OpName %580 "world_pos" -OpName %583 "fs_main" -OpName %592 "color" +OpName %299 "naga_div" +OpName %301 "lhs" +OpName %302 "rhs" +OpName %308 "vert_index" +OpName %309 "chunk_size" +OpName %310 "chunk_corner" +OpName %311 "index_to_p" +OpName %327 "p" +OpName %328 "color23" +OpName %350 "gid" +OpName %353 "gen_terrain_compute" +OpName %413 "naga_mod" +OpName %414 "lhs" +OpName %415 "rhs" +OpName %421 "vindex" +OpName %424 "index" +OpName %426 "position" +OpName %428 "uv" +OpName %430 "gen_terrain_vertex" +OpName %470 "index" +OpName %472 "position" +OpName %475 "uv" +OpName %478 "vert_component" +OpName %479 "index" +OpName %480 "gen_terrain_fragment" +OpName %483 "vert_component" +OpName %484 "index" +OpName %564 "position" +OpName %567 "normal" +OpName %569 "clip_position" +OpName %570 "normal" +OpName %572 "world_pos" +OpName %573 "vs_main" +OpName %591 "clip_position" +OpName %593 "normal" +OpName %595 "world_pos" +OpName %598 "fs_main" +OpName %607 "color" OpMemberDecorate %13 0 Offset 0 OpMemberDecorate %13 1 Offset 8 OpMemberDecorate %13 2 Offset 16 @@ -7631,27 +7637,27 @@ OpDecorate %49 DescriptorSet 2 OpDecorate %49 Binding 2 OpDecorate %50 DescriptorSet 2 OpDecorate %50 Binding 3 -OpDecorate %342 BuiltIn GlobalInvocationId -OpDecorate %406 BuiltIn VertexIndex -OpDecorate %409 Location 0 -OpDecorate %409 Flat -OpDecorate %411 BuiltIn Position -OpDecorate %413 Location 1 -OpDecorate %455 Location 0 -OpDecorate %455 Flat -OpDecorate %457 BuiltIn FragCoord -OpDecorate %460 Location 1 -OpDecorate %463 Location 0 -OpDecorate %464 Location 1 -OpDecorate %549 Location 0 -OpDecorate %552 Location 1 -OpDecorate %554 BuiltIn Position -OpDecorate %555 Location 0 -OpDecorate %557 Location 1 -OpDecorate %576 BuiltIn FragCoord -OpDecorate %578 Location 0 -OpDecorate %580 Location 1 -OpDecorate %582 Location 0 +OpDecorate %350 BuiltIn GlobalInvocationId +OpDecorate %421 BuiltIn VertexIndex +OpDecorate %424 Location 0 +OpDecorate %424 Flat +OpDecorate %426 BuiltIn Position +OpDecorate %428 Location 1 +OpDecorate %470 Location 0 +OpDecorate %470 Flat +OpDecorate %472 BuiltIn FragCoord +OpDecorate %475 Location 1 +OpDecorate %478 Location 0 +OpDecorate %479 Location 1 +OpDecorate %564 Location 0 +OpDecorate %567 Location 1 +OpDecorate %569 BuiltIn Position +OpDecorate %570 Location 0 +OpDecorate %572 Location 1 +OpDecorate %591 BuiltIn FragCoord +OpDecorate %593 Location 0 +OpDecorate %595 Location 1 +OpDecorate %597 Location 0 %2 = OpTypeVoid %4 = OpTypeFloat 32 %5 = OpTypeVector %4 3 @@ -7754,72 +7760,73 @@ OpDecorate %582 Location 0 %275 = OpConstant %4 -0.1 %276 = OpConstantComposite %6 %275 %74 %277 = OpConstantComposite %6 %74 %275 -%304 = OpTypeFunction %6 %8 %10 %11 -%321 = OpTypeFunction %5 %6 -%322 = OpConstant %4 23.0 -%323 = OpConstant %4 32.0 -%324 = OpConstantComposite %6 %322 %323 -%325 = OpConstant %4 -43.0 -%326 = OpConstant %4 3.0 -%327 = OpConstantComposite %6 %325 %326 -%343 = OpTypePointer Input %19 -%342 = OpVariable %343 Input -%346 = OpTypeFunction %2 -%347 = OpTypePointer Uniform %13 -%349 = OpConstant %8 6 -%350 = OpConstant %8 2 -%351 = OpConstant %8 3 -%352 = OpConstant %8 4 -%355 = OpTypePointer Uniform %10 -%358 = OpTypePointer Uniform %11 -%362 = OpTypePointer StorageBuffer %15 -%363 = OpTypePointer StorageBuffer %14 -%364 = OpTypePointer Uniform %6 -%371 = OpTypePointer Uniform %8 -%392 = OpTypePointer StorageBuffer %17 -%393 = OpTypePointer StorageBuffer %8 -%407 = OpTypePointer Input %8 -%406 = OpVariable %407 Input -%410 = OpTypePointer Output %8 -%409 = OpVariable %410 Output -%412 = OpTypePointer Output %7 -%411 = OpVariable %412 Output -%414 = OpTypePointer Output %6 -%413 = OpVariable %414 Output -%416 = OpTypePointer Uniform %20 -%418 = OpConstant %4 -1.0 -%419 = OpConstantComposite %6 %418 %418 -%434 = OpTypePointer Uniform %8 -%455 = OpVariable %407 Input -%458 = OpTypePointer Input %7 -%457 = OpVariable %458 Input -%461 = OpTypePointer Input %6 -%460 = OpVariable %461 Input -%463 = OpVariable %410 Output -%464 = OpVariable %410 Output -%467 = OpConstant %4 6.0 -%550 = OpTypePointer Input %5 -%549 = OpVariable %550 Input -%552 = OpVariable %550 Input -%554 = OpVariable %412 Output -%556 = OpTypePointer Output %5 -%555 = OpVariable %556 Output -%557 = OpVariable %556 Output -%559 = OpTypePointer Uniform %24 -%562 = OpTypePointer Uniform %23 -%576 = OpVariable %458 Input -%578 = OpVariable %550 Input -%580 = OpVariable %550 Input -%582 = OpVariable %412 Output -%585 = OpTypePointer Uniform %25 -%587 = OpConstantComposite %5 %272 %272 %272 -%588 = OpConstant %4 0.7 -%589 = OpConstantComposite %5 %78 %272 %588 -%590 = OpConstant %4 0.2 -%591 = OpConstantComposite %5 %590 %590 %590 -%593 = OpConstantNull %5 -%608 = OpTypePointer Uniform %5 -%617 = OpTypePointer Uniform %7 +%300 = OpTypeFunction %8 %8 %8 +%312 = OpTypeFunction %6 %8 %10 %11 +%329 = OpTypeFunction %5 %6 +%330 = OpConstant %4 23.0 +%331 = OpConstant %4 32.0 +%332 = OpConstantComposite %6 %330 %331 +%333 = OpConstant %4 -43.0 +%334 = OpConstant %4 3.0 +%335 = OpConstantComposite %6 %333 %334 +%351 = OpTypePointer Input %19 +%350 = OpVariable %351 Input +%354 = OpTypeFunction %2 +%355 = OpTypePointer Uniform %13 +%357 = OpConstant %8 6 +%358 = OpConstant %8 2 +%359 = OpConstant %8 3 +%360 = OpConstant %8 4 +%363 = OpTypePointer Uniform %10 +%366 = OpTypePointer Uniform %11 +%370 = OpTypePointer StorageBuffer %15 +%371 = OpTypePointer StorageBuffer %14 +%372 = OpTypePointer Uniform %6 +%379 = OpTypePointer Uniform %8 +%400 = OpTypePointer StorageBuffer %17 +%401 = OpTypePointer StorageBuffer %8 +%422 = OpTypePointer Input %8 +%421 = OpVariable %422 Input +%425 = OpTypePointer Output %8 +%424 = OpVariable %425 Output +%427 = OpTypePointer Output %7 +%426 = OpVariable %427 Output +%429 = OpTypePointer Output %6 +%428 = OpVariable %429 Output +%431 = OpTypePointer Uniform %20 +%433 = OpConstant %4 -1.0 +%434 = OpConstantComposite %6 %433 %433 +%449 = OpTypePointer Uniform %8 +%470 = OpVariable %422 Input +%473 = OpTypePointer Input %7 +%472 = OpVariable %473 Input +%476 = OpTypePointer Input %6 +%475 = OpVariable %476 Input +%478 = OpVariable %425 Output +%479 = OpVariable %425 Output +%482 = OpConstant %4 6.0 +%565 = OpTypePointer Input %5 +%564 = OpVariable %565 Input +%567 = OpVariable %565 Input +%569 = OpVariable %427 Output +%571 = OpTypePointer Output %5 +%570 = OpVariable %571 Output +%572 = OpVariable %571 Output +%574 = OpTypePointer Uniform %24 +%577 = OpTypePointer Uniform %23 +%591 = OpVariable %473 Input +%593 = OpVariable %565 Input +%595 = OpVariable %565 Input +%597 = OpVariable %427 Output +%600 = OpTypePointer Uniform %25 +%602 = OpConstantComposite %5 %272 %272 %272 +%603 = OpConstant %4 0.7 +%604 = OpConstantComposite %5 %78 %272 %603 +%605 = OpConstant %4 0.2 +%606 = OpConstantComposite %5 %605 %605 %605 +%608 = OpConstantNull %5 +%623 = OpTypePointer Uniform %5 +%632 = OpTypePointer Uniform %7 %53 = OpFunction %5 None %54 %52 = OpFunctionParameter %5 %51 = OpLabel @@ -8146,480 +8153,498 @@ OpLine %3 7239 12 %298 = OpCompositeConstruct %14 %279 %297 OpReturnValue %298 OpFunctionEnd -%303 = OpFunction %6 None %304 -%300 = OpFunctionParameter %8 -%301 = OpFunctionParameter %10 -%302 = OpFunctionParameter %11 -%299 = OpLabel -OpBranch %305 -%305 = OpLabel +%299 = OpFunction %8 None %300 +%301 = OpFunctionParameter %8 +%302 = OpFunctionParameter %8 +%303 = OpLabel +%304 = OpIEqual %112 %302 %135 +%305 = OpSelect %8 %304 %126 %302 +%306 = OpUDiv %8 %301 %305 +OpReturnValue %306 +OpFunctionEnd +%311 = OpFunction %6 None %312 +%308 = OpFunctionParameter %8 +%309 = OpFunctionParameter %10 +%310 = OpFunctionParameter %11 +%307 = OpLabel +OpBranch %313 +%313 = OpLabel OpLine %3 7244 9 -%306 = OpConvertUToF %4 %300 -%307 = OpCompositeExtract %8 %301 0 +%314 = OpConvertUToF %4 %308 +%315 = OpCompositeExtract %8 %309 0 OpLine %3 7244 9 -%308 = OpIAdd %8 %307 %126 -%309 = OpConvertUToF %4 %308 -%310 = OpFRem %4 %306 %309 -%311 = OpCompositeExtract %8 %301 0 +%316 = OpIAdd %8 %315 %126 +%317 = OpConvertUToF %4 %316 +%318 = OpFRem %4 %314 %317 +%319 = OpCompositeExtract %8 %309 0 OpLine %3 7243 12 -%312 = OpIAdd %8 %311 %126 -%313 = OpUDiv %8 %300 %312 -%314 = OpConvertUToF %4 %313 -%315 = OpCompositeConstruct %6 %310 %314 -%316 = OpConvertSToF %6 %302 -%317 = OpFAdd %6 %315 %316 -OpReturnValue %317 +%320 = OpIAdd %8 %319 %126 +%321 = OpFunctionCall %8 %299 %308 %320 +%322 = OpConvertUToF %4 %321 +%323 = OpCompositeConstruct %6 %318 %322 +%324 = OpConvertSToF %6 %310 +%325 = OpFAdd %6 %323 %324 +OpReturnValue %325 OpFunctionEnd -%320 = OpFunction %5 None %321 -%319 = OpFunctionParameter %6 -%318 = OpLabel -OpBranch %328 -%328 = OpLabel +%328 = OpFunction %5 None %329 +%327 = OpFunctionParameter %6 +%326 = OpLabel +OpBranch %336 +%336 = OpLabel OpLine %3 7413 9 -%329 = OpFunctionCall %4 %67 %319 +%337 = OpFunctionCall %4 %67 %327 OpLine %3 7413 9 -%330 = OpFMul %4 %329 %78 +%338 = OpFMul %4 %337 %78 OpLine %3 7413 9 -%331 = OpFAdd %4 %330 %78 +%339 = OpFAdd %4 %338 %78 OpLine %3 7414 17 -%332 = OpFAdd %6 %319 %324 +%340 = OpFAdd %6 %327 %332 OpLine %3 7414 9 -%333 = OpFunctionCall %4 %67 %332 +%341 = OpFunctionCall %4 %67 %340 OpLine %3 7414 9 -%334 = OpFMul %4 %333 %78 +%342 = OpFMul %4 %341 %78 OpLine %3 7414 9 -%335 = OpFAdd %4 %334 %78 +%343 = OpFAdd %4 %342 %78 OpLine %3 7415 17 -%336 = OpFAdd %6 %319 %327 +%344 = OpFAdd %6 %327 %335 OpLine %3 7415 9 -%337 = OpFunctionCall %4 %67 %336 +%345 = OpFunctionCall %4 %67 %344 OpLine %3 7415 9 -%338 = OpFMul %4 %337 %78 +%346 = OpFMul %4 %345 %78 OpLine %3 7412 12 -%339 = OpFAdd %4 %338 %78 -%340 = OpCompositeConstruct %5 %331 %335 %339 -OpReturnValue %340 +%347 = OpFAdd %4 %346 %78 +%348 = OpCompositeConstruct %5 %339 %343 %347 +OpReturnValue %348 OpFunctionEnd -%345 = OpFunction %2 None %346 -%341 = OpLabel -%344 = OpLoad %19 %342 -%348 = OpAccessChain %347 %29 %135 -OpBranch %353 -%353 = OpLabel +%353 = OpFunction %2 None %354 +%349 = OpLabel +%352 = OpLoad %19 %350 +%356 = OpAccessChain %355 %29 %135 +OpBranch %361 +%361 = OpLabel OpLine %3 7254 22 -%354 = OpCompositeExtract %8 %344 0 +%362 = OpCompositeExtract %8 %352 0 OpLine %3 7256 36 -%356 = OpAccessChain %355 %348 %135 -%357 = OpLoad %10 %356 +%364 = OpAccessChain %363 %356 %135 +%365 = OpLoad %10 %364 OpLine %3 7256 59 -%359 = OpAccessChain %358 %348 %126 -%360 = OpLoad %11 %359 +%367 = OpAccessChain %366 %356 %126 +%368 = OpLoad %11 %367 OpLine %3 7256 13 -%361 = OpFunctionCall %6 %303 %354 %357 %360 +%369 = OpFunctionCall %6 %311 %362 %365 %368 OpLine %3 7258 5 OpLine %3 7258 51 -%365 = OpAccessChain %364 %348 %350 -%366 = OpLoad %6 %365 +%373 = OpAccessChain %372 %356 %358 +%374 = OpLoad %6 %373 OpLine %3 7258 33 -%367 = OpFunctionCall %14 %270 %361 %366 +%375 = OpFunctionCall %14 %270 %369 %374 OpLine %3 7258 5 -%368 = OpAccessChain %363 %32 %135 %354 -OpStore %368 %367 +%376 = OpAccessChain %371 %32 %135 %362 +OpStore %376 %375 OpLine %3 7261 23 -%369 = OpCompositeExtract %8 %344 0 +%377 = OpCompositeExtract %8 %352 0 OpLine %3 7261 23 -%370 = OpIMul %8 %369 %349 +%378 = OpIMul %8 %377 %357 OpLine %3 7263 24 -%372 = OpAccessChain %371 %348 %135 %135 -%373 = OpLoad %8 %372 +%380 = OpAccessChain %379 %356 %135 %135 +%381 = OpLoad %8 %380 OpLine %3 7263 24 -%374 = OpAccessChain %371 %348 %135 %126 -%375 = OpLoad %8 %374 -%376 = OpIMul %8 %373 %375 +%382 = OpAccessChain %379 %356 %135 %126 +%383 = OpLoad %8 %382 +%384 = OpIMul %8 %381 %383 OpLine %3 7263 8 -%377 = OpIMul %8 %376 %349 -%378 = OpUGreaterThanEqual %112 %370 %377 +%385 = OpIMul %8 %384 %357 +%386 = OpUGreaterThanEqual %112 %378 %385 OpLine %3 7263 5 -OpSelectionMerge %379 None -OpBranchConditional %378 %380 %379 -%380 = OpLabel +OpSelectionMerge %387 None +OpBranchConditional %386 %388 %387 +%388 = OpLabel OpReturn -%379 = OpLabel +%387 = OpLabel OpLine %3 7265 28 -%381 = OpCompositeExtract %8 %344 0 +%389 = OpCompositeExtract %8 %352 0 OpLine %3 7265 15 -%382 = OpAccessChain %371 %348 %135 %135 -%383 = OpLoad %8 %382 -%384 = OpUDiv %8 %381 %383 -%385 = OpIAdd %8 %354 %384 +%390 = OpAccessChain %379 %356 %135 %135 +%391 = OpLoad %8 %390 +%392 = OpFunctionCall %8 %299 %389 %391 +%393 = OpIAdd %8 %362 %392 OpLine %3 7266 15 -%386 = OpIAdd %8 %385 %126 +%394 = OpIAdd %8 %393 %126 OpLine %3 7267 15 -%387 = OpAccessChain %371 %348 %135 %135 -%388 = OpLoad %8 %387 -%389 = OpIAdd %8 %385 %388 +%395 = OpAccessChain %379 %356 %135 %135 +%396 = OpLoad %8 %395 +%397 = OpIAdd %8 %393 %396 OpLine %3 7267 15 -%390 = OpIAdd %8 %389 %126 +%398 = OpIAdd %8 %397 %126 OpLine %3 7268 15 -%391 = OpIAdd %8 %390 %126 +%399 = OpIAdd %8 %398 %126 OpLine %3 7270 5 OpLine %3 7270 5 -%394 = OpAccessChain %393 %34 %135 %370 -OpStore %394 %385 +%402 = OpAccessChain %401 %34 %135 %378 +OpStore %402 %393 OpLine %3 7271 5 OpLine %3 7271 5 -%395 = OpIAdd %8 %370 %126 +%403 = OpIAdd %8 %378 %126 OpLine %3 7271 5 -%396 = OpAccessChain %393 %34 %135 %395 -OpStore %396 %390 +%404 = OpAccessChain %401 %34 %135 %403 +OpStore %404 %398 OpLine %3 7272 5 OpLine %3 7272 5 -%397 = OpIAdd %8 %370 %350 +%405 = OpIAdd %8 %378 %358 OpLine %3 7272 5 -%398 = OpAccessChain %393 %34 %135 %397 -OpStore %398 %391 +%406 = OpAccessChain %401 %34 %135 %405 +OpStore %406 %399 OpLine %3 7273 5 OpLine %3 7273 5 -%399 = OpIAdd %8 %370 %351 +%407 = OpIAdd %8 %378 %359 OpLine %3 7273 5 -%400 = OpAccessChain %393 %34 %135 %399 -OpStore %400 %385 +%408 = OpAccessChain %401 %34 %135 %407 +OpStore %408 %393 OpLine %3 7274 5 OpLine %3 7274 5 -%401 = OpIAdd %8 %370 %352 +%409 = OpIAdd %8 %378 %360 OpLine %3 7274 5 -%402 = OpAccessChain %393 %34 %135 %401 -OpStore %402 %391 +%410 = OpAccessChain %401 %34 %135 %409 +OpStore %410 %399 OpLine %3 7275 5 OpLine %3 7275 5 -%403 = OpIAdd %8 %370 %205 +%411 = OpIAdd %8 %378 %205 OpLine %3 7275 5 -%404 = OpAccessChain %393 %34 %135 %403 -OpStore %404 %386 +%412 = OpAccessChain %401 %34 %135 %411 +OpStore %412 %394 OpReturn OpFunctionEnd -%415 = OpFunction %2 None %346 -%405 = OpLabel -%408 = OpLoad %8 %406 -%417 = OpAccessChain %416 %36 %135 -OpBranch %420 +%413 = OpFunction %8 None %300 +%414 = OpFunctionParameter %8 +%415 = OpFunctionParameter %8 +%416 = OpLabel +%417 = OpIEqual %112 %415 %135 +%418 = OpSelect %8 %417 %126 %415 +%419 = OpUMod %8 %414 %418 +OpReturnValue %419 +OpFunctionEnd +%430 = OpFunction %2 None %354 %420 = OpLabel +%423 = OpLoad %8 %421 +%432 = OpAccessChain %431 %36 %135 +OpBranch %435 +%435 = OpLabel OpLine %3 7304 19 -%421 = OpIAdd %8 %408 %350 +%436 = OpIAdd %8 %423 %358 OpLine %3 7304 18 -%422 = OpUDiv %8 %421 %351 +%437 = OpFunctionCall %8 %299 %436 %359 OpLine %3 7304 13 -%423 = OpUMod %8 %422 %350 -%424 = OpConvertUToF %4 %423 +%438 = OpFunctionCall %8 %413 %437 %358 +%439 = OpConvertUToF %4 %438 OpLine %3 7305 19 -%425 = OpIAdd %8 %408 %126 +%440 = OpIAdd %8 %423 %126 OpLine %3 7305 18 -%426 = OpUDiv %8 %425 %351 +%441 = OpFunctionCall %8 %299 %440 %359 OpLine %3 7305 13 -%427 = OpUMod %8 %426 %350 -%428 = OpConvertUToF %4 %427 +%442 = OpFunctionCall %8 %413 %441 %358 +%443 = OpConvertUToF %4 %442 OpLine %3 7306 14 -%429 = OpCompositeConstruct %6 %424 %428 +%444 = OpCompositeConstruct %6 %439 %443 OpLine %3 7308 30 -%430 = OpVectorTimesScalar %6 %429 %81 +%445 = OpVectorTimesScalar %6 %444 %81 OpLine %3 7308 30 -%431 = OpFAdd %6 %419 %430 +%446 = OpFAdd %6 %434 %445 OpLine %3 7308 20 -%432 = OpCompositeConstruct %7 %431 %74 %56 +%447 = OpCompositeConstruct %7 %446 %74 %56 OpLine %3 7311 21 -%433 = OpCompositeExtract %4 %429 0 +%448 = OpCompositeExtract %4 %444 0 OpLine %3 7311 21 -%435 = OpAccessChain %434 %417 %351 -%436 = OpLoad %8 %435 -%437 = OpConvertUToF %4 %436 -%438 = OpFMul %4 %433 %437 -%439 = OpCompositeExtract %4 %429 1 +%450 = OpAccessChain %449 %432 %359 +%451 = OpLoad %8 %450 +%452 = OpConvertUToF %4 %451 +%453 = OpFMul %4 %448 %452 +%454 = OpCompositeExtract %4 %444 1 OpLine %3 7311 17 -%440 = OpAccessChain %434 %417 %351 -%441 = OpLoad %8 %440 -%442 = OpConvertUToF %4 %441 -%443 = OpFMul %4 %439 %442 -%444 = OpFAdd %4 %438 %443 -%445 = OpConvertFToU %8 %444 +%455 = OpAccessChain %449 %432 %359 +%456 = OpLoad %8 %455 +%457 = OpConvertUToF %4 %456 +%458 = OpFMul %4 %454 %457 +%459 = OpFAdd %4 %453 %458 +%460 = OpConvertFToU %8 %459 OpLine %3 7311 17 -%446 = OpAccessChain %434 %417 %352 -%447 = OpLoad %8 %446 -%448 = OpIAdd %8 %445 %447 +%461 = OpAccessChain %449 %432 %360 +%462 = OpLoad %8 %461 +%463 = OpIAdd %8 %460 %462 OpLine %3 7313 12 -%449 = OpCompositeConstruct %21 %448 %432 %429 -%450 = OpCompositeExtract %8 %449 0 -OpStore %409 %450 -%451 = OpCompositeExtract %7 %449 1 -OpStore %411 %451 -%452 = OpCompositeExtract %6 %449 2 -OpStore %413 %452 +%464 = OpCompositeConstruct %21 %463 %447 %444 +%465 = OpCompositeExtract %8 %464 0 +OpStore %424 %465 +%466 = OpCompositeExtract %7 %464 1 +OpStore %426 %466 +%467 = OpCompositeExtract %6 %464 2 +OpStore %428 %467 OpReturn OpFunctionEnd -%465 = OpFunction %2 None %346 -%453 = OpLabel -%468 = OpVariable %215 Function %74 -%469 = OpVariable %218 Function %135 -%456 = OpLoad %8 %455 -%459 = OpLoad %7 %457 -%462 = OpLoad %6 %460 -%454 = OpCompositeConstruct %21 %456 %459 %462 -%466 = OpAccessChain %416 %36 %135 -OpBranch %470 -%470 = OpLabel +%480 = OpFunction %2 None %354 +%468 = OpLabel +%483 = OpVariable %215 Function %74 +%484 = OpVariable %218 Function %135 +%471 = OpLoad %8 %470 +%474 = OpLoad %7 %472 +%477 = OpLoad %6 %475 +%469 = OpCompositeConstruct %21 %471 %474 %477 +%481 = OpAccessChain %431 %36 %135 +OpBranch %485 +%485 = OpLabel OpLine %3 7324 17 -%471 = OpCompositeExtract %6 %454 2 -%472 = OpCompositeExtract %4 %471 0 +%486 = OpCompositeExtract %6 %469 2 +%487 = OpCompositeExtract %4 %486 0 OpLine %3 7324 17 -%473 = OpAccessChain %434 %466 %351 -%474 = OpLoad %8 %473 -%475 = OpConvertUToF %4 %474 -%476 = OpFMul %4 %472 %475 -%477 = OpCompositeExtract %6 %454 2 -%478 = OpCompositeExtract %4 %477 1 +%488 = OpAccessChain %449 %481 %359 +%489 = OpLoad %8 %488 +%490 = OpConvertUToF %4 %489 +%491 = OpFMul %4 %487 %490 +%492 = OpCompositeExtract %6 %469 2 +%493 = OpCompositeExtract %4 %492 1 OpLine %3 7324 70 -%479 = OpAccessChain %434 %466 %351 -%480 = OpLoad %8 %479 +%494 = OpAccessChain %449 %481 %359 +%495 = OpLoad %8 %494 OpLine %3 7324 13 -%481 = OpAccessChain %434 %466 %351 -%482 = OpLoad %8 %481 -%483 = OpIMul %8 %480 %482 -%484 = OpConvertUToF %4 %483 -%485 = OpFMul %4 %478 %484 -%486 = OpFAdd %4 %476 %485 -%487 = OpConvertFToU %8 %486 +%496 = OpAccessChain %449 %481 %359 +%497 = OpLoad %8 %496 +%498 = OpIMul %8 %495 %497 +%499 = OpConvertUToF %4 %498 +%500 = OpFMul %4 %493 %499 +%501 = OpFAdd %4 %491 %500 +%502 = OpConvertFToU %8 %501 OpLine %3 7324 13 -%488 = OpAccessChain %434 %466 %352 -%489 = OpLoad %8 %488 -%490 = OpIAdd %8 %487 %489 +%503 = OpAccessChain %449 %481 %360 +%504 = OpLoad %8 %503 +%505 = OpIAdd %8 %502 %504 OpLine %3 7325 32 -%491 = OpConvertUToF %4 %490 +%506 = OpConvertUToF %4 %505 OpLine %3 7325 22 -%492 = OpFDiv %4 %491 %467 -%493 = OpExtInst %4 %1 Floor %492 -%494 = OpConvertFToU %8 %493 +%507 = OpFDiv %4 %506 %482 +%508 = OpExtInst %4 %1 Floor %507 +%509 = OpConvertFToU %8 %508 OpLine %3 7326 22 -%495 = OpUMod %8 %490 %349 +%510 = OpFunctionCall %8 %413 %505 %357 OpLine %3 7328 36 -%496 = OpAccessChain %355 %466 %135 -%497 = OpLoad %10 %496 +%511 = OpAccessChain %363 %481 %135 +%512 = OpLoad %10 %511 OpLine %3 7328 57 -%498 = OpAccessChain %358 %466 %126 -%499 = OpLoad %11 %498 +%513 = OpAccessChain %366 %481 %126 +%514 = OpLoad %11 %513 OpLine %3 7328 13 -%500 = OpFunctionCall %6 %303 %494 %497 %499 +%515 = OpFunctionCall %6 %311 %509 %512 %514 OpLine %3 7329 31 -%501 = OpAccessChain %364 %466 %350 -%502 = OpLoad %6 %501 +%516 = OpAccessChain %372 %481 %358 +%517 = OpLoad %6 %516 OpLine %3 7329 13 -%503 = OpFunctionCall %14 %270 %500 %502 +%518 = OpFunctionCall %14 %270 %515 %517 OpLine %3 7333 5 -OpSelectionMerge %504 None -OpSwitch %495 %511 0 %505 1 %506 2 %507 3 %508 4 %509 5 %510 -%505 = OpLabel +OpSelectionMerge %519 None +OpSwitch %510 %526 0 %520 1 %521 2 %522 3 %523 4 %524 5 %525 +%520 = OpLabel OpLine %3 7334 37 -%512 = OpCompositeExtract %5 %503 0 -%513 = OpCompositeExtract %4 %512 0 +%527 = OpCompositeExtract %5 %518 0 +%528 = OpCompositeExtract %4 %527 0 OpLine %3 7334 20 -OpStore %468 %513 -OpBranch %504 -%506 = OpLabel +OpStore %483 %528 +OpBranch %519 +%521 = OpLabel OpLine %3 7335 37 -%514 = OpCompositeExtract %5 %503 0 -%515 = OpCompositeExtract %4 %514 1 +%529 = OpCompositeExtract %5 %518 0 +%530 = OpCompositeExtract %4 %529 1 OpLine %3 7335 20 -OpStore %468 %515 -OpBranch %504 -%507 = OpLabel +OpStore %483 %530 +OpBranch %519 +%522 = OpLabel OpLine %3 7336 37 -%516 = OpCompositeExtract %5 %503 0 -%517 = OpCompositeExtract %4 %516 2 +%531 = OpCompositeExtract %5 %518 0 +%532 = OpCompositeExtract %4 %531 2 OpLine %3 7336 20 -OpStore %468 %517 -OpBranch %504 -%508 = OpLabel +OpStore %483 %532 +OpBranch %519 +%523 = OpLabel OpLine %3 7337 37 -%518 = OpCompositeExtract %5 %503 1 -%519 = OpCompositeExtract %4 %518 0 +%533 = OpCompositeExtract %5 %518 1 +%534 = OpCompositeExtract %4 %533 0 OpLine %3 7337 20 -OpStore %468 %519 -OpBranch %504 -%509 = OpLabel +OpStore %483 %534 +OpBranch %519 +%524 = OpLabel OpLine %3 7338 37 -%520 = OpCompositeExtract %5 %503 1 -%521 = OpCompositeExtract %4 %520 1 +%535 = OpCompositeExtract %5 %518 1 +%536 = OpCompositeExtract %4 %535 1 OpLine %3 7338 20 -OpStore %468 %521 -OpBranch %504 -%510 = OpLabel +OpStore %483 %536 +OpBranch %519 +%525 = OpLabel OpLine %3 7339 37 -%522 = OpCompositeExtract %5 %503 1 -%523 = OpCompositeExtract %4 %522 2 +%537 = OpCompositeExtract %5 %518 1 +%538 = OpCompositeExtract %4 %537 2 OpLine %3 7339 20 -OpStore %468 %523 -OpBranch %504 -%511 = OpLabel -OpBranch %504 -%504 = OpLabel +OpStore %483 %538 +OpBranch %519 +%526 = OpLabel +OpBranch %519 +%519 = OpLabel OpLine %3 7343 15 -%524 = OpAccessChain %371 %466 %135 %135 -%525 = OpLoad %8 %524 -%526 = OpUDiv %8 %494 %525 -%527 = OpIAdd %8 %494 %526 +%539 = OpAccessChain %379 %481 %135 %135 +%540 = OpLoad %8 %539 +%541 = OpFunctionCall %8 %299 %509 %540 +%542 = OpIAdd %8 %509 %541 OpLine %3 7344 15 -%528 = OpIAdd %8 %527 %126 +%543 = OpIAdd %8 %542 %126 OpLine %3 7345 15 -%529 = OpAccessChain %371 %466 %135 %135 -%530 = OpLoad %8 %529 -%531 = OpIAdd %8 %527 %530 +%544 = OpAccessChain %379 %481 %135 %135 +%545 = OpLoad %8 %544 +%546 = OpIAdd %8 %542 %545 OpLine %3 7345 15 -%532 = OpIAdd %8 %531 %126 +%547 = OpIAdd %8 %546 %126 OpLine %3 7346 15 -%533 = OpIAdd %8 %532 %126 +%548 = OpIAdd %8 %547 %126 OpLine %3 7349 5 -OpSelectionMerge %534 None -OpSwitch %495 %539 0 %535 3 %535 2 %536 4 %536 1 %537 5 %538 -%535 = OpLabel +OpSelectionMerge %549 None +OpSwitch %510 %554 0 %550 3 %550 2 %551 4 %551 1 %552 5 %553 +%550 = OpLabel OpLine %3 7350 24 -OpStore %469 %527 -OpBranch %534 -%536 = OpLabel +OpStore %484 %542 +OpBranch %549 +%551 = OpLabel OpLine %3 7351 24 -OpStore %469 %533 -OpBranch %534 -%537 = OpLabel +OpStore %484 %548 +OpBranch %549 +%552 = OpLabel OpLine %3 7352 20 -OpStore %469 %532 -OpBranch %534 -%538 = OpLabel +OpStore %484 %547 +OpBranch %549 +%553 = OpLabel OpLine %3 7353 20 -OpStore %469 %528 -OpBranch %534 -%539 = OpLabel -OpBranch %534 -%534 = OpLabel +OpStore %484 %543 +OpBranch %549 +%554 = OpLabel +OpBranch %549 +%549 = OpLabel OpLine %3 7356 13 -%540 = OpCompositeExtract %8 %454 0 +%555 = OpCompositeExtract %8 %469 0 OpLine %3 7356 5 -OpStore %469 %540 +OpStore %484 %555 OpLine %3 7365 27 -%541 = OpLoad %4 %468 -%542 = OpBitcast %8 %541 +%556 = OpLoad %4 %483 +%557 = OpBitcast %8 %556 OpLine %3 7366 12 -%543 = OpLoad %8 %469 -%544 = OpCompositeConstruct %22 %542 %543 -%545 = OpCompositeExtract %8 %544 0 -OpStore %463 %545 -%546 = OpCompositeExtract %8 %544 1 -OpStore %464 %546 +%558 = OpLoad %8 %484 +%559 = OpCompositeConstruct %22 %557 %558 +%560 = OpCompositeExtract %8 %559 0 +OpStore %478 %560 +%561 = OpCompositeExtract %8 %559 1 +OpStore %479 %561 OpReturn OpFunctionEnd -%558 = OpFunction %2 None %346 -%547 = OpLabel -%551 = OpLoad %5 %549 -%553 = OpLoad %5 %552 -%548 = OpCompositeConstruct %14 %551 %553 -%560 = OpAccessChain %559 %39 %135 -OpBranch %561 -%561 = OpLabel +%573 = OpFunction %2 None %354 +%562 = OpLabel +%566 = OpLoad %5 %564 +%568 = OpLoad %5 %567 +%563 = OpCompositeConstruct %14 %566 %568 +%575 = OpAccessChain %574 %39 %135 +OpBranch %576 +%576 = OpLabel OpLine %3 7397 25 -%563 = OpAccessChain %562 %560 %126 -%564 = OpLoad %23 %563 -%565 = OpCompositeExtract %5 %548 0 +%578 = OpAccessChain %577 %575 %126 +%579 = OpLoad %23 %578 +%580 = OpCompositeExtract %5 %563 0 OpLine %3 7397 25 -%566 = OpCompositeConstruct %7 %565 %56 -%567 = OpMatrixTimesVector %7 %564 %566 +%581 = OpCompositeConstruct %7 %580 %56 +%582 = OpMatrixTimesVector %7 %579 %581 OpLine %3 7398 18 -%568 = OpCompositeExtract %5 %548 1 +%583 = OpCompositeExtract %5 %563 1 OpLine %3 7399 12 -%569 = OpCompositeExtract %5 %548 0 -%570 = OpCompositeConstruct %26 %567 %568 %569 -%571 = OpCompositeExtract %7 %570 0 -OpStore %554 %571 -%572 = OpCompositeExtract %5 %570 1 -OpStore %555 %572 -%573 = OpCompositeExtract %5 %570 2 -OpStore %557 %573 +%584 = OpCompositeExtract %5 %563 0 +%585 = OpCompositeConstruct %26 %582 %583 %584 +%586 = OpCompositeExtract %7 %585 0 +OpStore %569 %586 +%587 = OpCompositeExtract %5 %585 1 +OpStore %570 %587 +%588 = OpCompositeExtract %5 %585 2 +OpStore %572 %588 OpReturn OpFunctionEnd -%583 = OpFunction %2 None %346 -%574 = OpLabel -%592 = OpVariable %95 Function %593 -%577 = OpLoad %7 %576 -%579 = OpLoad %5 %578 -%581 = OpLoad %5 %580 -%575 = OpCompositeConstruct %26 %577 %579 %581 -%584 = OpAccessChain %559 %39 %135 -%586 = OpAccessChain %585 %42 %135 -OpBranch %594 -%594 = OpLabel +%598 = OpFunction %2 None %354 +%589 = OpLabel +%607 = OpVariable %95 Function %608 +%592 = OpLoad %7 %591 +%594 = OpLoad %5 %593 +%596 = OpLoad %5 %595 +%590 = OpCompositeConstruct %26 %592 %594 %596 +%599 = OpAccessChain %574 %39 %135 +%601 = OpAccessChain %600 %42 %135 +OpBranch %609 +%609 = OpLabel OpLine %3 7421 28 OpLine %3 7421 17 -%595 = OpCompositeExtract %5 %575 2 -%596 = OpExtInst %5 %1 Fract %595 -%597 = OpExtInst %5 %1 SmoothStep %80 %587 %596 +%610 = OpCompositeExtract %5 %590 2 +%611 = OpExtInst %5 %1 Fract %610 +%612 = OpExtInst %5 %1 SmoothStep %80 %602 %611 OpLine %3 7421 5 -OpStore %592 %597 +OpStore %607 %612 OpLine %3 7422 17 OpLine %3 7422 13 -%598 = OpAccessChain %125 %592 %135 -%599 = OpLoad %4 %598 -%600 = OpAccessChain %125 %592 %126 -%601 = OpLoad %4 %600 -%602 = OpFMul %4 %599 %601 -%603 = OpAccessChain %125 %592 %350 -%604 = OpLoad %4 %603 -%605 = OpFMul %4 %602 %604 -%606 = OpCompositeConstruct %5 %605 %605 %605 -%607 = OpExtInst %5 %1 FMix %589 %591 %606 +%613 = OpAccessChain %125 %607 %135 +%614 = OpLoad %4 %613 +%615 = OpAccessChain %125 %607 %126 +%616 = OpLoad %4 %615 +%617 = OpFMul %4 %614 %616 +%618 = OpAccessChain %125 %607 %358 +%619 = OpLoad %4 %618 +%620 = OpFMul %4 %617 %619 +%621 = OpCompositeConstruct %5 %620 %620 %620 +%622 = OpExtInst %5 %1 FMix %604 %606 %621 OpLine %3 7422 5 -OpStore %592 %607 +OpStore %607 %622 OpLine %3 7425 25 -%609 = OpAccessChain %608 %586 %126 -%610 = OpLoad %5 %609 -%611 = OpVectorTimesScalar %5 %610 %272 +%624 = OpAccessChain %623 %601 %126 +%625 = OpLoad %5 %624 +%626 = OpVectorTimesScalar %5 %625 %272 OpLine %3 7427 21 -%612 = OpAccessChain %608 %586 %135 -%613 = OpLoad %5 %612 -%614 = OpCompositeExtract %5 %575 2 -%615 = OpFSub %5 %613 %614 -%616 = OpExtInst %5 %1 Normalize %615 +%627 = OpAccessChain %623 %601 %135 +%628 = OpLoad %5 %627 +%629 = OpCompositeExtract %5 %590 2 +%630 = OpFSub %5 %628 %629 +%631 = OpExtInst %5 %1 Normalize %630 OpLine %3 7428 20 -%618 = OpAccessChain %617 %584 %135 -%619 = OpLoad %7 %618 -%620 = OpVectorShuffle %5 %619 %619 0 1 2 -%621 = OpCompositeExtract %5 %575 2 -%622 = OpFSub %5 %620 %621 -%623 = OpExtInst %5 %1 Normalize %622 +%633 = OpAccessChain %632 %599 %135 +%634 = OpLoad %7 %633 +%635 = OpVectorShuffle %5 %634 %634 0 1 2 +%636 = OpCompositeExtract %5 %590 2 +%637 = OpFSub %5 %635 %636 +%638 = OpExtInst %5 %1 Normalize %637 OpLine %3 7429 20 -%624 = OpFAdd %5 %623 %616 -%625 = OpExtInst %5 %1 Normalize %624 +%639 = OpFAdd %5 %638 %631 +%640 = OpExtInst %5 %1 Normalize %639 OpLine %3 7431 32 -%626 = OpCompositeExtract %5 %575 1 -%627 = OpDot %4 %626 %616 +%641 = OpCompositeExtract %5 %590 1 +%642 = OpDot %4 %641 %631 OpLine %3 7431 28 -%628 = OpExtInst %4 %1 FMax %627 %74 +%643 = OpExtInst %4 %1 FMax %642 %74 OpLine %3 7432 25 -%629 = OpAccessChain %608 %586 %126 -%630 = OpLoad %5 %629 -%631 = OpVectorTimesScalar %5 %630 %628 +%644 = OpAccessChain %623 %601 %126 +%645 = OpLoad %5 %644 +%646 = OpVectorTimesScalar %5 %645 %643 OpLine %3 7434 37 -%632 = OpCompositeExtract %5 %575 1 -%633 = OpDot %4 %632 %625 +%647 = OpCompositeExtract %5 %590 1 +%648 = OpDot %4 %647 %640 OpLine %3 7434 33 -%634 = OpExtInst %4 %1 FMax %633 %74 +%649 = OpExtInst %4 %1 FMax %648 %74 OpLine %3 7434 29 -%635 = OpExtInst %4 %1 Pow %634 %323 +%650 = OpExtInst %4 %1 Pow %649 %331 OpLine %3 7435 26 -%636 = OpAccessChain %608 %586 %126 -%637 = OpLoad %5 %636 -%638 = OpVectorTimesScalar %5 %637 %635 +%651 = OpAccessChain %623 %601 %126 +%652 = OpLoad %5 %651 +%653 = OpVectorTimesScalar %5 %652 %650 OpLine %3 7437 18 -%639 = OpFAdd %5 %611 %631 -%640 = OpFAdd %5 %639 %638 -%641 = OpLoad %5 %592 -%642 = OpFMul %5 %640 %641 +%654 = OpFAdd %5 %626 %646 +%655 = OpFAdd %5 %654 %653 +%656 = OpLoad %5 %607 +%657 = OpFMul %5 %655 %656 OpLine %3 7439 12 -%643 = OpCompositeConstruct %7 %642 %56 -OpStore %582 %643 +%658 = OpCompositeConstruct %7 %657 %56 +OpStore %597 %658 OpReturn OpFunctionEnd \ No newline at end of file diff --git a/naga/tests/out/spv/debug-symbol-terrain.spvasm b/naga/tests/out/spv/debug-symbol-terrain.spvasm index 38d8984d0f..e8d7d141e7 100644 --- a/naga/tests/out/spv/debug-symbol-terrain.spvasm +++ b/naga/tests/out/spv/debug-symbol-terrain.spvasm @@ -1,19 +1,19 @@ ; SPIR-V ; Version: 1.1 ; Generator: rspirv -; Bound: 644 +; Bound: 659 OpCapability Shader OpExtension "SPV_KHR_storage_buffer_storage_class" %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %345 "gen_terrain_compute" %342 -OpEntryPoint Vertex %415 "gen_terrain_vertex" %406 %409 %411 %413 -OpEntryPoint Fragment %465 "gen_terrain_fragment" %455 %457 %460 %463 %464 -OpEntryPoint Vertex %558 "vs_main" %549 %552 %554 %555 %557 -OpEntryPoint Fragment %583 "fs_main" %576 %578 %580 %582 -OpExecutionMode %345 LocalSize 64 1 1 -OpExecutionMode %465 OriginUpperLeft -OpExecutionMode %583 OriginUpperLeft +OpEntryPoint GLCompute %353 "gen_terrain_compute" %350 +OpEntryPoint Vertex %430 "gen_terrain_vertex" %421 %424 %426 %428 +OpEntryPoint Fragment %480 "gen_terrain_fragment" %470 %472 %475 %478 %479 +OpEntryPoint Vertex %573 "vs_main" %564 %567 %569 %570 %572 +OpEntryPoint Fragment %598 "fs_main" %591 %593 %595 %597 +OpExecutionMode %353 LocalSize 64 1 1 +OpExecutionMode %480 OriginUpperLeft +OpExecutionMode %598 OriginUpperLeft %3 = OpString "debug-symbol-terrain.wgsl" OpSource Unknown 0 %3 "// Taken from https://github.com/sotrh/learn-wgpu/blob/11820796f5e1dbce42fb1119f04ddeb4b167d2a0/code/intermediate/tutorial13-terrain/src/terrain.wgsl // ============================ @@ -376,38 +376,44 @@ OpName %257 "terrain_point" OpName %268 "p" OpName %269 "min_max_height" OpName %270 "terrain_vertex" -OpName %300 "vert_index" -OpName %301 "chunk_size" -OpName %302 "chunk_corner" -OpName %303 "index_to_p" -OpName %319 "p" -OpName %320 "color23" -OpName %342 "gid" -OpName %345 "gen_terrain_compute" -OpName %406 "vindex" -OpName %409 "index" -OpName %411 "position" -OpName %413 "uv" -OpName %415 "gen_terrain_vertex" -OpName %455 "index" -OpName %457 "position" -OpName %460 "uv" -OpName %463 "vert_component" -OpName %464 "index" -OpName %465 "gen_terrain_fragment" -OpName %468 "vert_component" -OpName %469 "index" -OpName %549 "position" -OpName %552 "normal" -OpName %554 "clip_position" -OpName %555 "normal" -OpName %557 "world_pos" -OpName %558 "vs_main" -OpName %576 "clip_position" -OpName %578 "normal" -OpName %580 "world_pos" -OpName %583 "fs_main" -OpName %592 "color" +OpName %299 "naga_div" +OpName %301 "lhs" +OpName %302 "rhs" +OpName %308 "vert_index" +OpName %309 "chunk_size" +OpName %310 "chunk_corner" +OpName %311 "index_to_p" +OpName %327 "p" +OpName %328 "color23" +OpName %350 "gid" +OpName %353 "gen_terrain_compute" +OpName %413 "naga_mod" +OpName %414 "lhs" +OpName %415 "rhs" +OpName %421 "vindex" +OpName %424 "index" +OpName %426 "position" +OpName %428 "uv" +OpName %430 "gen_terrain_vertex" +OpName %470 "index" +OpName %472 "position" +OpName %475 "uv" +OpName %478 "vert_component" +OpName %479 "index" +OpName %480 "gen_terrain_fragment" +OpName %483 "vert_component" +OpName %484 "index" +OpName %564 "position" +OpName %567 "normal" +OpName %569 "clip_position" +OpName %570 "normal" +OpName %572 "world_pos" +OpName %573 "vs_main" +OpName %591 "clip_position" +OpName %593 "normal" +OpName %595 "world_pos" +OpName %598 "fs_main" +OpName %607 "color" OpMemberDecorate %13 0 Offset 0 OpMemberDecorate %13 1 Offset 8 OpMemberDecorate %13 2 Offset 16 @@ -466,27 +472,27 @@ OpDecorate %49 DescriptorSet 2 OpDecorate %49 Binding 2 OpDecorate %50 DescriptorSet 2 OpDecorate %50 Binding 3 -OpDecorate %342 BuiltIn GlobalInvocationId -OpDecorate %406 BuiltIn VertexIndex -OpDecorate %409 Location 0 -OpDecorate %409 Flat -OpDecorate %411 BuiltIn Position -OpDecorate %413 Location 1 -OpDecorate %455 Location 0 -OpDecorate %455 Flat -OpDecorate %457 BuiltIn FragCoord -OpDecorate %460 Location 1 -OpDecorate %463 Location 0 -OpDecorate %464 Location 1 -OpDecorate %549 Location 0 -OpDecorate %552 Location 1 -OpDecorate %554 BuiltIn Position -OpDecorate %555 Location 0 -OpDecorate %557 Location 1 -OpDecorate %576 BuiltIn FragCoord -OpDecorate %578 Location 0 -OpDecorate %580 Location 1 -OpDecorate %582 Location 0 +OpDecorate %350 BuiltIn GlobalInvocationId +OpDecorate %421 BuiltIn VertexIndex +OpDecorate %424 Location 0 +OpDecorate %424 Flat +OpDecorate %426 BuiltIn Position +OpDecorate %428 Location 1 +OpDecorate %470 Location 0 +OpDecorate %470 Flat +OpDecorate %472 BuiltIn FragCoord +OpDecorate %475 Location 1 +OpDecorate %478 Location 0 +OpDecorate %479 Location 1 +OpDecorate %564 Location 0 +OpDecorate %567 Location 1 +OpDecorate %569 BuiltIn Position +OpDecorate %570 Location 0 +OpDecorate %572 Location 1 +OpDecorate %591 BuiltIn FragCoord +OpDecorate %593 Location 0 +OpDecorate %595 Location 1 +OpDecorate %597 Location 0 %2 = OpTypeVoid %4 = OpTypeFloat 32 %5 = OpTypeVector %4 3 @@ -589,72 +595,73 @@ OpDecorate %582 Location 0 %275 = OpConstant %4 -0.1 %276 = OpConstantComposite %6 %275 %74 %277 = OpConstantComposite %6 %74 %275 -%304 = OpTypeFunction %6 %8 %10 %11 -%321 = OpTypeFunction %5 %6 -%322 = OpConstant %4 23.0 -%323 = OpConstant %4 32.0 -%324 = OpConstantComposite %6 %322 %323 -%325 = OpConstant %4 -43.0 -%326 = OpConstant %4 3.0 -%327 = OpConstantComposite %6 %325 %326 -%343 = OpTypePointer Input %19 -%342 = OpVariable %343 Input -%346 = OpTypeFunction %2 -%347 = OpTypePointer Uniform %13 -%349 = OpConstant %8 6 -%350 = OpConstant %8 2 -%351 = OpConstant %8 3 -%352 = OpConstant %8 4 -%355 = OpTypePointer Uniform %10 -%358 = OpTypePointer Uniform %11 -%362 = OpTypePointer StorageBuffer %15 -%363 = OpTypePointer StorageBuffer %14 -%364 = OpTypePointer Uniform %6 -%371 = OpTypePointer Uniform %8 -%392 = OpTypePointer StorageBuffer %17 -%393 = OpTypePointer StorageBuffer %8 -%407 = OpTypePointer Input %8 -%406 = OpVariable %407 Input -%410 = OpTypePointer Output %8 -%409 = OpVariable %410 Output -%412 = OpTypePointer Output %7 -%411 = OpVariable %412 Output -%414 = OpTypePointer Output %6 -%413 = OpVariable %414 Output -%416 = OpTypePointer Uniform %20 -%418 = OpConstant %4 -1.0 -%419 = OpConstantComposite %6 %418 %418 -%434 = OpTypePointer Uniform %8 -%455 = OpVariable %407 Input -%458 = OpTypePointer Input %7 -%457 = OpVariable %458 Input -%461 = OpTypePointer Input %6 -%460 = OpVariable %461 Input -%463 = OpVariable %410 Output -%464 = OpVariable %410 Output -%467 = OpConstant %4 6.0 -%550 = OpTypePointer Input %5 -%549 = OpVariable %550 Input -%552 = OpVariable %550 Input -%554 = OpVariable %412 Output -%556 = OpTypePointer Output %5 -%555 = OpVariable %556 Output -%557 = OpVariable %556 Output -%559 = OpTypePointer Uniform %24 -%562 = OpTypePointer Uniform %23 -%576 = OpVariable %458 Input -%578 = OpVariable %550 Input -%580 = OpVariable %550 Input -%582 = OpVariable %412 Output -%585 = OpTypePointer Uniform %25 -%587 = OpConstantComposite %5 %272 %272 %272 -%588 = OpConstant %4 0.7 -%589 = OpConstantComposite %5 %78 %272 %588 -%590 = OpConstant %4 0.2 -%591 = OpConstantComposite %5 %590 %590 %590 -%593 = OpConstantNull %5 -%608 = OpTypePointer Uniform %5 -%617 = OpTypePointer Uniform %7 +%300 = OpTypeFunction %8 %8 %8 +%312 = OpTypeFunction %6 %8 %10 %11 +%329 = OpTypeFunction %5 %6 +%330 = OpConstant %4 23.0 +%331 = OpConstant %4 32.0 +%332 = OpConstantComposite %6 %330 %331 +%333 = OpConstant %4 -43.0 +%334 = OpConstant %4 3.0 +%335 = OpConstantComposite %6 %333 %334 +%351 = OpTypePointer Input %19 +%350 = OpVariable %351 Input +%354 = OpTypeFunction %2 +%355 = OpTypePointer Uniform %13 +%357 = OpConstant %8 6 +%358 = OpConstant %8 2 +%359 = OpConstant %8 3 +%360 = OpConstant %8 4 +%363 = OpTypePointer Uniform %10 +%366 = OpTypePointer Uniform %11 +%370 = OpTypePointer StorageBuffer %15 +%371 = OpTypePointer StorageBuffer %14 +%372 = OpTypePointer Uniform %6 +%379 = OpTypePointer Uniform %8 +%400 = OpTypePointer StorageBuffer %17 +%401 = OpTypePointer StorageBuffer %8 +%422 = OpTypePointer Input %8 +%421 = OpVariable %422 Input +%425 = OpTypePointer Output %8 +%424 = OpVariable %425 Output +%427 = OpTypePointer Output %7 +%426 = OpVariable %427 Output +%429 = OpTypePointer Output %6 +%428 = OpVariable %429 Output +%431 = OpTypePointer Uniform %20 +%433 = OpConstant %4 -1.0 +%434 = OpConstantComposite %6 %433 %433 +%449 = OpTypePointer Uniform %8 +%470 = OpVariable %422 Input +%473 = OpTypePointer Input %7 +%472 = OpVariable %473 Input +%476 = OpTypePointer Input %6 +%475 = OpVariable %476 Input +%478 = OpVariable %425 Output +%479 = OpVariable %425 Output +%482 = OpConstant %4 6.0 +%565 = OpTypePointer Input %5 +%564 = OpVariable %565 Input +%567 = OpVariable %565 Input +%569 = OpVariable %427 Output +%571 = OpTypePointer Output %5 +%570 = OpVariable %571 Output +%572 = OpVariable %571 Output +%574 = OpTypePointer Uniform %24 +%577 = OpTypePointer Uniform %23 +%591 = OpVariable %473 Input +%593 = OpVariable %565 Input +%595 = OpVariable %565 Input +%597 = OpVariable %427 Output +%600 = OpTypePointer Uniform %25 +%602 = OpConstantComposite %5 %272 %272 %272 +%603 = OpConstant %4 0.7 +%604 = OpConstantComposite %5 %78 %272 %603 +%605 = OpConstant %4 0.2 +%606 = OpConstantComposite %5 %605 %605 %605 +%608 = OpConstantNull %5 +%623 = OpTypePointer Uniform %5 +%632 = OpTypePointer Uniform %7 %53 = OpFunction %5 None %54 %52 = OpFunctionParameter %5 %51 = OpLabel @@ -981,480 +988,498 @@ OpLine %3 96 12 %298 = OpCompositeConstruct %14 %279 %297 OpReturnValue %298 OpFunctionEnd -%303 = OpFunction %6 None %304 -%300 = OpFunctionParameter %8 -%301 = OpFunctionParameter %10 -%302 = OpFunctionParameter %11 -%299 = OpLabel -OpBranch %305 -%305 = OpLabel +%299 = OpFunction %8 None %300 +%301 = OpFunctionParameter %8 +%302 = OpFunctionParameter %8 +%303 = OpLabel +%304 = OpIEqual %112 %302 %135 +%305 = OpSelect %8 %304 %126 %302 +%306 = OpUDiv %8 %301 %305 +OpReturnValue %306 +OpFunctionEnd +%311 = OpFunction %6 None %312 +%308 = OpFunctionParameter %8 +%309 = OpFunctionParameter %10 +%310 = OpFunctionParameter %11 +%307 = OpLabel +OpBranch %313 +%313 = OpLabel OpLine %3 101 9 -%306 = OpConvertUToF %4 %300 -%307 = OpCompositeExtract %8 %301 0 +%314 = OpConvertUToF %4 %308 +%315 = OpCompositeExtract %8 %309 0 OpLine %3 101 9 -%308 = OpIAdd %8 %307 %126 -%309 = OpConvertUToF %4 %308 -%310 = OpFRem %4 %306 %309 -%311 = OpCompositeExtract %8 %301 0 +%316 = OpIAdd %8 %315 %126 +%317 = OpConvertUToF %4 %316 +%318 = OpFRem %4 %314 %317 +%319 = OpCompositeExtract %8 %309 0 OpLine %3 100 12 -%312 = OpIAdd %8 %311 %126 -%313 = OpUDiv %8 %300 %312 -%314 = OpConvertUToF %4 %313 -%315 = OpCompositeConstruct %6 %310 %314 -%316 = OpConvertSToF %6 %302 -%317 = OpFAdd %6 %315 %316 -OpReturnValue %317 +%320 = OpIAdd %8 %319 %126 +%321 = OpFunctionCall %8 %299 %308 %320 +%322 = OpConvertUToF %4 %321 +%323 = OpCompositeConstruct %6 %318 %322 +%324 = OpConvertSToF %6 %310 +%325 = OpFAdd %6 %323 %324 +OpReturnValue %325 OpFunctionEnd -%320 = OpFunction %5 None %321 -%319 = OpFunctionParameter %6 -%318 = OpLabel -OpBranch %328 -%328 = OpLabel +%328 = OpFunction %5 None %329 +%327 = OpFunctionParameter %6 +%326 = OpLabel +OpBranch %336 +%336 = OpLabel OpLine %3 270 9 -%329 = OpFunctionCall %4 %67 %319 +%337 = OpFunctionCall %4 %67 %327 OpLine %3 270 9 -%330 = OpFMul %4 %329 %78 +%338 = OpFMul %4 %337 %78 OpLine %3 270 9 -%331 = OpFAdd %4 %330 %78 +%339 = OpFAdd %4 %338 %78 OpLine %3 271 17 -%332 = OpFAdd %6 %319 %324 +%340 = OpFAdd %6 %327 %332 OpLine %3 271 9 -%333 = OpFunctionCall %4 %67 %332 +%341 = OpFunctionCall %4 %67 %340 OpLine %3 271 9 -%334 = OpFMul %4 %333 %78 +%342 = OpFMul %4 %341 %78 OpLine %3 271 9 -%335 = OpFAdd %4 %334 %78 +%343 = OpFAdd %4 %342 %78 OpLine %3 272 17 -%336 = OpFAdd %6 %319 %327 +%344 = OpFAdd %6 %327 %335 OpLine %3 272 9 -%337 = OpFunctionCall %4 %67 %336 +%345 = OpFunctionCall %4 %67 %344 OpLine %3 272 9 -%338 = OpFMul %4 %337 %78 +%346 = OpFMul %4 %345 %78 OpLine %3 269 12 -%339 = OpFAdd %4 %338 %78 -%340 = OpCompositeConstruct %5 %331 %335 %339 -OpReturnValue %340 +%347 = OpFAdd %4 %346 %78 +%348 = OpCompositeConstruct %5 %339 %343 %347 +OpReturnValue %348 OpFunctionEnd -%345 = OpFunction %2 None %346 -%341 = OpLabel -%344 = OpLoad %19 %342 -%348 = OpAccessChain %347 %29 %135 -OpBranch %353 -%353 = OpLabel +%353 = OpFunction %2 None %354 +%349 = OpLabel +%352 = OpLoad %19 %350 +%356 = OpAccessChain %355 %29 %135 +OpBranch %361 +%361 = OpLabel OpLine %3 111 22 -%354 = OpCompositeExtract %8 %344 0 +%362 = OpCompositeExtract %8 %352 0 OpLine %3 113 36 -%356 = OpAccessChain %355 %348 %135 -%357 = OpLoad %10 %356 +%364 = OpAccessChain %363 %356 %135 +%365 = OpLoad %10 %364 OpLine %3 113 59 -%359 = OpAccessChain %358 %348 %126 -%360 = OpLoad %11 %359 +%367 = OpAccessChain %366 %356 %126 +%368 = OpLoad %11 %367 OpLine %3 113 13 -%361 = OpFunctionCall %6 %303 %354 %357 %360 +%369 = OpFunctionCall %6 %311 %362 %365 %368 OpLine %3 115 5 OpLine %3 115 51 -%365 = OpAccessChain %364 %348 %350 -%366 = OpLoad %6 %365 +%373 = OpAccessChain %372 %356 %358 +%374 = OpLoad %6 %373 OpLine %3 115 33 -%367 = OpFunctionCall %14 %270 %361 %366 +%375 = OpFunctionCall %14 %270 %369 %374 OpLine %3 115 5 -%368 = OpAccessChain %363 %32 %135 %354 -OpStore %368 %367 +%376 = OpAccessChain %371 %32 %135 %362 +OpStore %376 %375 OpLine %3 118 23 -%369 = OpCompositeExtract %8 %344 0 +%377 = OpCompositeExtract %8 %352 0 OpLine %3 118 23 -%370 = OpIMul %8 %369 %349 +%378 = OpIMul %8 %377 %357 OpLine %3 120 25 -%372 = OpAccessChain %371 %348 %135 %135 -%373 = OpLoad %8 %372 +%380 = OpAccessChain %379 %356 %135 %135 +%381 = OpLoad %8 %380 OpLine %3 120 25 -%374 = OpAccessChain %371 %348 %135 %126 -%375 = OpLoad %8 %374 -%376 = OpIMul %8 %373 %375 +%382 = OpAccessChain %379 %356 %135 %126 +%383 = OpLoad %8 %382 +%384 = OpIMul %8 %381 %383 OpLine %3 120 9 -%377 = OpIMul %8 %376 %349 -%378 = OpUGreaterThanEqual %112 %370 %377 +%385 = OpIMul %8 %384 %357 +%386 = OpUGreaterThanEqual %112 %378 %385 OpLine %3 120 5 -OpSelectionMerge %379 None -OpBranchConditional %378 %380 %379 -%380 = OpLabel +OpSelectionMerge %387 None +OpBranchConditional %386 %388 %387 +%388 = OpLabel OpReturn -%379 = OpLabel +%387 = OpLabel OpLine %3 122 28 -%381 = OpCompositeExtract %8 %344 0 +%389 = OpCompositeExtract %8 %352 0 OpLine %3 122 15 -%382 = OpAccessChain %371 %348 %135 %135 -%383 = OpLoad %8 %382 -%384 = OpUDiv %8 %381 %383 -%385 = OpIAdd %8 %354 %384 +%390 = OpAccessChain %379 %356 %135 %135 +%391 = OpLoad %8 %390 +%392 = OpFunctionCall %8 %299 %389 %391 +%393 = OpIAdd %8 %362 %392 OpLine %3 123 15 -%386 = OpIAdd %8 %385 %126 +%394 = OpIAdd %8 %393 %126 OpLine %3 124 15 -%387 = OpAccessChain %371 %348 %135 %135 -%388 = OpLoad %8 %387 -%389 = OpIAdd %8 %385 %388 +%395 = OpAccessChain %379 %356 %135 %135 +%396 = OpLoad %8 %395 +%397 = OpIAdd %8 %393 %396 OpLine %3 124 15 -%390 = OpIAdd %8 %389 %126 +%398 = OpIAdd %8 %397 %126 OpLine %3 125 15 -%391 = OpIAdd %8 %390 %126 +%399 = OpIAdd %8 %398 %126 OpLine %3 127 5 OpLine %3 127 5 -%394 = OpAccessChain %393 %34 %135 %370 -OpStore %394 %385 +%402 = OpAccessChain %401 %34 %135 %378 +OpStore %402 %393 OpLine %3 128 5 OpLine %3 128 5 -%395 = OpIAdd %8 %370 %126 +%403 = OpIAdd %8 %378 %126 OpLine %3 128 5 -%396 = OpAccessChain %393 %34 %135 %395 -OpStore %396 %390 +%404 = OpAccessChain %401 %34 %135 %403 +OpStore %404 %398 OpLine %3 129 5 OpLine %3 129 5 -%397 = OpIAdd %8 %370 %350 +%405 = OpIAdd %8 %378 %358 OpLine %3 129 5 -%398 = OpAccessChain %393 %34 %135 %397 -OpStore %398 %391 +%406 = OpAccessChain %401 %34 %135 %405 +OpStore %406 %399 OpLine %3 130 5 OpLine %3 130 5 -%399 = OpIAdd %8 %370 %351 +%407 = OpIAdd %8 %378 %359 OpLine %3 130 5 -%400 = OpAccessChain %393 %34 %135 %399 -OpStore %400 %385 +%408 = OpAccessChain %401 %34 %135 %407 +OpStore %408 %393 OpLine %3 131 5 OpLine %3 131 5 -%401 = OpIAdd %8 %370 %352 +%409 = OpIAdd %8 %378 %360 OpLine %3 131 5 -%402 = OpAccessChain %393 %34 %135 %401 -OpStore %402 %391 +%410 = OpAccessChain %401 %34 %135 %409 +OpStore %410 %399 OpLine %3 132 5 OpLine %3 132 5 -%403 = OpIAdd %8 %370 %205 +%411 = OpIAdd %8 %378 %205 OpLine %3 132 5 -%404 = OpAccessChain %393 %34 %135 %403 -OpStore %404 %386 +%412 = OpAccessChain %401 %34 %135 %411 +OpStore %412 %394 OpReturn OpFunctionEnd -%415 = OpFunction %2 None %346 -%405 = OpLabel -%408 = OpLoad %8 %406 -%417 = OpAccessChain %416 %36 %135 -OpBranch %420 +%413 = OpFunction %8 None %300 +%414 = OpFunctionParameter %8 +%415 = OpFunctionParameter %8 +%416 = OpLabel +%417 = OpIEqual %112 %415 %135 +%418 = OpSelect %8 %417 %126 %415 +%419 = OpUMod %8 %414 %418 +OpReturnValue %419 +OpFunctionEnd +%430 = OpFunction %2 None %354 %420 = OpLabel +%423 = OpLoad %8 %421 +%432 = OpAccessChain %431 %36 %135 +OpBranch %435 +%435 = OpLabel OpLine %3 161 19 -%421 = OpIAdd %8 %408 %350 +%436 = OpIAdd %8 %423 %358 OpLine %3 161 18 -%422 = OpUDiv %8 %421 %351 +%437 = OpFunctionCall %8 %299 %436 %359 OpLine %3 161 13 -%423 = OpUMod %8 %422 %350 -%424 = OpConvertUToF %4 %423 +%438 = OpFunctionCall %8 %413 %437 %358 +%439 = OpConvertUToF %4 %438 OpLine %3 162 19 -%425 = OpIAdd %8 %408 %126 +%440 = OpIAdd %8 %423 %126 OpLine %3 162 18 -%426 = OpUDiv %8 %425 %351 +%441 = OpFunctionCall %8 %299 %440 %359 OpLine %3 162 13 -%427 = OpUMod %8 %426 %350 -%428 = OpConvertUToF %4 %427 +%442 = OpFunctionCall %8 %413 %441 %358 +%443 = OpConvertUToF %4 %442 OpLine %3 163 14 -%429 = OpCompositeConstruct %6 %424 %428 +%444 = OpCompositeConstruct %6 %439 %443 OpLine %3 165 30 -%430 = OpVectorTimesScalar %6 %429 %81 +%445 = OpVectorTimesScalar %6 %444 %81 OpLine %3 165 30 -%431 = OpFAdd %6 %419 %430 +%446 = OpFAdd %6 %434 %445 OpLine %3 165 20 -%432 = OpCompositeConstruct %7 %431 %74 %56 +%447 = OpCompositeConstruct %7 %446 %74 %56 OpLine %3 168 21 -%433 = OpCompositeExtract %4 %429 0 +%448 = OpCompositeExtract %4 %444 0 OpLine %3 168 21 -%435 = OpAccessChain %434 %417 %351 -%436 = OpLoad %8 %435 -%437 = OpConvertUToF %4 %436 -%438 = OpFMul %4 %433 %437 -%439 = OpCompositeExtract %4 %429 1 +%450 = OpAccessChain %449 %432 %359 +%451 = OpLoad %8 %450 +%452 = OpConvertUToF %4 %451 +%453 = OpFMul %4 %448 %452 +%454 = OpCompositeExtract %4 %444 1 OpLine %3 168 17 -%440 = OpAccessChain %434 %417 %351 -%441 = OpLoad %8 %440 -%442 = OpConvertUToF %4 %441 -%443 = OpFMul %4 %439 %442 -%444 = OpFAdd %4 %438 %443 -%445 = OpConvertFToU %8 %444 +%455 = OpAccessChain %449 %432 %359 +%456 = OpLoad %8 %455 +%457 = OpConvertUToF %4 %456 +%458 = OpFMul %4 %454 %457 +%459 = OpFAdd %4 %453 %458 +%460 = OpConvertFToU %8 %459 OpLine %3 168 17 -%446 = OpAccessChain %434 %417 %352 -%447 = OpLoad %8 %446 -%448 = OpIAdd %8 %445 %447 +%461 = OpAccessChain %449 %432 %360 +%462 = OpLoad %8 %461 +%463 = OpIAdd %8 %460 %462 OpLine %3 170 12 -%449 = OpCompositeConstruct %21 %448 %432 %429 -%450 = OpCompositeExtract %8 %449 0 -OpStore %409 %450 -%451 = OpCompositeExtract %7 %449 1 -OpStore %411 %451 -%452 = OpCompositeExtract %6 %449 2 -OpStore %413 %452 +%464 = OpCompositeConstruct %21 %463 %447 %444 +%465 = OpCompositeExtract %8 %464 0 +OpStore %424 %465 +%466 = OpCompositeExtract %7 %464 1 +OpStore %426 %466 +%467 = OpCompositeExtract %6 %464 2 +OpStore %428 %467 OpReturn OpFunctionEnd -%465 = OpFunction %2 None %346 -%453 = OpLabel -%468 = OpVariable %215 Function %74 -%469 = OpVariable %218 Function %135 -%456 = OpLoad %8 %455 -%459 = OpLoad %7 %457 -%462 = OpLoad %6 %460 -%454 = OpCompositeConstruct %21 %456 %459 %462 -%466 = OpAccessChain %416 %36 %135 -OpBranch %470 -%470 = OpLabel +%480 = OpFunction %2 None %354 +%468 = OpLabel +%483 = OpVariable %215 Function %74 +%484 = OpVariable %218 Function %135 +%471 = OpLoad %8 %470 +%474 = OpLoad %7 %472 +%477 = OpLoad %6 %475 +%469 = OpCompositeConstruct %21 %471 %474 %477 +%481 = OpAccessChain %431 %36 %135 +OpBranch %485 +%485 = OpLabel OpLine %3 181 17 -%471 = OpCompositeExtract %6 %454 2 -%472 = OpCompositeExtract %4 %471 0 +%486 = OpCompositeExtract %6 %469 2 +%487 = OpCompositeExtract %4 %486 0 OpLine %3 181 17 -%473 = OpAccessChain %434 %466 %351 -%474 = OpLoad %8 %473 -%475 = OpConvertUToF %4 %474 -%476 = OpFMul %4 %472 %475 -%477 = OpCompositeExtract %6 %454 2 -%478 = OpCompositeExtract %4 %477 1 +%488 = OpAccessChain %449 %481 %359 +%489 = OpLoad %8 %488 +%490 = OpConvertUToF %4 %489 +%491 = OpFMul %4 %487 %490 +%492 = OpCompositeExtract %6 %469 2 +%493 = OpCompositeExtract %4 %492 1 OpLine %3 181 70 -%479 = OpAccessChain %434 %466 %351 -%480 = OpLoad %8 %479 +%494 = OpAccessChain %449 %481 %359 +%495 = OpLoad %8 %494 OpLine %3 181 13 -%481 = OpAccessChain %434 %466 %351 -%482 = OpLoad %8 %481 -%483 = OpIMul %8 %480 %482 -%484 = OpConvertUToF %4 %483 -%485 = OpFMul %4 %478 %484 -%486 = OpFAdd %4 %476 %485 -%487 = OpConvertFToU %8 %486 +%496 = OpAccessChain %449 %481 %359 +%497 = OpLoad %8 %496 +%498 = OpIMul %8 %495 %497 +%499 = OpConvertUToF %4 %498 +%500 = OpFMul %4 %493 %499 +%501 = OpFAdd %4 %491 %500 +%502 = OpConvertFToU %8 %501 OpLine %3 181 13 -%488 = OpAccessChain %434 %466 %352 -%489 = OpLoad %8 %488 -%490 = OpIAdd %8 %487 %489 +%503 = OpAccessChain %449 %481 %360 +%504 = OpLoad %8 %503 +%505 = OpIAdd %8 %502 %504 OpLine %3 182 32 -%491 = OpConvertUToF %4 %490 +%506 = OpConvertUToF %4 %505 OpLine %3 182 22 -%492 = OpFDiv %4 %491 %467 -%493 = OpExtInst %4 %1 Floor %492 -%494 = OpConvertFToU %8 %493 +%507 = OpFDiv %4 %506 %482 +%508 = OpExtInst %4 %1 Floor %507 +%509 = OpConvertFToU %8 %508 OpLine %3 183 22 -%495 = OpUMod %8 %490 %349 +%510 = OpFunctionCall %8 %413 %505 %357 OpLine %3 185 36 -%496 = OpAccessChain %355 %466 %135 -%497 = OpLoad %10 %496 +%511 = OpAccessChain %363 %481 %135 +%512 = OpLoad %10 %511 OpLine %3 185 57 -%498 = OpAccessChain %358 %466 %126 -%499 = OpLoad %11 %498 +%513 = OpAccessChain %366 %481 %126 +%514 = OpLoad %11 %513 OpLine %3 185 13 -%500 = OpFunctionCall %6 %303 %494 %497 %499 +%515 = OpFunctionCall %6 %311 %509 %512 %514 OpLine %3 186 31 -%501 = OpAccessChain %364 %466 %350 -%502 = OpLoad %6 %501 +%516 = OpAccessChain %372 %481 %358 +%517 = OpLoad %6 %516 OpLine %3 186 13 -%503 = OpFunctionCall %14 %270 %500 %502 +%518 = OpFunctionCall %14 %270 %515 %517 OpLine %3 190 5 -OpSelectionMerge %504 None -OpSwitch %495 %511 0 %505 1 %506 2 %507 3 %508 4 %509 5 %510 -%505 = OpLabel +OpSelectionMerge %519 None +OpSwitch %510 %526 0 %520 1 %521 2 %522 3 %523 4 %524 5 %525 +%520 = OpLabel OpLine %3 191 37 -%512 = OpCompositeExtract %5 %503 0 -%513 = OpCompositeExtract %4 %512 0 +%527 = OpCompositeExtract %5 %518 0 +%528 = OpCompositeExtract %4 %527 0 OpLine %3 191 20 -OpStore %468 %513 -OpBranch %504 -%506 = OpLabel +OpStore %483 %528 +OpBranch %519 +%521 = OpLabel OpLine %3 192 37 -%514 = OpCompositeExtract %5 %503 0 -%515 = OpCompositeExtract %4 %514 1 +%529 = OpCompositeExtract %5 %518 0 +%530 = OpCompositeExtract %4 %529 1 OpLine %3 192 20 -OpStore %468 %515 -OpBranch %504 -%507 = OpLabel +OpStore %483 %530 +OpBranch %519 +%522 = OpLabel OpLine %3 193 37 -%516 = OpCompositeExtract %5 %503 0 -%517 = OpCompositeExtract %4 %516 2 +%531 = OpCompositeExtract %5 %518 0 +%532 = OpCompositeExtract %4 %531 2 OpLine %3 193 20 -OpStore %468 %517 -OpBranch %504 -%508 = OpLabel +OpStore %483 %532 +OpBranch %519 +%523 = OpLabel OpLine %3 194 37 -%518 = OpCompositeExtract %5 %503 1 -%519 = OpCompositeExtract %4 %518 0 +%533 = OpCompositeExtract %5 %518 1 +%534 = OpCompositeExtract %4 %533 0 OpLine %3 194 20 -OpStore %468 %519 -OpBranch %504 -%509 = OpLabel +OpStore %483 %534 +OpBranch %519 +%524 = OpLabel OpLine %3 195 37 -%520 = OpCompositeExtract %5 %503 1 -%521 = OpCompositeExtract %4 %520 1 +%535 = OpCompositeExtract %5 %518 1 +%536 = OpCompositeExtract %4 %535 1 OpLine %3 195 20 -OpStore %468 %521 -OpBranch %504 -%510 = OpLabel +OpStore %483 %536 +OpBranch %519 +%525 = OpLabel OpLine %3 196 37 -%522 = OpCompositeExtract %5 %503 1 -%523 = OpCompositeExtract %4 %522 2 +%537 = OpCompositeExtract %5 %518 1 +%538 = OpCompositeExtract %4 %537 2 OpLine %3 196 20 -OpStore %468 %523 -OpBranch %504 -%511 = OpLabel -OpBranch %504 -%504 = OpLabel +OpStore %483 %538 +OpBranch %519 +%526 = OpLabel +OpBranch %519 +%519 = OpLabel OpLine %3 200 15 -%524 = OpAccessChain %371 %466 %135 %135 -%525 = OpLoad %8 %524 -%526 = OpUDiv %8 %494 %525 -%527 = OpIAdd %8 %494 %526 +%539 = OpAccessChain %379 %481 %135 %135 +%540 = OpLoad %8 %539 +%541 = OpFunctionCall %8 %299 %509 %540 +%542 = OpIAdd %8 %509 %541 OpLine %3 201 15 -%528 = OpIAdd %8 %527 %126 +%543 = OpIAdd %8 %542 %126 OpLine %3 202 15 -%529 = OpAccessChain %371 %466 %135 %135 -%530 = OpLoad %8 %529 -%531 = OpIAdd %8 %527 %530 +%544 = OpAccessChain %379 %481 %135 %135 +%545 = OpLoad %8 %544 +%546 = OpIAdd %8 %542 %545 OpLine %3 202 15 -%532 = OpIAdd %8 %531 %126 +%547 = OpIAdd %8 %546 %126 OpLine %3 203 15 -%533 = OpIAdd %8 %532 %126 +%548 = OpIAdd %8 %547 %126 OpLine %3 206 5 -OpSelectionMerge %534 None -OpSwitch %495 %539 0 %535 3 %535 2 %536 4 %536 1 %537 5 %538 -%535 = OpLabel +OpSelectionMerge %549 None +OpSwitch %510 %554 0 %550 3 %550 2 %551 4 %551 1 %552 5 %553 +%550 = OpLabel OpLine %3 207 24 -OpStore %469 %527 -OpBranch %534 -%536 = OpLabel +OpStore %484 %542 +OpBranch %549 +%551 = OpLabel OpLine %3 208 24 -OpStore %469 %533 -OpBranch %534 -%537 = OpLabel +OpStore %484 %548 +OpBranch %549 +%552 = OpLabel OpLine %3 209 20 -OpStore %469 %532 -OpBranch %534 -%538 = OpLabel +OpStore %484 %547 +OpBranch %549 +%553 = OpLabel OpLine %3 210 20 -OpStore %469 %528 -OpBranch %534 -%539 = OpLabel -OpBranch %534 -%534 = OpLabel +OpStore %484 %543 +OpBranch %549 +%554 = OpLabel +OpBranch %549 +%549 = OpLabel OpLine %3 213 13 -%540 = OpCompositeExtract %8 %454 0 +%555 = OpCompositeExtract %8 %469 0 OpLine %3 213 5 -OpStore %469 %540 +OpStore %484 %555 OpLine %3 222 27 -%541 = OpLoad %4 %468 -%542 = OpBitcast %8 %541 +%556 = OpLoad %4 %483 +%557 = OpBitcast %8 %556 OpLine %3 223 12 -%543 = OpLoad %8 %469 -%544 = OpCompositeConstruct %22 %542 %543 -%545 = OpCompositeExtract %8 %544 0 -OpStore %463 %545 -%546 = OpCompositeExtract %8 %544 1 -OpStore %464 %546 +%558 = OpLoad %8 %484 +%559 = OpCompositeConstruct %22 %557 %558 +%560 = OpCompositeExtract %8 %559 0 +OpStore %478 %560 +%561 = OpCompositeExtract %8 %559 1 +OpStore %479 %561 OpReturn OpFunctionEnd -%558 = OpFunction %2 None %346 -%547 = OpLabel -%551 = OpLoad %5 %549 -%553 = OpLoad %5 %552 -%548 = OpCompositeConstruct %14 %551 %553 -%560 = OpAccessChain %559 %39 %135 -OpBranch %561 -%561 = OpLabel +%573 = OpFunction %2 None %354 +%562 = OpLabel +%566 = OpLoad %5 %564 +%568 = OpLoad %5 %567 +%563 = OpCompositeConstruct %14 %566 %568 +%575 = OpAccessChain %574 %39 %135 +OpBranch %576 +%576 = OpLabel OpLine %3 254 25 -%563 = OpAccessChain %562 %560 %126 -%564 = OpLoad %23 %563 -%565 = OpCompositeExtract %5 %548 0 +%578 = OpAccessChain %577 %575 %126 +%579 = OpLoad %23 %578 +%580 = OpCompositeExtract %5 %563 0 OpLine %3 254 25 -%566 = OpCompositeConstruct %7 %565 %56 -%567 = OpMatrixTimesVector %7 %564 %566 +%581 = OpCompositeConstruct %7 %580 %56 +%582 = OpMatrixTimesVector %7 %579 %581 OpLine %3 255 18 -%568 = OpCompositeExtract %5 %548 1 +%583 = OpCompositeExtract %5 %563 1 OpLine %3 256 12 -%569 = OpCompositeExtract %5 %548 0 -%570 = OpCompositeConstruct %26 %567 %568 %569 -%571 = OpCompositeExtract %7 %570 0 -OpStore %554 %571 -%572 = OpCompositeExtract %5 %570 1 -OpStore %555 %572 -%573 = OpCompositeExtract %5 %570 2 -OpStore %557 %573 +%584 = OpCompositeExtract %5 %563 0 +%585 = OpCompositeConstruct %26 %582 %583 %584 +%586 = OpCompositeExtract %7 %585 0 +OpStore %569 %586 +%587 = OpCompositeExtract %5 %585 1 +OpStore %570 %587 +%588 = OpCompositeExtract %5 %585 2 +OpStore %572 %588 OpReturn OpFunctionEnd -%583 = OpFunction %2 None %346 -%574 = OpLabel -%592 = OpVariable %95 Function %593 -%577 = OpLoad %7 %576 -%579 = OpLoad %5 %578 -%581 = OpLoad %5 %580 -%575 = OpCompositeConstruct %26 %577 %579 %581 -%584 = OpAccessChain %559 %39 %135 -%586 = OpAccessChain %585 %42 %135 -OpBranch %594 -%594 = OpLabel +%598 = OpFunction %2 None %354 +%589 = OpLabel +%607 = OpVariable %95 Function %608 +%592 = OpLoad %7 %591 +%594 = OpLoad %5 %593 +%596 = OpLoad %5 %595 +%590 = OpCompositeConstruct %26 %592 %594 %596 +%599 = OpAccessChain %574 %39 %135 +%601 = OpAccessChain %600 %42 %135 +OpBranch %609 +%609 = OpLabel OpLine %3 278 28 OpLine %3 278 17 -%595 = OpCompositeExtract %5 %575 2 -%596 = OpExtInst %5 %1 Fract %595 -%597 = OpExtInst %5 %1 SmoothStep %80 %587 %596 +%610 = OpCompositeExtract %5 %590 2 +%611 = OpExtInst %5 %1 Fract %610 +%612 = OpExtInst %5 %1 SmoothStep %80 %602 %611 OpLine %3 278 5 -OpStore %592 %597 +OpStore %607 %612 OpLine %3 279 17 OpLine %3 279 13 -%598 = OpAccessChain %125 %592 %135 -%599 = OpLoad %4 %598 -%600 = OpAccessChain %125 %592 %126 -%601 = OpLoad %4 %600 -%602 = OpFMul %4 %599 %601 -%603 = OpAccessChain %125 %592 %350 -%604 = OpLoad %4 %603 -%605 = OpFMul %4 %602 %604 -%606 = OpCompositeConstruct %5 %605 %605 %605 -%607 = OpExtInst %5 %1 FMix %589 %591 %606 +%613 = OpAccessChain %125 %607 %135 +%614 = OpLoad %4 %613 +%615 = OpAccessChain %125 %607 %126 +%616 = OpLoad %4 %615 +%617 = OpFMul %4 %614 %616 +%618 = OpAccessChain %125 %607 %358 +%619 = OpLoad %4 %618 +%620 = OpFMul %4 %617 %619 +%621 = OpCompositeConstruct %5 %620 %620 %620 +%622 = OpExtInst %5 %1 FMix %604 %606 %621 OpLine %3 279 5 -OpStore %592 %607 +OpStore %607 %622 OpLine %3 282 25 -%609 = OpAccessChain %608 %586 %126 -%610 = OpLoad %5 %609 -%611 = OpVectorTimesScalar %5 %610 %272 +%624 = OpAccessChain %623 %601 %126 +%625 = OpLoad %5 %624 +%626 = OpVectorTimesScalar %5 %625 %272 OpLine %3 284 21 -%612 = OpAccessChain %608 %586 %135 -%613 = OpLoad %5 %612 -%614 = OpCompositeExtract %5 %575 2 -%615 = OpFSub %5 %613 %614 -%616 = OpExtInst %5 %1 Normalize %615 +%627 = OpAccessChain %623 %601 %135 +%628 = OpLoad %5 %627 +%629 = OpCompositeExtract %5 %590 2 +%630 = OpFSub %5 %628 %629 +%631 = OpExtInst %5 %1 Normalize %630 OpLine %3 285 20 -%618 = OpAccessChain %617 %584 %135 -%619 = OpLoad %7 %618 -%620 = OpVectorShuffle %5 %619 %619 0 1 2 -%621 = OpCompositeExtract %5 %575 2 -%622 = OpFSub %5 %620 %621 -%623 = OpExtInst %5 %1 Normalize %622 +%633 = OpAccessChain %632 %599 %135 +%634 = OpLoad %7 %633 +%635 = OpVectorShuffle %5 %634 %634 0 1 2 +%636 = OpCompositeExtract %5 %590 2 +%637 = OpFSub %5 %635 %636 +%638 = OpExtInst %5 %1 Normalize %637 OpLine %3 286 20 -%624 = OpFAdd %5 %623 %616 -%625 = OpExtInst %5 %1 Normalize %624 +%639 = OpFAdd %5 %638 %631 +%640 = OpExtInst %5 %1 Normalize %639 OpLine %3 288 32 -%626 = OpCompositeExtract %5 %575 1 -%627 = OpDot %4 %626 %616 +%641 = OpCompositeExtract %5 %590 1 +%642 = OpDot %4 %641 %631 OpLine %3 288 28 -%628 = OpExtInst %4 %1 FMax %627 %74 +%643 = OpExtInst %4 %1 FMax %642 %74 OpLine %3 289 25 -%629 = OpAccessChain %608 %586 %126 -%630 = OpLoad %5 %629 -%631 = OpVectorTimesScalar %5 %630 %628 +%644 = OpAccessChain %623 %601 %126 +%645 = OpLoad %5 %644 +%646 = OpVectorTimesScalar %5 %645 %643 OpLine %3 291 37 -%632 = OpCompositeExtract %5 %575 1 -%633 = OpDot %4 %632 %625 +%647 = OpCompositeExtract %5 %590 1 +%648 = OpDot %4 %647 %640 OpLine %3 291 33 -%634 = OpExtInst %4 %1 FMax %633 %74 +%649 = OpExtInst %4 %1 FMax %648 %74 OpLine %3 291 29 -%635 = OpExtInst %4 %1 Pow %634 %323 +%650 = OpExtInst %4 %1 Pow %649 %331 OpLine %3 292 26 -%636 = OpAccessChain %608 %586 %126 -%637 = OpLoad %5 %636 -%638 = OpVectorTimesScalar %5 %637 %635 +%651 = OpAccessChain %623 %601 %126 +%652 = OpLoad %5 %651 +%653 = OpVectorTimesScalar %5 %652 %650 OpLine %3 294 18 -%639 = OpFAdd %5 %611 %631 -%640 = OpFAdd %5 %639 %638 -%641 = OpLoad %5 %592 -%642 = OpFMul %5 %640 %641 +%654 = OpFAdd %5 %626 %646 +%655 = OpFAdd %5 %654 %653 +%656 = OpLoad %5 %607 +%657 = OpFMul %5 %655 %656 OpLine %3 296 12 -%643 = OpCompositeConstruct %7 %642 %56 -OpStore %582 %643 +%658 = OpCompositeConstruct %7 %657 %56 +OpStore %597 %658 OpReturn OpFunctionEnd \ No newline at end of file diff --git a/naga/tests/out/spv/image.spvasm b/naga/tests/out/spv/image.spvasm index 5ec2925dc6..7a34bed86e 100644 --- a/naga/tests/out/spv/image.spvasm +++ b/naga/tests/out/spv/image.spvasm @@ -1,7 +1,7 @@ ; SPIR-V ; Version: 1.1 ; Generator: rspirv -; Bound: 526 +; Bound: 546 OpCapability Shader OpCapability Image1D OpCapability Sampled1D @@ -9,20 +9,20 @@ OpCapability SampledCubeArray OpCapability ImageQuery %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %78 "main" %75 -OpEntryPoint GLCompute %169 "depth_load" %167 -OpEntryPoint Vertex %189 "queries" %187 -OpEntryPoint Vertex %241 "levels_queries" %240 -OpEntryPoint Fragment %272 "texture_sample" %271 -OpEntryPoint Fragment %419 "texture_sample_comparison" %417 -OpEntryPoint Fragment %475 "gather" %474 -OpEntryPoint Fragment %509 "depth_no_comparison" %508 -OpExecutionMode %78 LocalSize 16 1 1 -OpExecutionMode %169 LocalSize 16 1 1 -OpExecutionMode %272 OriginUpperLeft -OpExecutionMode %419 OriginUpperLeft -OpExecutionMode %475 OriginUpperLeft -OpExecutionMode %509 OriginUpperLeft +OpEntryPoint GLCompute %99 "main" %96 +OpEntryPoint GLCompute %190 "depth_load" %188 +OpEntryPoint Vertex %210 "queries" %208 +OpEntryPoint Vertex %262 "levels_queries" %261 +OpEntryPoint Fragment %293 "texture_sample" %292 +OpEntryPoint Fragment %439 "texture_sample_comparison" %437 +OpEntryPoint Fragment %495 "gather" %494 +OpEntryPoint Fragment %529 "depth_no_comparison" %528 +OpExecutionMode %99 LocalSize 16 1 1 +OpExecutionMode %190 LocalSize 16 1 1 +OpExecutionMode %293 OriginUpperLeft +OpExecutionMode %439 OriginUpperLeft +OpExecutionMode %495 OriginUpperLeft +OpExecutionMode %529 OriginUpperLeft OpName %31 "image_mipmapped_src" OpName %33 "image_multisampled_src" OpName %35 "image_depth_multisampled_src" @@ -45,18 +45,21 @@ OpName %66 "sampler_cmp" OpName %68 "image_2d_depth" OpName %70 "image_2d_array_depth" OpName %72 "image_cube_depth" -OpName %75 "local_id" -OpName %78 "main" -OpName %167 "local_id" -OpName %169 "depth_load" -OpName %189 "queries" -OpName %241 "levels_queries" -OpName %272 "texture_sample" -OpName %286 "a" -OpName %419 "texture_sample_comparison" -OpName %424 "a" -OpName %475 "gather" -OpName %509 "depth_no_comparison" +OpName %74 "naga_mod" +OpName %76 "lhs" +OpName %77 "rhs" +OpName %96 "local_id" +OpName %99 "main" +OpName %188 "local_id" +OpName %190 "depth_load" +OpName %210 "queries" +OpName %262 "levels_queries" +OpName %293 "texture_sample" +OpName %306 "a" +OpName %439 "texture_sample_comparison" +OpName %444 "a" +OpName %495 "gather" +OpName %529 "depth_no_comparison" OpDecorate %31 DescriptorSet 0 OpDecorate %31 Binding 0 OpDecorate %33 DescriptorSet 0 @@ -104,14 +107,14 @@ OpDecorate %70 DescriptorSet 1 OpDecorate %70 Binding 3 OpDecorate %72 DescriptorSet 1 OpDecorate %72 Binding 4 -OpDecorate %75 BuiltIn LocalInvocationId -OpDecorate %167 BuiltIn LocalInvocationId -OpDecorate %187 BuiltIn Position -OpDecorate %240 BuiltIn Position -OpDecorate %271 Location 0 -OpDecorate %417 Location 0 -OpDecorate %474 Location 0 -OpDecorate %508 Location 0 +OpDecorate %96 BuiltIn LocalInvocationId +OpDecorate %188 BuiltIn LocalInvocationId +OpDecorate %208 BuiltIn Position +OpDecorate %261 BuiltIn Position +OpDecorate %292 Location 0 +OpDecorate %437 Location 0 +OpDecorate %494 Location 0 +OpDecorate %528 Location 0 %2 = OpTypeVoid %4 = OpTypeInt 32 0 %3 = OpTypeImage %4 2D 0 0 0 1 Unknown @@ -184,517 +187,539 @@ OpDecorate %508 Location 0 %70 = OpVariable %71 UniformConstant %73 = OpTypePointer UniformConstant %27 %72 = OpVariable %73 UniformConstant -%76 = OpTypePointer Input %12 -%75 = OpVariable %76 Input -%79 = OpTypeFunction %2 -%86 = OpConstant %14 10 -%87 = OpConstant %14 20 -%88 = OpConstantComposite %13 %86 %87 -%90 = OpTypeVector %4 2 -%98 = OpTypeVector %4 4 -%109 = OpTypeVector %14 3 -%167 = OpVariable %76 Input -%188 = OpTypePointer Output %23 -%187 = OpVariable %188 Output -%198 = OpConstant %4 0 -%240 = OpVariable %188 Output -%271 = OpVariable %188 Output -%278 = OpConstant %7 0.5 -%279 = OpTypeVector %7 2 -%280 = OpConstantComposite %279 %278 %278 -%281 = OpTypeVector %7 3 -%282 = OpConstantComposite %281 %278 %278 %278 -%283 = OpConstant %7 2.3 -%284 = OpConstant %7 2.0 -%285 = OpConstant %14 0 -%287 = OpTypePointer Function %23 -%288 = OpConstantNull %23 -%291 = OpTypeSampledImage %15 -%296 = OpTypeSampledImage %16 -%317 = OpTypeSampledImage %18 -%378 = OpTypeSampledImage %20 -%418 = OpTypePointer Output %7 -%417 = OpVariable %418 Output -%425 = OpTypePointer Function %7 -%426 = OpConstantNull %7 -%428 = OpTypeSampledImage %25 -%433 = OpTypeSampledImage %26 -%446 = OpTypeSampledImage %27 -%453 = OpConstant %7 0.0 -%474 = OpVariable %188 Output -%485 = OpConstant %4 1 -%488 = OpConstant %4 3 -%493 = OpTypeSampledImage %3 -%496 = OpTypeVector %14 4 -%497 = OpTypeSampledImage %17 -%508 = OpVariable %188 Output -%78 = OpFunction %2 None %79 -%74 = OpLabel -%77 = OpLoad %12 %75 -%80 = OpLoad %3 %31 -%81 = OpLoad %5 %33 -%82 = OpLoad %8 %37 -%83 = OpLoad %9 %39 -%84 = OpLoad %11 %43 -%85 = OpLoad %10 %45 -OpBranch %89 -%89 = OpLabel -%91 = OpImageQuerySize %90 %82 -%92 = OpVectorShuffle %90 %77 %77 0 1 -%93 = OpIMul %90 %91 %92 -%94 = OpBitcast %13 %93 -%95 = OpSRem %13 %94 %88 -%96 = OpCompositeExtract %4 %77 2 -%97 = OpBitcast %14 %96 -%99 = OpImageFetch %98 %80 %95 Lod %97 -%100 = OpCompositeExtract %4 %77 2 -%101 = OpBitcast %14 %100 -%102 = OpImageFetch %98 %81 %95 Sample %101 -%103 = OpImageRead %98 %82 %95 -%104 = OpCompositeExtract %4 %77 2 -%105 = OpCompositeExtract %4 %77 2 -%106 = OpBitcast %14 %105 -%107 = OpIAdd %14 %106 %29 -%108 = OpBitcast %14 %104 -%110 = OpCompositeConstruct %109 %95 %108 -%111 = OpImageFetch %98 %83 %110 Lod %107 -%112 = OpCompositeExtract %4 %77 2 -%113 = OpBitcast %14 %112 -%114 = OpCompositeExtract %4 %77 2 -%115 = OpBitcast %14 %114 -%116 = OpIAdd %14 %115 %29 -%117 = OpCompositeConstruct %109 %95 %113 -%118 = OpImageFetch %98 %83 %117 Lod %116 -%119 = OpCompositeExtract %4 %77 0 -%120 = OpBitcast %14 %119 -%121 = OpCompositeExtract %4 %77 2 +%75 = OpTypeFunction %13 %13 %13 +%80 = OpTypeBool +%79 = OpTypeVector %80 2 +%81 = OpConstant %14 0 +%82 = OpConstantComposite %13 %81 %81 +%84 = OpConstant %14 -2147483648 +%85 = OpConstant %14 -1 +%86 = OpConstantComposite %13 %84 %84 +%87 = OpConstantComposite %13 %85 %85 +%92 = OpConstantComposite %13 %29 %29 +%97 = OpTypePointer Input %12 +%96 = OpVariable %97 Input +%100 = OpTypeFunction %2 +%107 = OpConstant %14 10 +%108 = OpConstant %14 20 +%109 = OpConstantComposite %13 %107 %108 +%111 = OpTypeVector %4 2 +%119 = OpTypeVector %4 4 +%130 = OpTypeVector %14 3 +%188 = OpVariable %97 Input +%209 = OpTypePointer Output %23 +%208 = OpVariable %209 Output +%219 = OpConstant %4 0 +%261 = OpVariable %209 Output +%292 = OpVariable %209 Output +%299 = OpConstant %7 0.5 +%300 = OpTypeVector %7 2 +%301 = OpConstantComposite %300 %299 %299 +%302 = OpTypeVector %7 3 +%303 = OpConstantComposite %302 %299 %299 %299 +%304 = OpConstant %7 2.3 +%305 = OpConstant %7 2.0 +%307 = OpTypePointer Function %23 +%308 = OpConstantNull %23 +%311 = OpTypeSampledImage %15 +%316 = OpTypeSampledImage %16 +%337 = OpTypeSampledImage %18 +%398 = OpTypeSampledImage %20 +%438 = OpTypePointer Output %7 +%437 = OpVariable %438 Output +%445 = OpTypePointer Function %7 +%446 = OpConstantNull %7 +%448 = OpTypeSampledImage %25 +%453 = OpTypeSampledImage %26 +%466 = OpTypeSampledImage %27 +%473 = OpConstant %7 0.0 +%494 = OpVariable %209 Output +%505 = OpConstant %4 1 +%508 = OpConstant %4 3 +%513 = OpTypeSampledImage %3 +%516 = OpTypeVector %14 4 +%517 = OpTypeSampledImage %17 +%528 = OpVariable %209 Output +%74 = OpFunction %13 None %75 +%76 = OpFunctionParameter %13 +%77 = OpFunctionParameter %13 +%78 = OpLabel +%83 = OpIEqual %79 %77 %82 +%88 = OpIEqual %79 %76 %86 +%89 = OpIEqual %79 %77 %87 +%90 = OpLogicalAnd %79 %88 %89 +%91 = OpLogicalOr %79 %83 %90 +%93 = OpSelect %13 %91 %92 %77 +%94 = OpSRem %13 %76 %93 +OpReturnValue %94 +OpFunctionEnd +%99 = OpFunction %2 None %100 +%95 = OpLabel +%98 = OpLoad %12 %96 +%101 = OpLoad %3 %31 +%102 = OpLoad %5 %33 +%103 = OpLoad %8 %37 +%104 = OpLoad %9 %39 +%105 = OpLoad %11 %43 +%106 = OpLoad %10 %45 +OpBranch %110 +%110 = OpLabel +%112 = OpImageQuerySize %111 %103 +%113 = OpVectorShuffle %111 %98 %98 0 1 +%114 = OpIMul %111 %112 %113 +%115 = OpBitcast %13 %114 +%116 = OpFunctionCall %13 %74 %115 %109 +%117 = OpCompositeExtract %4 %98 2 +%118 = OpBitcast %14 %117 +%120 = OpImageFetch %119 %101 %116 Lod %118 +%121 = OpCompositeExtract %4 %98 2 %122 = OpBitcast %14 %121 -%123 = OpImageFetch %98 %84 %120 Lod %122 -%124 = OpBitcast %90 %95 -%125 = OpCompositeExtract %4 %77 2 -%126 = OpBitcast %14 %125 -%127 = OpImageFetch %98 %80 %124 Lod %126 -%128 = OpBitcast %90 %95 -%129 = OpCompositeExtract %4 %77 2 -%130 = OpBitcast %14 %129 -%131 = OpImageFetch %98 %81 %128 Sample %130 -%132 = OpBitcast %90 %95 -%133 = OpImageRead %98 %82 %132 -%134 = OpBitcast %90 %95 -%135 = OpCompositeExtract %4 %77 2 -%136 = OpCompositeExtract %4 %77 2 -%137 = OpBitcast %14 %136 -%138 = OpIAdd %14 %137 %29 -%139 = OpCompositeConstruct %12 %134 %135 -%140 = OpImageFetch %98 %83 %139 Lod %138 -%141 = OpBitcast %90 %95 -%142 = OpCompositeExtract %4 %77 2 +%123 = OpImageFetch %119 %102 %116 Sample %122 +%124 = OpImageRead %119 %103 %116 +%125 = OpCompositeExtract %4 %98 2 +%126 = OpCompositeExtract %4 %98 2 +%127 = OpBitcast %14 %126 +%128 = OpIAdd %14 %127 %29 +%129 = OpBitcast %14 %125 +%131 = OpCompositeConstruct %130 %116 %129 +%132 = OpImageFetch %119 %104 %131 Lod %128 +%133 = OpCompositeExtract %4 %98 2 +%134 = OpBitcast %14 %133 +%135 = OpCompositeExtract %4 %98 2 +%136 = OpBitcast %14 %135 +%137 = OpIAdd %14 %136 %29 +%138 = OpCompositeConstruct %130 %116 %134 +%139 = OpImageFetch %119 %104 %138 Lod %137 +%140 = OpCompositeExtract %4 %98 0 +%141 = OpBitcast %14 %140 +%142 = OpCompositeExtract %4 %98 2 %143 = OpBitcast %14 %142 -%144 = OpCompositeExtract %4 %77 2 -%145 = OpBitcast %14 %144 -%146 = OpIAdd %14 %145 %29 -%147 = OpBitcast %4 %143 -%148 = OpCompositeConstruct %12 %141 %147 -%149 = OpImageFetch %98 %83 %148 Lod %146 -%150 = OpCompositeExtract %4 %77 0 -%152 = OpCompositeExtract %4 %77 2 -%153 = OpBitcast %14 %152 -%154 = OpImageFetch %98 %84 %150 Lod %153 -%155 = OpCompositeExtract %14 %95 0 -%156 = OpIAdd %98 %99 %102 -%157 = OpIAdd %98 %156 %103 -%158 = OpIAdd %98 %157 %111 -%159 = OpIAdd %98 %158 %118 -OpImageWrite %85 %155 %159 -%160 = OpCompositeExtract %14 %95 0 -%161 = OpBitcast %4 %160 -%162 = OpIAdd %98 %127 %131 -%163 = OpIAdd %98 %162 %133 -%164 = OpIAdd %98 %163 %140 -%165 = OpIAdd %98 %164 %149 -OpImageWrite %85 %161 %165 +%144 = OpImageFetch %119 %105 %141 Lod %143 +%145 = OpBitcast %111 %116 +%146 = OpCompositeExtract %4 %98 2 +%147 = OpBitcast %14 %146 +%148 = OpImageFetch %119 %101 %145 Lod %147 +%149 = OpBitcast %111 %116 +%150 = OpCompositeExtract %4 %98 2 +%151 = OpBitcast %14 %150 +%152 = OpImageFetch %119 %102 %149 Sample %151 +%153 = OpBitcast %111 %116 +%154 = OpImageRead %119 %103 %153 +%155 = OpBitcast %111 %116 +%156 = OpCompositeExtract %4 %98 2 +%157 = OpCompositeExtract %4 %98 2 +%158 = OpBitcast %14 %157 +%159 = OpIAdd %14 %158 %29 +%160 = OpCompositeConstruct %12 %155 %156 +%161 = OpImageFetch %119 %104 %160 Lod %159 +%162 = OpBitcast %111 %116 +%163 = OpCompositeExtract %4 %98 2 +%164 = OpBitcast %14 %163 +%165 = OpCompositeExtract %4 %98 2 +%166 = OpBitcast %14 %165 +%167 = OpIAdd %14 %166 %29 +%168 = OpBitcast %4 %164 +%169 = OpCompositeConstruct %12 %162 %168 +%170 = OpImageFetch %119 %104 %169 Lod %167 +%171 = OpCompositeExtract %4 %98 0 +%173 = OpCompositeExtract %4 %98 2 +%174 = OpBitcast %14 %173 +%175 = OpImageFetch %119 %105 %171 Lod %174 +%176 = OpCompositeExtract %14 %116 0 +%177 = OpIAdd %119 %120 %123 +%178 = OpIAdd %119 %177 %124 +%179 = OpIAdd %119 %178 %132 +%180 = OpIAdd %119 %179 %139 +OpImageWrite %106 %176 %180 +%181 = OpCompositeExtract %14 %116 0 +%182 = OpBitcast %4 %181 +%183 = OpIAdd %119 %148 %152 +%184 = OpIAdd %119 %183 %154 +%185 = OpIAdd %119 %184 %161 +%186 = OpIAdd %119 %185 %170 +OpImageWrite %106 %182 %186 OpReturn OpFunctionEnd -%169 = OpFunction %2 None %79 -%166 = OpLabel -%168 = OpLoad %12 %167 -%170 = OpLoad %6 %35 -%171 = OpLoad %8 %37 -%172 = OpLoad %10 %45 -OpBranch %173 -%173 = OpLabel -%174 = OpImageQuerySize %90 %171 -%175 = OpVectorShuffle %90 %168 %168 0 1 -%176 = OpIMul %90 %174 %175 -%177 = OpBitcast %13 %176 -%178 = OpSRem %13 %177 %88 -%179 = OpCompositeExtract %4 %168 2 -%180 = OpBitcast %14 %179 -%181 = OpImageFetch %23 %170 %178 Sample %180 -%182 = OpCompositeExtract %7 %181 0 -%183 = OpCompositeExtract %14 %178 0 -%184 = OpConvertFToU %4 %182 -%185 = OpCompositeConstruct %98 %184 %184 %184 %184 -OpImageWrite %172 %183 %185 +%190 = OpFunction %2 None %100 +%187 = OpLabel +%189 = OpLoad %12 %188 +%191 = OpLoad %6 %35 +%192 = OpLoad %8 %37 +%193 = OpLoad %10 %45 +OpBranch %194 +%194 = OpLabel +%195 = OpImageQuerySize %111 %192 +%196 = OpVectorShuffle %111 %189 %189 0 1 +%197 = OpIMul %111 %195 %196 +%198 = OpBitcast %13 %197 +%199 = OpFunctionCall %13 %74 %198 %109 +%200 = OpCompositeExtract %4 %189 2 +%201 = OpBitcast %14 %200 +%202 = OpImageFetch %23 %191 %199 Sample %201 +%203 = OpCompositeExtract %7 %202 0 +%204 = OpCompositeExtract %14 %199 0 +%205 = OpConvertFToU %4 %203 +%206 = OpCompositeConstruct %119 %205 %205 %205 %205 +OpImageWrite %193 %204 %206 OpReturn OpFunctionEnd -%189 = OpFunction %2 None %79 -%186 = OpLabel -%190 = OpLoad %15 %47 -%191 = OpLoad %16 %49 -%192 = OpLoad %18 %54 -%193 = OpLoad %19 %56 -%194 = OpLoad %20 %58 -%195 = OpLoad %21 %60 -%196 = OpLoad %22 %62 -OpBranch %197 -%197 = OpLabel -%199 = OpImageQuerySizeLod %4 %190 %198 -%200 = OpBitcast %14 %199 -%201 = OpImageQuerySizeLod %4 %190 %200 -%202 = OpImageQuerySizeLod %90 %191 %198 -%203 = OpImageQuerySizeLod %90 %191 %29 -%204 = OpImageQuerySizeLod %12 %192 %198 -%205 = OpVectorShuffle %90 %204 %204 0 1 -%206 = OpImageQuerySizeLod %12 %192 %29 -%207 = OpVectorShuffle %90 %206 %206 0 1 -%208 = OpImageQuerySizeLod %90 %193 %198 -%209 = OpImageQuerySizeLod %90 %193 %29 -%210 = OpImageQuerySizeLod %12 %194 %198 -%211 = OpVectorShuffle %90 %210 %210 0 0 -%212 = OpImageQuerySizeLod %12 %194 %29 -%213 = OpVectorShuffle %90 %212 %212 0 0 -%214 = OpImageQuerySizeLod %12 %195 %198 -%215 = OpImageQuerySizeLod %12 %195 %29 -%216 = OpImageQuerySize %90 %196 -%217 = OpCompositeExtract %4 %202 1 -%218 = OpIAdd %4 %199 %217 -%219 = OpCompositeExtract %4 %203 1 -%220 = OpIAdd %4 %218 %219 -%221 = OpCompositeExtract %4 %205 1 -%222 = OpIAdd %4 %220 %221 -%223 = OpCompositeExtract %4 %207 1 -%224 = OpIAdd %4 %222 %223 -%225 = OpCompositeExtract %4 %208 1 -%226 = OpIAdd %4 %224 %225 -%227 = OpCompositeExtract %4 %209 1 -%228 = OpIAdd %4 %226 %227 -%229 = OpCompositeExtract %4 %211 1 -%230 = OpIAdd %4 %228 %229 -%231 = OpCompositeExtract %4 %213 1 -%232 = OpIAdd %4 %230 %231 -%233 = OpCompositeExtract %4 %214 2 -%234 = OpIAdd %4 %232 %233 -%235 = OpCompositeExtract %4 %215 2 -%236 = OpIAdd %4 %234 %235 -%237 = OpConvertUToF %7 %236 -%238 = OpCompositeConstruct %23 %237 %237 %237 %237 -OpStore %187 %238 +%210 = OpFunction %2 None %100 +%207 = OpLabel +%211 = OpLoad %15 %47 +%212 = OpLoad %16 %49 +%213 = OpLoad %18 %54 +%214 = OpLoad %19 %56 +%215 = OpLoad %20 %58 +%216 = OpLoad %21 %60 +%217 = OpLoad %22 %62 +OpBranch %218 +%218 = OpLabel +%220 = OpImageQuerySizeLod %4 %211 %219 +%221 = OpBitcast %14 %220 +%222 = OpImageQuerySizeLod %4 %211 %221 +%223 = OpImageQuerySizeLod %111 %212 %219 +%224 = OpImageQuerySizeLod %111 %212 %29 +%225 = OpImageQuerySizeLod %12 %213 %219 +%226 = OpVectorShuffle %111 %225 %225 0 1 +%227 = OpImageQuerySizeLod %12 %213 %29 +%228 = OpVectorShuffle %111 %227 %227 0 1 +%229 = OpImageQuerySizeLod %111 %214 %219 +%230 = OpImageQuerySizeLod %111 %214 %29 +%231 = OpImageQuerySizeLod %12 %215 %219 +%232 = OpVectorShuffle %111 %231 %231 0 0 +%233 = OpImageQuerySizeLod %12 %215 %29 +%234 = OpVectorShuffle %111 %233 %233 0 0 +%235 = OpImageQuerySizeLod %12 %216 %219 +%236 = OpImageQuerySizeLod %12 %216 %29 +%237 = OpImageQuerySize %111 %217 +%238 = OpCompositeExtract %4 %223 1 +%239 = OpIAdd %4 %220 %238 +%240 = OpCompositeExtract %4 %224 1 +%241 = OpIAdd %4 %239 %240 +%242 = OpCompositeExtract %4 %226 1 +%243 = OpIAdd %4 %241 %242 +%244 = OpCompositeExtract %4 %228 1 +%245 = OpIAdd %4 %243 %244 +%246 = OpCompositeExtract %4 %229 1 +%247 = OpIAdd %4 %245 %246 +%248 = OpCompositeExtract %4 %230 1 +%249 = OpIAdd %4 %247 %248 +%250 = OpCompositeExtract %4 %232 1 +%251 = OpIAdd %4 %249 %250 +%252 = OpCompositeExtract %4 %234 1 +%253 = OpIAdd %4 %251 %252 +%254 = OpCompositeExtract %4 %235 2 +%255 = OpIAdd %4 %253 %254 +%256 = OpCompositeExtract %4 %236 2 +%257 = OpIAdd %4 %255 %256 +%258 = OpConvertUToF %7 %257 +%259 = OpCompositeConstruct %23 %258 %258 %258 %258 +OpStore %208 %259 OpReturn OpFunctionEnd -%241 = OpFunction %2 None %79 -%239 = OpLabel -%242 = OpLoad %16 %49 -%243 = OpLoad %18 %54 -%244 = OpLoad %19 %56 -%245 = OpLoad %20 %58 -%246 = OpLoad %21 %60 -%247 = OpLoad %22 %62 -OpBranch %248 -%248 = OpLabel -%249 = OpImageQueryLevels %4 %242 -%250 = OpImageQuerySizeLod %12 %243 %198 -%251 = OpCompositeExtract %4 %250 2 -%252 = OpImageQueryLevels %4 %243 -%253 = OpImageQuerySizeLod %12 %243 %198 -%254 = OpCompositeExtract %4 %253 2 -%255 = OpImageQueryLevels %4 %244 -%256 = OpImageQueryLevels %4 %245 -%257 = OpImageQuerySizeLod %12 %245 %198 -%258 = OpCompositeExtract %4 %257 2 -%259 = OpImageQueryLevels %4 %246 -%260 = OpImageQuerySamples %4 %247 -%261 = OpIAdd %4 %251 %258 -%262 = OpIAdd %4 %261 %260 -%263 = OpIAdd %4 %262 %249 -%264 = OpIAdd %4 %263 %252 -%265 = OpIAdd %4 %264 %259 -%266 = OpIAdd %4 %265 %255 -%267 = OpIAdd %4 %266 %256 -%268 = OpConvertUToF %7 %267 -%269 = OpCompositeConstruct %23 %268 %268 %268 %268 -OpStore %240 %269 +%262 = OpFunction %2 None %100 +%260 = OpLabel +%263 = OpLoad %16 %49 +%264 = OpLoad %18 %54 +%265 = OpLoad %19 %56 +%266 = OpLoad %20 %58 +%267 = OpLoad %21 %60 +%268 = OpLoad %22 %62 +OpBranch %269 +%269 = OpLabel +%270 = OpImageQueryLevels %4 %263 +%271 = OpImageQuerySizeLod %12 %264 %219 +%272 = OpCompositeExtract %4 %271 2 +%273 = OpImageQueryLevels %4 %264 +%274 = OpImageQuerySizeLod %12 %264 %219 +%275 = OpCompositeExtract %4 %274 2 +%276 = OpImageQueryLevels %4 %265 +%277 = OpImageQueryLevels %4 %266 +%278 = OpImageQuerySizeLod %12 %266 %219 +%279 = OpCompositeExtract %4 %278 2 +%280 = OpImageQueryLevels %4 %267 +%281 = OpImageQuerySamples %4 %268 +%282 = OpIAdd %4 %272 %279 +%283 = OpIAdd %4 %282 %281 +%284 = OpIAdd %4 %283 %270 +%285 = OpIAdd %4 %284 %273 +%286 = OpIAdd %4 %285 %280 +%287 = OpIAdd %4 %286 %276 +%288 = OpIAdd %4 %287 %277 +%289 = OpConvertUToF %7 %288 +%290 = OpCompositeConstruct %23 %289 %289 %289 %289 +OpStore %261 %290 OpReturn OpFunctionEnd -%272 = OpFunction %2 None %79 -%270 = OpLabel -%286 = OpVariable %287 Function %288 -%273 = OpLoad %15 %47 -%274 = OpLoad %16 %49 -%275 = OpLoad %18 %54 -%276 = OpLoad %20 %58 -%277 = OpLoad %24 %64 -OpBranch %289 -%289 = OpLabel -%290 = OpCompositeExtract %7 %280 0 -%292 = OpSampledImage %291 %273 %277 -%293 = OpImageSampleImplicitLod %23 %292 %290 -%294 = OpLoad %23 %286 -%295 = OpFAdd %23 %294 %293 -OpStore %286 %295 -%297 = OpSampledImage %296 %274 %277 -%298 = OpImageSampleImplicitLod %23 %297 %280 -%299 = OpLoad %23 %286 -%300 = OpFAdd %23 %299 %298 -OpStore %286 %300 -%301 = OpSampledImage %296 %274 %277 -%302 = OpImageSampleImplicitLod %23 %301 %280 ConstOffset %30 -%303 = OpLoad %23 %286 -%304 = OpFAdd %23 %303 %302 -OpStore %286 %304 -%305 = OpSampledImage %296 %274 %277 -%306 = OpImageSampleExplicitLod %23 %305 %280 Lod %283 -%307 = OpLoad %23 %286 -%308 = OpFAdd %23 %307 %306 -OpStore %286 %308 -%309 = OpSampledImage %296 %274 %277 -%310 = OpImageSampleExplicitLod %23 %309 %280 Lod|ConstOffset %283 %30 -%311 = OpLoad %23 %286 -%312 = OpFAdd %23 %311 %310 -OpStore %286 %312 -%313 = OpSampledImage %296 %274 %277 -%314 = OpImageSampleImplicitLod %23 %313 %280 Bias|ConstOffset %284 %30 -%315 = OpLoad %23 %286 -%316 = OpFAdd %23 %315 %314 -OpStore %286 %316 -%318 = OpConvertUToF %7 %198 -%319 = OpCompositeConstruct %281 %280 %318 -%320 = OpSampledImage %317 %275 %277 -%321 = OpImageSampleImplicitLod %23 %320 %319 -%322 = OpLoad %23 %286 -%323 = OpFAdd %23 %322 %321 -OpStore %286 %323 -%324 = OpConvertUToF %7 %198 -%325 = OpCompositeConstruct %281 %280 %324 -%326 = OpSampledImage %317 %275 %277 -%327 = OpImageSampleImplicitLod %23 %326 %325 ConstOffset %30 -%328 = OpLoad %23 %286 -%329 = OpFAdd %23 %328 %327 -OpStore %286 %329 -%330 = OpConvertUToF %7 %198 -%331 = OpCompositeConstruct %281 %280 %330 -%332 = OpSampledImage %317 %275 %277 -%333 = OpImageSampleExplicitLod %23 %332 %331 Lod %283 -%334 = OpLoad %23 %286 -%335 = OpFAdd %23 %334 %333 -OpStore %286 %335 -%336 = OpConvertUToF %7 %198 -%337 = OpCompositeConstruct %281 %280 %336 -%338 = OpSampledImage %317 %275 %277 -%339 = OpImageSampleExplicitLod %23 %338 %337 Lod|ConstOffset %283 %30 -%340 = OpLoad %23 %286 -%341 = OpFAdd %23 %340 %339 -OpStore %286 %341 -%342 = OpConvertUToF %7 %198 -%343 = OpCompositeConstruct %281 %280 %342 -%344 = OpSampledImage %317 %275 %277 -%345 = OpImageSampleImplicitLod %23 %344 %343 Bias|ConstOffset %284 %30 -%346 = OpLoad %23 %286 -%347 = OpFAdd %23 %346 %345 -OpStore %286 %347 -%348 = OpConvertSToF %7 %285 -%349 = OpCompositeConstruct %281 %280 %348 -%350 = OpSampledImage %317 %275 %277 -%351 = OpImageSampleImplicitLod %23 %350 %349 -%352 = OpLoad %23 %286 -%353 = OpFAdd %23 %352 %351 -OpStore %286 %353 -%354 = OpConvertSToF %7 %285 -%355 = OpCompositeConstruct %281 %280 %354 -%356 = OpSampledImage %317 %275 %277 -%357 = OpImageSampleImplicitLod %23 %356 %355 ConstOffset %30 -%358 = OpLoad %23 %286 -%359 = OpFAdd %23 %358 %357 -OpStore %286 %359 -%360 = OpConvertSToF %7 %285 -%361 = OpCompositeConstruct %281 %280 %360 -%362 = OpSampledImage %317 %275 %277 -%363 = OpImageSampleExplicitLod %23 %362 %361 Lod %283 -%364 = OpLoad %23 %286 -%365 = OpFAdd %23 %364 %363 -OpStore %286 %365 -%366 = OpConvertSToF %7 %285 -%367 = OpCompositeConstruct %281 %280 %366 -%368 = OpSampledImage %317 %275 %277 -%369 = OpImageSampleExplicitLod %23 %368 %367 Lod|ConstOffset %283 %30 -%370 = OpLoad %23 %286 -%371 = OpFAdd %23 %370 %369 -OpStore %286 %371 -%372 = OpConvertSToF %7 %285 -%373 = OpCompositeConstruct %281 %280 %372 -%374 = OpSampledImage %317 %275 %277 -%375 = OpImageSampleImplicitLod %23 %374 %373 Bias|ConstOffset %284 %30 -%376 = OpLoad %23 %286 -%377 = OpFAdd %23 %376 %375 -OpStore %286 %377 -%379 = OpConvertUToF %7 %198 -%380 = OpCompositeConstruct %23 %282 %379 -%381 = OpSampledImage %378 %276 %277 -%382 = OpImageSampleImplicitLod %23 %381 %380 -%383 = OpLoad %23 %286 -%384 = OpFAdd %23 %383 %382 -OpStore %286 %384 -%385 = OpConvertUToF %7 %198 -%386 = OpCompositeConstruct %23 %282 %385 -%387 = OpSampledImage %378 %276 %277 -%388 = OpImageSampleExplicitLod %23 %387 %386 Lod %283 -%389 = OpLoad %23 %286 -%390 = OpFAdd %23 %389 %388 -OpStore %286 %390 -%391 = OpConvertUToF %7 %198 -%392 = OpCompositeConstruct %23 %282 %391 -%393 = OpSampledImage %378 %276 %277 -%394 = OpImageSampleImplicitLod %23 %393 %392 Bias %284 -%395 = OpLoad %23 %286 -%396 = OpFAdd %23 %395 %394 -OpStore %286 %396 -%397 = OpConvertSToF %7 %285 -%398 = OpCompositeConstruct %23 %282 %397 -%399 = OpSampledImage %378 %276 %277 -%400 = OpImageSampleImplicitLod %23 %399 %398 -%401 = OpLoad %23 %286 -%402 = OpFAdd %23 %401 %400 -OpStore %286 %402 -%403 = OpConvertSToF %7 %285 -%404 = OpCompositeConstruct %23 %282 %403 -%405 = OpSampledImage %378 %276 %277 -%406 = OpImageSampleExplicitLod %23 %405 %404 Lod %283 -%407 = OpLoad %23 %286 -%408 = OpFAdd %23 %407 %406 -OpStore %286 %408 -%409 = OpConvertSToF %7 %285 -%410 = OpCompositeConstruct %23 %282 %409 -%411 = OpSampledImage %378 %276 %277 -%412 = OpImageSampleImplicitLod %23 %411 %410 Bias %284 -%413 = OpLoad %23 %286 -%414 = OpFAdd %23 %413 %412 -OpStore %286 %414 -%415 = OpLoad %23 %286 -OpStore %271 %415 +%293 = OpFunction %2 None %100 +%291 = OpLabel +%306 = OpVariable %307 Function %308 +%294 = OpLoad %15 %47 +%295 = OpLoad %16 %49 +%296 = OpLoad %18 %54 +%297 = OpLoad %20 %58 +%298 = OpLoad %24 %64 +OpBranch %309 +%309 = OpLabel +%310 = OpCompositeExtract %7 %301 0 +%312 = OpSampledImage %311 %294 %298 +%313 = OpImageSampleImplicitLod %23 %312 %310 +%314 = OpLoad %23 %306 +%315 = OpFAdd %23 %314 %313 +OpStore %306 %315 +%317 = OpSampledImage %316 %295 %298 +%318 = OpImageSampleImplicitLod %23 %317 %301 +%319 = OpLoad %23 %306 +%320 = OpFAdd %23 %319 %318 +OpStore %306 %320 +%321 = OpSampledImage %316 %295 %298 +%322 = OpImageSampleImplicitLod %23 %321 %301 ConstOffset %30 +%323 = OpLoad %23 %306 +%324 = OpFAdd %23 %323 %322 +OpStore %306 %324 +%325 = OpSampledImage %316 %295 %298 +%326 = OpImageSampleExplicitLod %23 %325 %301 Lod %304 +%327 = OpLoad %23 %306 +%328 = OpFAdd %23 %327 %326 +OpStore %306 %328 +%329 = OpSampledImage %316 %295 %298 +%330 = OpImageSampleExplicitLod %23 %329 %301 Lod|ConstOffset %304 %30 +%331 = OpLoad %23 %306 +%332 = OpFAdd %23 %331 %330 +OpStore %306 %332 +%333 = OpSampledImage %316 %295 %298 +%334 = OpImageSampleImplicitLod %23 %333 %301 Bias|ConstOffset %305 %30 +%335 = OpLoad %23 %306 +%336 = OpFAdd %23 %335 %334 +OpStore %306 %336 +%338 = OpConvertUToF %7 %219 +%339 = OpCompositeConstruct %302 %301 %338 +%340 = OpSampledImage %337 %296 %298 +%341 = OpImageSampleImplicitLod %23 %340 %339 +%342 = OpLoad %23 %306 +%343 = OpFAdd %23 %342 %341 +OpStore %306 %343 +%344 = OpConvertUToF %7 %219 +%345 = OpCompositeConstruct %302 %301 %344 +%346 = OpSampledImage %337 %296 %298 +%347 = OpImageSampleImplicitLod %23 %346 %345 ConstOffset %30 +%348 = OpLoad %23 %306 +%349 = OpFAdd %23 %348 %347 +OpStore %306 %349 +%350 = OpConvertUToF %7 %219 +%351 = OpCompositeConstruct %302 %301 %350 +%352 = OpSampledImage %337 %296 %298 +%353 = OpImageSampleExplicitLod %23 %352 %351 Lod %304 +%354 = OpLoad %23 %306 +%355 = OpFAdd %23 %354 %353 +OpStore %306 %355 +%356 = OpConvertUToF %7 %219 +%357 = OpCompositeConstruct %302 %301 %356 +%358 = OpSampledImage %337 %296 %298 +%359 = OpImageSampleExplicitLod %23 %358 %357 Lod|ConstOffset %304 %30 +%360 = OpLoad %23 %306 +%361 = OpFAdd %23 %360 %359 +OpStore %306 %361 +%362 = OpConvertUToF %7 %219 +%363 = OpCompositeConstruct %302 %301 %362 +%364 = OpSampledImage %337 %296 %298 +%365 = OpImageSampleImplicitLod %23 %364 %363 Bias|ConstOffset %305 %30 +%366 = OpLoad %23 %306 +%367 = OpFAdd %23 %366 %365 +OpStore %306 %367 +%368 = OpConvertSToF %7 %81 +%369 = OpCompositeConstruct %302 %301 %368 +%370 = OpSampledImage %337 %296 %298 +%371 = OpImageSampleImplicitLod %23 %370 %369 +%372 = OpLoad %23 %306 +%373 = OpFAdd %23 %372 %371 +OpStore %306 %373 +%374 = OpConvertSToF %7 %81 +%375 = OpCompositeConstruct %302 %301 %374 +%376 = OpSampledImage %337 %296 %298 +%377 = OpImageSampleImplicitLod %23 %376 %375 ConstOffset %30 +%378 = OpLoad %23 %306 +%379 = OpFAdd %23 %378 %377 +OpStore %306 %379 +%380 = OpConvertSToF %7 %81 +%381 = OpCompositeConstruct %302 %301 %380 +%382 = OpSampledImage %337 %296 %298 +%383 = OpImageSampleExplicitLod %23 %382 %381 Lod %304 +%384 = OpLoad %23 %306 +%385 = OpFAdd %23 %384 %383 +OpStore %306 %385 +%386 = OpConvertSToF %7 %81 +%387 = OpCompositeConstruct %302 %301 %386 +%388 = OpSampledImage %337 %296 %298 +%389 = OpImageSampleExplicitLod %23 %388 %387 Lod|ConstOffset %304 %30 +%390 = OpLoad %23 %306 +%391 = OpFAdd %23 %390 %389 +OpStore %306 %391 +%392 = OpConvertSToF %7 %81 +%393 = OpCompositeConstruct %302 %301 %392 +%394 = OpSampledImage %337 %296 %298 +%395 = OpImageSampleImplicitLod %23 %394 %393 Bias|ConstOffset %305 %30 +%396 = OpLoad %23 %306 +%397 = OpFAdd %23 %396 %395 +OpStore %306 %397 +%399 = OpConvertUToF %7 %219 +%400 = OpCompositeConstruct %23 %303 %399 +%401 = OpSampledImage %398 %297 %298 +%402 = OpImageSampleImplicitLod %23 %401 %400 +%403 = OpLoad %23 %306 +%404 = OpFAdd %23 %403 %402 +OpStore %306 %404 +%405 = OpConvertUToF %7 %219 +%406 = OpCompositeConstruct %23 %303 %405 +%407 = OpSampledImage %398 %297 %298 +%408 = OpImageSampleExplicitLod %23 %407 %406 Lod %304 +%409 = OpLoad %23 %306 +%410 = OpFAdd %23 %409 %408 +OpStore %306 %410 +%411 = OpConvertUToF %7 %219 +%412 = OpCompositeConstruct %23 %303 %411 +%413 = OpSampledImage %398 %297 %298 +%414 = OpImageSampleImplicitLod %23 %413 %412 Bias %305 +%415 = OpLoad %23 %306 +%416 = OpFAdd %23 %415 %414 +OpStore %306 %416 +%417 = OpConvertSToF %7 %81 +%418 = OpCompositeConstruct %23 %303 %417 +%419 = OpSampledImage %398 %297 %298 +%420 = OpImageSampleImplicitLod %23 %419 %418 +%421 = OpLoad %23 %306 +%422 = OpFAdd %23 %421 %420 +OpStore %306 %422 +%423 = OpConvertSToF %7 %81 +%424 = OpCompositeConstruct %23 %303 %423 +%425 = OpSampledImage %398 %297 %298 +%426 = OpImageSampleExplicitLod %23 %425 %424 Lod %304 +%427 = OpLoad %23 %306 +%428 = OpFAdd %23 %427 %426 +OpStore %306 %428 +%429 = OpConvertSToF %7 %81 +%430 = OpCompositeConstruct %23 %303 %429 +%431 = OpSampledImage %398 %297 %298 +%432 = OpImageSampleImplicitLod %23 %431 %430 Bias %305 +%433 = OpLoad %23 %306 +%434 = OpFAdd %23 %433 %432 +OpStore %306 %434 +%435 = OpLoad %23 %306 +OpStore %292 %435 OpReturn OpFunctionEnd -%419 = OpFunction %2 None %79 -%416 = OpLabel -%424 = OpVariable %425 Function %426 -%420 = OpLoad %24 %66 -%421 = OpLoad %25 %68 -%422 = OpLoad %26 %70 -%423 = OpLoad %27 %72 -OpBranch %427 -%427 = OpLabel -%429 = OpSampledImage %428 %421 %420 -%430 = OpImageSampleDrefImplicitLod %7 %429 %280 %278 -%431 = OpLoad %7 %424 -%432 = OpFAdd %7 %431 %430 -OpStore %424 %432 -%434 = OpConvertUToF %7 %198 -%435 = OpCompositeConstruct %281 %280 %434 -%436 = OpSampledImage %433 %422 %420 -%437 = OpImageSampleDrefImplicitLod %7 %436 %435 %278 -%438 = OpLoad %7 %424 -%439 = OpFAdd %7 %438 %437 -OpStore %424 %439 -%440 = OpConvertSToF %7 %285 -%441 = OpCompositeConstruct %281 %280 %440 -%442 = OpSampledImage %433 %422 %420 -%443 = OpImageSampleDrefImplicitLod %7 %442 %441 %278 -%444 = OpLoad %7 %424 -%445 = OpFAdd %7 %444 %443 -OpStore %424 %445 -%447 = OpSampledImage %446 %423 %420 -%448 = OpImageSampleDrefImplicitLod %7 %447 %282 %278 -%449 = OpLoad %7 %424 -%450 = OpFAdd %7 %449 %448 -OpStore %424 %450 -%451 = OpSampledImage %428 %421 %420 -%452 = OpImageSampleDrefExplicitLod %7 %451 %280 %278 Lod %453 -%454 = OpLoad %7 %424 -%455 = OpFAdd %7 %454 %452 -OpStore %424 %455 -%456 = OpConvertUToF %7 %198 -%457 = OpCompositeConstruct %281 %280 %456 -%458 = OpSampledImage %433 %422 %420 -%459 = OpImageSampleDrefExplicitLod %7 %458 %457 %278 Lod %453 -%460 = OpLoad %7 %424 -%461 = OpFAdd %7 %460 %459 -OpStore %424 %461 -%462 = OpConvertSToF %7 %285 -%463 = OpCompositeConstruct %281 %280 %462 -%464 = OpSampledImage %433 %422 %420 -%465 = OpImageSampleDrefExplicitLod %7 %464 %463 %278 Lod %453 -%466 = OpLoad %7 %424 -%467 = OpFAdd %7 %466 %465 -OpStore %424 %467 -%468 = OpSampledImage %446 %423 %420 -%469 = OpImageSampleDrefExplicitLod %7 %468 %282 %278 Lod %453 -%470 = OpLoad %7 %424 -%471 = OpFAdd %7 %470 %469 -OpStore %424 %471 -%472 = OpLoad %7 %424 -OpStore %417 %472 +%439 = OpFunction %2 None %100 +%436 = OpLabel +%444 = OpVariable %445 Function %446 +%440 = OpLoad %24 %66 +%441 = OpLoad %25 %68 +%442 = OpLoad %26 %70 +%443 = OpLoad %27 %72 +OpBranch %447 +%447 = OpLabel +%449 = OpSampledImage %448 %441 %440 +%450 = OpImageSampleDrefImplicitLod %7 %449 %301 %299 +%451 = OpLoad %7 %444 +%452 = OpFAdd %7 %451 %450 +OpStore %444 %452 +%454 = OpConvertUToF %7 %219 +%455 = OpCompositeConstruct %302 %301 %454 +%456 = OpSampledImage %453 %442 %440 +%457 = OpImageSampleDrefImplicitLod %7 %456 %455 %299 +%458 = OpLoad %7 %444 +%459 = OpFAdd %7 %458 %457 +OpStore %444 %459 +%460 = OpConvertSToF %7 %81 +%461 = OpCompositeConstruct %302 %301 %460 +%462 = OpSampledImage %453 %442 %440 +%463 = OpImageSampleDrefImplicitLod %7 %462 %461 %299 +%464 = OpLoad %7 %444 +%465 = OpFAdd %7 %464 %463 +OpStore %444 %465 +%467 = OpSampledImage %466 %443 %440 +%468 = OpImageSampleDrefImplicitLod %7 %467 %303 %299 +%469 = OpLoad %7 %444 +%470 = OpFAdd %7 %469 %468 +OpStore %444 %470 +%471 = OpSampledImage %448 %441 %440 +%472 = OpImageSampleDrefExplicitLod %7 %471 %301 %299 Lod %473 +%474 = OpLoad %7 %444 +%475 = OpFAdd %7 %474 %472 +OpStore %444 %475 +%476 = OpConvertUToF %7 %219 +%477 = OpCompositeConstruct %302 %301 %476 +%478 = OpSampledImage %453 %442 %440 +%479 = OpImageSampleDrefExplicitLod %7 %478 %477 %299 Lod %473 +%480 = OpLoad %7 %444 +%481 = OpFAdd %7 %480 %479 +OpStore %444 %481 +%482 = OpConvertSToF %7 %81 +%483 = OpCompositeConstruct %302 %301 %482 +%484 = OpSampledImage %453 %442 %440 +%485 = OpImageSampleDrefExplicitLod %7 %484 %483 %299 Lod %473 +%486 = OpLoad %7 %444 +%487 = OpFAdd %7 %486 %485 +OpStore %444 %487 +%488 = OpSampledImage %466 %443 %440 +%489 = OpImageSampleDrefExplicitLod %7 %488 %303 %299 Lod %473 +%490 = OpLoad %7 %444 +%491 = OpFAdd %7 %490 %489 +OpStore %444 %491 +%492 = OpLoad %7 %444 +OpStore %437 %492 OpReturn OpFunctionEnd -%475 = OpFunction %2 None %79 -%473 = OpLabel -%476 = OpLoad %16 %49 -%477 = OpLoad %3 %51 -%478 = OpLoad %17 %52 -%479 = OpLoad %24 %64 -%480 = OpLoad %24 %66 -%481 = OpLoad %25 %68 -OpBranch %482 -%482 = OpLabel -%483 = OpSampledImage %296 %476 %479 -%484 = OpImageGather %23 %483 %280 %485 -%486 = OpSampledImage %296 %476 %479 -%487 = OpImageGather %23 %486 %280 %488 ConstOffset %30 -%489 = OpSampledImage %428 %481 %480 -%490 = OpImageDrefGather %23 %489 %280 %278 -%491 = OpSampledImage %428 %481 %480 -%492 = OpImageDrefGather %23 %491 %280 %278 ConstOffset %30 -%494 = OpSampledImage %493 %477 %479 -%495 = OpImageGather %98 %494 %280 %198 -%498 = OpSampledImage %497 %478 %479 -%499 = OpImageGather %496 %498 %280 %198 -%500 = OpConvertUToF %23 %495 -%501 = OpConvertSToF %23 %499 -%502 = OpFAdd %23 %500 %501 -%503 = OpFAdd %23 %484 %487 -%504 = OpFAdd %23 %503 %490 -%505 = OpFAdd %23 %504 %492 -%506 = OpFAdd %23 %505 %502 -OpStore %474 %506 +%495 = OpFunction %2 None %100 +%493 = OpLabel +%496 = OpLoad %16 %49 +%497 = OpLoad %3 %51 +%498 = OpLoad %17 %52 +%499 = OpLoad %24 %64 +%500 = OpLoad %24 %66 +%501 = OpLoad %25 %68 +OpBranch %502 +%502 = OpLabel +%503 = OpSampledImage %316 %496 %499 +%504 = OpImageGather %23 %503 %301 %505 +%506 = OpSampledImage %316 %496 %499 +%507 = OpImageGather %23 %506 %301 %508 ConstOffset %30 +%509 = OpSampledImage %448 %501 %500 +%510 = OpImageDrefGather %23 %509 %301 %299 +%511 = OpSampledImage %448 %501 %500 +%512 = OpImageDrefGather %23 %511 %301 %299 ConstOffset %30 +%514 = OpSampledImage %513 %497 %499 +%515 = OpImageGather %119 %514 %301 %219 +%518 = OpSampledImage %517 %498 %499 +%519 = OpImageGather %516 %518 %301 %219 +%520 = OpConvertUToF %23 %515 +%521 = OpConvertSToF %23 %519 +%522 = OpFAdd %23 %520 %521 +%523 = OpFAdd %23 %504 %507 +%524 = OpFAdd %23 %523 %510 +%525 = OpFAdd %23 %524 %512 +%526 = OpFAdd %23 %525 %522 +OpStore %494 %526 OpReturn OpFunctionEnd -%509 = OpFunction %2 None %79 -%507 = OpLabel -%510 = OpLoad %24 %64 -%511 = OpLoad %25 %68 -OpBranch %512 -%512 = OpLabel -%513 = OpSampledImage %428 %511 %510 -%514 = OpImageSampleImplicitLod %23 %513 %280 -%515 = OpCompositeExtract %7 %514 0 -%516 = OpSampledImage %428 %511 %510 -%517 = OpImageGather %23 %516 %280 %198 -%518 = OpSampledImage %428 %511 %510 -%520 = OpConvertSToF %7 %29 -%519 = OpImageSampleExplicitLod %23 %518 %280 Lod %520 -%521 = OpCompositeExtract %7 %519 0 -%522 = OpCompositeConstruct %23 %515 %515 %515 %515 -%523 = OpFAdd %23 %522 %517 -%524 = OpCompositeConstruct %23 %521 %521 %521 %521 -%525 = OpFAdd %23 %523 %524 -OpStore %508 %525 +%529 = OpFunction %2 None %100 +%527 = OpLabel +%530 = OpLoad %24 %64 +%531 = OpLoad %25 %68 +OpBranch %532 +%532 = OpLabel +%533 = OpSampledImage %448 %531 %530 +%534 = OpImageSampleImplicitLod %23 %533 %301 +%535 = OpCompositeExtract %7 %534 0 +%536 = OpSampledImage %448 %531 %530 +%537 = OpImageGather %23 %536 %301 %219 +%538 = OpSampledImage %448 %531 %530 +%540 = OpConvertSToF %7 %29 +%539 = OpImageSampleExplicitLod %23 %538 %301 Lod %540 +%541 = OpCompositeExtract %7 %539 0 +%542 = OpCompositeConstruct %23 %535 %535 %535 %535 +%543 = OpFAdd %23 %542 %537 +%544 = OpCompositeConstruct %23 %541 %541 %541 %541 +%545 = OpFAdd %23 %543 %544 +OpStore %528 %545 OpReturn OpFunctionEnd \ No newline at end of file diff --git a/naga/tests/out/spv/operators.spvasm b/naga/tests/out/spv/operators.spvasm index 766f45528b..4ceea6ab71 100644 --- a/naga/tests/out/spv/operators.spvasm +++ b/naga/tests/out/spv/operators.spvasm @@ -1,13 +1,13 @@ ; SPIR-V ; Version: 1.1 ; Generator: rspirv -; Bound: 389 +; Bound: 528 OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %374 "main" %371 -OpExecutionMode %374 LocalSize 1 1 1 -OpDecorate %371 BuiltIn WorkgroupId +OpEntryPoint GLCompute %513 "main" %510 +OpExecutionMode %513 LocalSize 1 1 1 +OpDecorate %510 BuiltIn WorkgroupId %2 = OpTypeVoid %3 = OpTypeFloat 32 %4 = OpTypeVector %3 4 @@ -38,55 +38,73 @@ OpDecorate %371 BuiltIn WorkgroupId %31 = OpConstantComposite %7 %30 %30 %30 %30 %32 = OpConstant %3 0.1 %33 = OpConstantComposite %6 %29 %29 %29 %29 -%57 = OpTypeFunction %4 %3 %5 -%58 = OpConstant %3 2.0 -%59 = OpConstantComposite %9 %58 %58 -%60 = OpConstant %3 4.0 -%61 = OpConstantComposite %9 %60 %60 -%62 = OpConstant %3 8.0 -%63 = OpConstantComposite %9 %62 %62 -%64 = OpConstant %5 2 -%65 = OpConstantComposite %6 %64 %64 %64 %64 -%78 = OpTypeFunction %9 -%79 = OpConstantComposite %9 %17 %17 -%80 = OpConstant %3 3.0 +%54 = OpTypeFunction %6 %6 %6 +%58 = OpConstantComposite %6 %29 %29 %29 %29 +%60 = OpConstant %5 -2147483648 +%61 = OpConstant %5 -1 +%62 = OpConstantComposite %6 %60 %60 %60 %60 +%63 = OpConstantComposite %6 %61 %61 %61 %61 +%68 = OpConstantComposite %6 %23 %23 %23 %23 +%75 = OpTypeFunction %4 %3 %5 +%76 = OpConstant %3 2.0 +%77 = OpConstantComposite %9 %76 %76 +%78 = OpConstant %3 4.0 +%79 = OpConstantComposite %9 %78 %78 +%80 = OpConstant %3 8.0 %81 = OpConstantComposite %9 %80 %80 -%83 = OpTypePointer Function %9 -%95 = OpTypeFunction %10 %10 -%97 = OpTypeVector %8 3 -%98 = OpConstantComposite %10 %19 %19 %19 -%100 = OpConstantComposite %10 %17 %17 %17 -%104 = OpTypeFunction %2 -%105 = OpTypeVector %8 2 -%106 = OpConstantComposite %105 %28 %28 -%107 = OpConstantComposite %97 %28 %28 %28 -%108 = OpConstantComposite %97 %30 %30 %30 -%109 = OpConstantComposite %7 %28 %28 %28 %28 -%110 = OpConstantComposite %7 %30 %30 %30 %30 -%122 = OpConstant %16 1 -%123 = OpConstant %16 2 -%124 = OpTypeVector %5 2 -%125 = OpConstantComposite %124 %23 %23 -%126 = OpConstantComposite %124 %64 %64 -%127 = OpConstantComposite %15 %123 %123 %123 -%128 = OpConstantComposite %15 %122 %122 %122 -%129 = OpConstantComposite %4 %58 %58 %58 %58 -%130 = OpConstantComposite %4 %17 %17 %17 %17 -%131 = OpTypeVector %16 2 -%132 = OpConstantComposite %131 %123 %123 -%133 = OpConstantComposite %131 %122 %122 -%134 = OpConstantNull %11 -%135 = OpConstantNull %12 -%136 = OpConstantComposite %10 %58 %58 %58 -%137 = OpConstantNull %13 -%301 = OpConstantNull %14 -%303 = OpTypePointer Function %5 -%304 = OpConstantNull %5 -%306 = OpTypePointer Function %14 -%334 = OpTypePointer Function %5 -%372 = OpTypePointer Input %15 -%371 = OpVariable %372 Input -%375 = OpConstantComposite %10 %17 %17 %17 +%82 = OpConstant %5 2 +%83 = OpConstantComposite %6 %82 %82 %82 %82 +%96 = OpTypeFunction %9 +%97 = OpConstantComposite %9 %17 %17 +%98 = OpConstant %3 3.0 +%99 = OpConstantComposite %9 %98 %98 +%101 = OpTypePointer Function %9 +%113 = OpTypeFunction %10 %10 +%115 = OpTypeVector %8 3 +%116 = OpConstantComposite %10 %19 %19 %19 +%118 = OpConstantComposite %10 %17 %17 %17 +%122 = OpTypeFunction %2 +%123 = OpTypeVector %8 2 +%124 = OpConstantComposite %123 %28 %28 +%125 = OpConstantComposite %115 %28 %28 %28 +%126 = OpConstantComposite %115 %30 %30 %30 +%127 = OpConstantComposite %7 %28 %28 %28 %28 +%128 = OpConstantComposite %7 %30 %30 %30 %30 +%139 = OpTypeFunction %5 %5 %5 +%151 = OpTypeFunction %16 %16 %16 +%155 = OpConstant %16 0 +%157 = OpConstant %16 1 +%160 = OpTypeVector %5 2 +%162 = OpTypeFunction %160 %160 %160 +%166 = OpConstantComposite %160 %29 %29 +%168 = OpConstantComposite %160 %60 %60 +%169 = OpConstantComposite %160 %61 %61 +%174 = OpConstantComposite %160 %23 %23 +%178 = OpTypeFunction %15 %15 %15 +%182 = OpConstantComposite %15 %155 %155 %155 +%184 = OpConstantComposite %15 %157 %157 %157 +%223 = OpTypeVector %16 2 +%225 = OpTypeFunction %223 %223 %223 +%229 = OpConstantComposite %223 %155 %155 +%231 = OpConstantComposite %223 %157 %157 +%243 = OpConstant %16 2 +%244 = OpConstantComposite %160 %82 %82 +%245 = OpConstantComposite %15 %243 %243 %243 +%246 = OpConstantComposite %4 %76 %76 %76 %76 +%247 = OpConstantComposite %4 %17 %17 %17 %17 +%248 = OpConstantComposite %223 %243 %243 +%249 = OpConstantNull %11 +%250 = OpConstantNull %12 +%251 = OpConstantComposite %10 %76 %76 %76 +%252 = OpConstantNull %13 +%416 = OpConstantNull %14 +%418 = OpTypePointer Function %5 +%419 = OpConstantNull %5 +%421 = OpTypePointer Function %14 +%449 = OpTypePointer Function %5 +%511 = OpTypePointer Input %15 +%510 = OpVariable %511 Input +%514 = OpConstantComposite %10 %17 %17 %17 %26 = OpFunction %4 None %27 %25 = OpLabel OpBranch %34 @@ -111,340 +129,483 @@ OpBranch %34 %52 = OpFAdd %4 %51 %43 OpReturnValue %52 OpFunctionEnd -%56 = OpFunction %4 None %57 -%54 = OpFunctionParameter %3 -%55 = OpFunctionParameter %5 -%53 = OpLabel -OpBranch %66 -%66 = OpLabel -%67 = OpCompositeConstruct %9 %54 %54 -%68 = OpFAdd %9 %59 %67 -%69 = OpFSub %9 %68 %61 -%70 = OpFDiv %9 %69 %63 -%71 = OpCompositeConstruct %6 %55 %55 %55 %55 -%72 = OpSRem %6 %71 %65 -%73 = OpVectorShuffle %4 %70 %70 0 1 0 1 -%74 = OpConvertSToF %4 %72 -%75 = OpFAdd %4 %73 %74 -OpReturnValue %75 +%53 = OpFunction %6 None %54 +%55 = OpFunctionParameter %6 +%56 = OpFunctionParameter %6 +%57 = OpLabel +%59 = OpIEqual %7 %56 %58 +%64 = OpIEqual %7 %55 %62 +%65 = OpIEqual %7 %56 %63 +%66 = OpLogicalAnd %7 %64 %65 +%67 = OpLogicalOr %7 %59 %66 +%69 = OpSelect %6 %67 %68 %56 +%70 = OpSRem %6 %55 %69 +OpReturnValue %70 OpFunctionEnd -%77 = OpFunction %9 None %78 -%76 = OpLabel -%82 = OpVariable %83 Function %59 +%74 = OpFunction %4 None %75 +%72 = OpFunctionParameter %3 +%73 = OpFunctionParameter %5 +%71 = OpLabel OpBranch %84 %84 = OpLabel -%85 = OpLoad %9 %82 -%86 = OpFAdd %9 %85 %79 -OpStore %82 %86 -%87 = OpLoad %9 %82 -%88 = OpFSub %9 %87 %81 -OpStore %82 %88 -%89 = OpLoad %9 %82 -%90 = OpFDiv %9 %89 %61 -OpStore %82 %90 -%91 = OpLoad %9 %82 -OpReturnValue %91 +%85 = OpCompositeConstruct %9 %72 %72 +%86 = OpFAdd %9 %77 %85 +%87 = OpFSub %9 %86 %79 +%88 = OpFDiv %9 %87 %81 +%89 = OpCompositeConstruct %6 %73 %73 %73 %73 +%90 = OpFunctionCall %6 %53 %89 %83 +%91 = OpVectorShuffle %4 %88 %88 0 1 0 1 +%92 = OpConvertSToF %4 %90 +%93 = OpFAdd %4 %91 %92 +OpReturnValue %93 OpFunctionEnd -%94 = OpFunction %10 None %95 -%93 = OpFunctionParameter %10 -%92 = OpLabel -OpBranch %96 -%96 = OpLabel -%99 = OpFUnordNotEqual %97 %93 %98 -%101 = OpSelect %10 %99 %100 %98 -OpReturnValue %101 -OpFunctionEnd -%103 = OpFunction %2 None %104 +%95 = OpFunction %9 None %96 +%94 = OpLabel +%100 = OpVariable %101 Function %77 +OpBranch %102 %102 = OpLabel -OpBranch %111 -%111 = OpLabel -%112 = OpLogicalNot %8 %28 -%113 = OpLogicalNot %105 %106 -%114 = OpLogicalOr %8 %28 %30 -%115 = OpLogicalAnd %8 %28 %30 -%116 = OpLogicalOr %8 %28 %30 -%117 = OpLogicalOr %97 %107 %108 -%118 = OpLogicalAnd %8 %28 %30 -%119 = OpLogicalAnd %7 %109 %110 -OpReturn +%103 = OpLoad %9 %100 +%104 = OpFAdd %9 %103 %97 +OpStore %100 %104 +%105 = OpLoad %9 %100 +%106 = OpFSub %9 %105 %99 +OpStore %100 %106 +%107 = OpLoad %9 %100 +%108 = OpFDiv %9 %107 %79 +OpStore %100 %108 +%109 = OpLoad %9 %100 +OpReturnValue %109 OpFunctionEnd -%121 = OpFunction %2 None %104 +%112 = OpFunction %10 None %113 +%111 = OpFunctionParameter %10 +%110 = OpLabel +OpBranch %114 +%114 = OpLabel +%117 = OpFUnordNotEqual %115 %111 %116 +%119 = OpSelect %10 %117 %118 %116 +OpReturnValue %119 +OpFunctionEnd +%121 = OpFunction %2 None %122 %120 = OpLabel -OpBranch %138 -%138 = OpLabel -%139 = OpFNegate %3 %17 -%140 = OpSNegate %124 %125 -%141 = OpFNegate %9 %79 -%142 = OpIAdd %5 %64 %23 -%143 = OpIAdd %16 %123 %122 -%144 = OpFAdd %3 %58 %17 -%145 = OpIAdd %124 %126 %125 -%146 = OpIAdd %15 %127 %128 -%147 = OpFAdd %4 %129 %130 -%148 = OpISub %5 %64 %23 -%149 = OpISub %16 %123 %122 -%150 = OpFSub %3 %58 %17 -%151 = OpISub %124 %126 %125 -%152 = OpISub %15 %127 %128 -%153 = OpFSub %4 %129 %130 -%154 = OpIMul %5 %64 %23 -%155 = OpIMul %16 %123 %122 -%156 = OpFMul %3 %58 %17 -%157 = OpIMul %124 %126 %125 -%158 = OpIMul %15 %127 %128 -%159 = OpFMul %4 %129 %130 -%160 = OpSDiv %5 %64 %23 -%161 = OpUDiv %16 %123 %122 -%162 = OpFDiv %3 %58 %17 -%163 = OpSDiv %124 %126 %125 -%164 = OpUDiv %15 %127 %128 -%165 = OpFDiv %4 %129 %130 -%166 = OpSRem %5 %64 %23 -%167 = OpUMod %16 %123 %122 -%168 = OpFRem %3 %58 %17 -%169 = OpSRem %124 %126 %125 -%170 = OpUMod %15 %127 %128 -%171 = OpFRem %4 %129 %130 -OpBranch %172 -%172 = OpLabel -%174 = OpIAdd %124 %126 %125 -%175 = OpIAdd %124 %126 %125 -%176 = OpIAdd %131 %132 %133 -%177 = OpIAdd %131 %132 %133 -%178 = OpFAdd %9 %59 %79 -%179 = OpFAdd %9 %59 %79 -%180 = OpISub %124 %126 %125 -%181 = OpISub %124 %126 %125 -%182 = OpISub %131 %132 %133 -%183 = OpISub %131 %132 %133 -%184 = OpFSub %9 %59 %79 -%185 = OpFSub %9 %59 %79 -%187 = OpCompositeConstruct %124 %23 %23 -%186 = OpIMul %124 %126 %187 -%189 = OpCompositeConstruct %124 %64 %64 -%188 = OpIMul %124 %125 %189 -%191 = OpCompositeConstruct %131 %122 %122 -%190 = OpIMul %131 %132 %191 -%193 = OpCompositeConstruct %131 %123 %123 -%192 = OpIMul %131 %133 %193 -%194 = OpVectorTimesScalar %9 %59 %17 -%195 = OpVectorTimesScalar %9 %79 %58 -%196 = OpSDiv %124 %126 %125 -%197 = OpSDiv %124 %126 %125 -%198 = OpUDiv %131 %132 %133 -%199 = OpUDiv %131 %132 %133 -%200 = OpFDiv %9 %59 %79 -%201 = OpFDiv %9 %59 %79 -%202 = OpSRem %124 %126 %125 -%203 = OpSRem %124 %126 %125 -%204 = OpUMod %131 %132 %133 -%205 = OpUMod %131 %132 %133 -%206 = OpFRem %9 %59 %79 -%207 = OpFRem %9 %59 %79 -OpBranch %173 -%173 = OpLabel -%209 = OpCompositeExtract %10 %134 0 -%210 = OpCompositeExtract %10 %134 0 -%211 = OpFAdd %10 %209 %210 -%212 = OpCompositeExtract %10 %134 1 -%213 = OpCompositeExtract %10 %134 1 -%214 = OpFAdd %10 %212 %213 -%215 = OpCompositeExtract %10 %134 2 -%216 = OpCompositeExtract %10 %134 2 -%217 = OpFAdd %10 %215 %216 -%208 = OpCompositeConstruct %11 %211 %214 %217 -%219 = OpCompositeExtract %10 %134 0 -%220 = OpCompositeExtract %10 %134 0 -%221 = OpFSub %10 %219 %220 -%222 = OpCompositeExtract %10 %134 1 -%223 = OpCompositeExtract %10 %134 1 -%224 = OpFSub %10 %222 %223 -%225 = OpCompositeExtract %10 %134 2 -%226 = OpCompositeExtract %10 %134 2 -%227 = OpFSub %10 %225 %226 -%218 = OpCompositeConstruct %11 %221 %224 %227 -%228 = OpMatrixTimesScalar %11 %134 %17 -%229 = OpMatrixTimesScalar %11 %134 %58 -%230 = OpMatrixTimesVector %10 %135 %130 -%231 = OpVectorTimesMatrix %4 %136 %135 -%232 = OpMatrixTimesMatrix %11 %135 %137 +OpBranch %129 +%129 = OpLabel +%130 = OpLogicalNot %8 %28 +%131 = OpLogicalNot %123 %124 +%132 = OpLogicalOr %8 %28 %30 +%133 = OpLogicalAnd %8 %28 %30 +%134 = OpLogicalOr %8 %28 %30 +%135 = OpLogicalOr %115 %125 %126 +%136 = OpLogicalAnd %8 %28 %30 +%137 = OpLogicalAnd %7 %127 %128 +OpReturn +OpFunctionEnd +%138 = OpFunction %5 None %139 +%140 = OpFunctionParameter %5 +%141 = OpFunctionParameter %5 +%142 = OpLabel +%143 = OpIEqual %8 %141 %29 +%144 = OpIEqual %8 %140 %60 +%145 = OpIEqual %8 %141 %61 +%146 = OpLogicalAnd %8 %144 %145 +%147 = OpLogicalOr %8 %143 %146 +%148 = OpSelect %5 %147 %23 %141 +%149 = OpSDiv %5 %140 %148 +OpReturnValue %149 +OpFunctionEnd +%150 = OpFunction %16 None %151 +%152 = OpFunctionParameter %16 +%153 = OpFunctionParameter %16 +%154 = OpLabel +%156 = OpIEqual %8 %153 %155 +%158 = OpSelect %16 %156 %157 %153 +%159 = OpUDiv %16 %152 %158 +OpReturnValue %159 +OpFunctionEnd +%161 = OpFunction %160 None %162 +%163 = OpFunctionParameter %160 +%164 = OpFunctionParameter %160 +%165 = OpLabel +%167 = OpIEqual %123 %164 %166 +%170 = OpIEqual %123 %163 %168 +%171 = OpIEqual %123 %164 %169 +%172 = OpLogicalAnd %123 %170 %171 +%173 = OpLogicalOr %123 %167 %172 +%175 = OpSelect %160 %173 %174 %164 +%176 = OpSDiv %160 %163 %175 +OpReturnValue %176 +OpFunctionEnd +%177 = OpFunction %15 None %178 +%179 = OpFunctionParameter %15 +%180 = OpFunctionParameter %15 +%181 = OpLabel +%183 = OpIEqual %115 %180 %182 +%185 = OpSelect %15 %183 %184 %180 +%186 = OpUDiv %15 %179 %185 +OpReturnValue %186 +OpFunctionEnd +%187 = OpFunction %5 None %139 +%188 = OpFunctionParameter %5 +%189 = OpFunctionParameter %5 +%190 = OpLabel +%191 = OpIEqual %8 %189 %29 +%192 = OpIEqual %8 %188 %60 +%193 = OpIEqual %8 %189 %61 +%194 = OpLogicalAnd %8 %192 %193 +%195 = OpLogicalOr %8 %191 %194 +%196 = OpSelect %5 %195 %23 %189 +%197 = OpSRem %5 %188 %196 +OpReturnValue %197 +OpFunctionEnd +%198 = OpFunction %16 None %151 +%199 = OpFunctionParameter %16 +%200 = OpFunctionParameter %16 +%201 = OpLabel +%202 = OpIEqual %8 %200 %155 +%203 = OpSelect %16 %202 %157 %200 +%204 = OpUMod %16 %199 %203 +OpReturnValue %204 +OpFunctionEnd +%205 = OpFunction %160 None %162 +%206 = OpFunctionParameter %160 +%207 = OpFunctionParameter %160 +%208 = OpLabel +%209 = OpIEqual %123 %207 %166 +%210 = OpIEqual %123 %206 %168 +%211 = OpIEqual %123 %207 %169 +%212 = OpLogicalAnd %123 %210 %211 +%213 = OpLogicalOr %123 %209 %212 +%214 = OpSelect %160 %213 %174 %207 +%215 = OpSRem %160 %206 %214 +OpReturnValue %215 +OpFunctionEnd +%216 = OpFunction %15 None %178 +%217 = OpFunctionParameter %15 +%218 = OpFunctionParameter %15 +%219 = OpLabel +%220 = OpIEqual %115 %218 %182 +%221 = OpSelect %15 %220 %184 %218 +%222 = OpUMod %15 %217 %221 +OpReturnValue %222 +OpFunctionEnd +%224 = OpFunction %223 None %225 +%226 = OpFunctionParameter %223 +%227 = OpFunctionParameter %223 +%228 = OpLabel +%230 = OpIEqual %123 %227 %229 +%232 = OpSelect %223 %230 %231 %227 +%233 = OpUDiv %223 %226 %232 +OpReturnValue %233 +OpFunctionEnd +%234 = OpFunction %223 None %225 +%235 = OpFunctionParameter %223 +%236 = OpFunctionParameter %223 +%237 = OpLabel +%238 = OpIEqual %123 %236 %229 +%239 = OpSelect %223 %238 %231 %236 +%240 = OpUMod %223 %235 %239 +OpReturnValue %240 +OpFunctionEnd +%242 = OpFunction %2 None %122 +%241 = OpLabel +OpBranch %253 +%253 = OpLabel +%254 = OpFNegate %3 %17 +%255 = OpSNegate %160 %174 +%256 = OpFNegate %9 %97 +%257 = OpIAdd %5 %82 %23 +%258 = OpIAdd %16 %243 %157 +%259 = OpFAdd %3 %76 %17 +%260 = OpIAdd %160 %244 %174 +%261 = OpIAdd %15 %245 %184 +%262 = OpFAdd %4 %246 %247 +%263 = OpISub %5 %82 %23 +%264 = OpISub %16 %243 %157 +%265 = OpFSub %3 %76 %17 +%266 = OpISub %160 %244 %174 +%267 = OpISub %15 %245 %184 +%268 = OpFSub %4 %246 %247 +%269 = OpIMul %5 %82 %23 +%270 = OpIMul %16 %243 %157 +%271 = OpFMul %3 %76 %17 +%272 = OpIMul %160 %244 %174 +%273 = OpIMul %15 %245 %184 +%274 = OpFMul %4 %246 %247 +%275 = OpFunctionCall %5 %138 %82 %23 +%276 = OpFunctionCall %16 %150 %243 %157 +%277 = OpFDiv %3 %76 %17 +%278 = OpFunctionCall %160 %161 %244 %174 +%279 = OpFunctionCall %15 %177 %245 %184 +%280 = OpFDiv %4 %246 %247 +%281 = OpFunctionCall %5 %187 %82 %23 +%282 = OpFunctionCall %16 %198 %243 %157 +%283 = OpFRem %3 %76 %17 +%284 = OpFunctionCall %160 %205 %244 %174 +%285 = OpFunctionCall %15 %216 %245 %184 +%286 = OpFRem %4 %246 %247 +OpBranch %287 +%287 = OpLabel +%289 = OpIAdd %160 %244 %174 +%290 = OpIAdd %160 %244 %174 +%291 = OpIAdd %223 %248 %231 +%292 = OpIAdd %223 %248 %231 +%293 = OpFAdd %9 %77 %97 +%294 = OpFAdd %9 %77 %97 +%295 = OpISub %160 %244 %174 +%296 = OpISub %160 %244 %174 +%297 = OpISub %223 %248 %231 +%298 = OpISub %223 %248 %231 +%299 = OpFSub %9 %77 %97 +%300 = OpFSub %9 %77 %97 +%302 = OpCompositeConstruct %160 %23 %23 +%301 = OpIMul %160 %244 %302 +%304 = OpCompositeConstruct %160 %82 %82 +%303 = OpIMul %160 %174 %304 +%306 = OpCompositeConstruct %223 %157 %157 +%305 = OpIMul %223 %248 %306 +%308 = OpCompositeConstruct %223 %243 %243 +%307 = OpIMul %223 %231 %308 +%309 = OpVectorTimesScalar %9 %77 %17 +%310 = OpVectorTimesScalar %9 %97 %76 +%311 = OpFunctionCall %160 %161 %244 %174 +%312 = OpFunctionCall %160 %161 %244 %174 +%313 = OpFunctionCall %223 %224 %248 %231 +%314 = OpFunctionCall %223 %224 %248 %231 +%315 = OpFDiv %9 %77 %97 +%316 = OpFDiv %9 %77 %97 +%317 = OpFunctionCall %160 %205 %244 %174 +%318 = OpFunctionCall %160 %205 %244 %174 +%319 = OpFunctionCall %223 %234 %248 %231 +%320 = OpFunctionCall %223 %234 %248 %231 +%321 = OpFRem %9 %77 %97 +%322 = OpFRem %9 %77 %97 +OpBranch %288 +%288 = OpLabel +%324 = OpCompositeExtract %10 %249 0 +%325 = OpCompositeExtract %10 %249 0 +%326 = OpFAdd %10 %324 %325 +%327 = OpCompositeExtract %10 %249 1 +%328 = OpCompositeExtract %10 %249 1 +%329 = OpFAdd %10 %327 %328 +%330 = OpCompositeExtract %10 %249 2 +%331 = OpCompositeExtract %10 %249 2 +%332 = OpFAdd %10 %330 %331 +%323 = OpCompositeConstruct %11 %326 %329 %332 +%334 = OpCompositeExtract %10 %249 0 +%335 = OpCompositeExtract %10 %249 0 +%336 = OpFSub %10 %334 %335 +%337 = OpCompositeExtract %10 %249 1 +%338 = OpCompositeExtract %10 %249 1 +%339 = OpFSub %10 %337 %338 +%340 = OpCompositeExtract %10 %249 2 +%341 = OpCompositeExtract %10 %249 2 +%342 = OpFSub %10 %340 %341 +%333 = OpCompositeConstruct %11 %336 %339 %342 +%343 = OpMatrixTimesScalar %11 %249 %17 +%344 = OpMatrixTimesScalar %11 %249 %76 +%345 = OpMatrixTimesVector %10 %250 %247 +%346 = OpVectorTimesMatrix %4 %251 %250 +%347 = OpMatrixTimesMatrix %11 %250 %252 OpReturn OpFunctionEnd -%234 = OpFunction %2 None %104 -%233 = OpLabel -OpBranch %235 -%235 = OpLabel -%236 = OpNot %5 %23 -%237 = OpNot %16 %122 -%238 = OpNot %124 %125 -%239 = OpNot %15 %128 -%240 = OpBitwiseOr %5 %64 %23 -%241 = OpBitwiseOr %16 %123 %122 -%242 = OpBitwiseOr %124 %126 %125 -%243 = OpBitwiseOr %15 %127 %128 -%244 = OpBitwiseAnd %5 %64 %23 -%245 = OpBitwiseAnd %16 %123 %122 -%246 = OpBitwiseAnd %124 %126 %125 -%247 = OpBitwiseAnd %15 %127 %128 -%248 = OpBitwiseXor %5 %64 %23 -%249 = OpBitwiseXor %16 %123 %122 -%250 = OpBitwiseXor %124 %126 %125 -%251 = OpBitwiseXor %15 %127 %128 -%252 = OpShiftLeftLogical %5 %64 %122 -%253 = OpShiftLeftLogical %16 %123 %122 -%254 = OpShiftLeftLogical %124 %126 %133 -%255 = OpShiftLeftLogical %15 %127 %128 -%256 = OpShiftRightArithmetic %5 %64 %122 -%257 = OpShiftRightLogical %16 %123 %122 -%258 = OpShiftRightArithmetic %124 %126 %133 -%259 = OpShiftRightLogical %15 %127 %128 +%349 = OpFunction %2 None %122 +%348 = OpLabel +OpBranch %350 +%350 = OpLabel +%351 = OpNot %5 %23 +%352 = OpNot %16 %157 +%353 = OpNot %160 %174 +%354 = OpNot %15 %184 +%355 = OpBitwiseOr %5 %82 %23 +%356 = OpBitwiseOr %16 %243 %157 +%357 = OpBitwiseOr %160 %244 %174 +%358 = OpBitwiseOr %15 %245 %184 +%359 = OpBitwiseAnd %5 %82 %23 +%360 = OpBitwiseAnd %16 %243 %157 +%361 = OpBitwiseAnd %160 %244 %174 +%362 = OpBitwiseAnd %15 %245 %184 +%363 = OpBitwiseXor %5 %82 %23 +%364 = OpBitwiseXor %16 %243 %157 +%365 = OpBitwiseXor %160 %244 %174 +%366 = OpBitwiseXor %15 %245 %184 +%367 = OpShiftLeftLogical %5 %82 %157 +%368 = OpShiftLeftLogical %16 %243 %157 +%369 = OpShiftLeftLogical %160 %244 %231 +%370 = OpShiftLeftLogical %15 %245 %184 +%371 = OpShiftRightArithmetic %5 %82 %157 +%372 = OpShiftRightLogical %16 %243 %157 +%373 = OpShiftRightArithmetic %160 %244 %231 +%374 = OpShiftRightLogical %15 %245 %184 OpReturn OpFunctionEnd -%261 = OpFunction %2 None %104 -%260 = OpLabel -OpBranch %262 -%262 = OpLabel -%263 = OpIEqual %8 %64 %23 -%264 = OpIEqual %8 %123 %122 -%265 = OpFOrdEqual %8 %58 %17 -%266 = OpIEqual %105 %126 %125 -%267 = OpIEqual %97 %127 %128 -%268 = OpFOrdEqual %7 %129 %130 -%269 = OpINotEqual %8 %64 %23 -%270 = OpINotEqual %8 %123 %122 -%271 = OpFOrdNotEqual %8 %58 %17 -%272 = OpINotEqual %105 %126 %125 -%273 = OpINotEqual %97 %127 %128 -%274 = OpFOrdNotEqual %7 %129 %130 -%275 = OpSLessThan %8 %64 %23 -%276 = OpULessThan %8 %123 %122 -%277 = OpFOrdLessThan %8 %58 %17 -%278 = OpSLessThan %105 %126 %125 -%279 = OpULessThan %97 %127 %128 -%280 = OpFOrdLessThan %7 %129 %130 -%281 = OpSLessThanEqual %8 %64 %23 -%282 = OpULessThanEqual %8 %123 %122 -%283 = OpFOrdLessThanEqual %8 %58 %17 -%284 = OpSLessThanEqual %105 %126 %125 -%285 = OpULessThanEqual %97 %127 %128 -%286 = OpFOrdLessThanEqual %7 %129 %130 -%287 = OpSGreaterThan %8 %64 %23 -%288 = OpUGreaterThan %8 %123 %122 -%289 = OpFOrdGreaterThan %8 %58 %17 -%290 = OpSGreaterThan %105 %126 %125 -%291 = OpUGreaterThan %97 %127 %128 -%292 = OpFOrdGreaterThan %7 %129 %130 -%293 = OpSGreaterThanEqual %8 %64 %23 -%294 = OpUGreaterThanEqual %8 %123 %122 -%295 = OpFOrdGreaterThanEqual %8 %58 %17 -%296 = OpSGreaterThanEqual %105 %126 %125 -%297 = OpUGreaterThanEqual %97 %127 %128 -%298 = OpFOrdGreaterThanEqual %7 %129 %130 +%376 = OpFunction %2 None %122 +%375 = OpLabel +OpBranch %377 +%377 = OpLabel +%378 = OpIEqual %8 %82 %23 +%379 = OpIEqual %8 %243 %157 +%380 = OpFOrdEqual %8 %76 %17 +%381 = OpIEqual %123 %244 %174 +%382 = OpIEqual %115 %245 %184 +%383 = OpFOrdEqual %7 %246 %247 +%384 = OpINotEqual %8 %82 %23 +%385 = OpINotEqual %8 %243 %157 +%386 = OpFOrdNotEqual %8 %76 %17 +%387 = OpINotEqual %123 %244 %174 +%388 = OpINotEqual %115 %245 %184 +%389 = OpFOrdNotEqual %7 %246 %247 +%390 = OpSLessThan %8 %82 %23 +%391 = OpULessThan %8 %243 %157 +%392 = OpFOrdLessThan %8 %76 %17 +%393 = OpSLessThan %123 %244 %174 +%394 = OpULessThan %115 %245 %184 +%395 = OpFOrdLessThan %7 %246 %247 +%396 = OpSLessThanEqual %8 %82 %23 +%397 = OpULessThanEqual %8 %243 %157 +%398 = OpFOrdLessThanEqual %8 %76 %17 +%399 = OpSLessThanEqual %123 %244 %174 +%400 = OpULessThanEqual %115 %245 %184 +%401 = OpFOrdLessThanEqual %7 %246 %247 +%402 = OpSGreaterThan %8 %82 %23 +%403 = OpUGreaterThan %8 %243 %157 +%404 = OpFOrdGreaterThan %8 %76 %17 +%405 = OpSGreaterThan %123 %244 %174 +%406 = OpUGreaterThan %115 %245 %184 +%407 = OpFOrdGreaterThan %7 %246 %247 +%408 = OpSGreaterThanEqual %8 %82 %23 +%409 = OpUGreaterThanEqual %8 %243 %157 +%410 = OpFOrdGreaterThanEqual %8 %76 %17 +%411 = OpSGreaterThanEqual %123 %244 %174 +%412 = OpUGreaterThanEqual %115 %245 %184 +%413 = OpFOrdGreaterThanEqual %7 %246 %247 OpReturn OpFunctionEnd -%300 = OpFunction %2 None %104 -%299 = OpLabel -%302 = OpVariable %303 Function %304 -%305 = OpVariable %306 Function %301 -OpBranch %307 -%307 = OpLabel -OpStore %302 %23 -%308 = OpLoad %5 %302 -%309 = OpIAdd %5 %308 %23 -OpStore %302 %309 -%310 = OpLoad %5 %302 -%311 = OpISub %5 %310 %23 -OpStore %302 %311 -%312 = OpLoad %5 %302 -%313 = OpLoad %5 %302 -%314 = OpIMul %5 %313 %312 -OpStore %302 %314 -%315 = OpLoad %5 %302 -%316 = OpLoad %5 %302 -%317 = OpSDiv %5 %316 %315 -OpStore %302 %317 -%318 = OpLoad %5 %302 -%319 = OpSRem %5 %318 %23 -OpStore %302 %319 -%320 = OpLoad %5 %302 -%321 = OpBitwiseAnd %5 %320 %29 -OpStore %302 %321 -%322 = OpLoad %5 %302 -%323 = OpBitwiseOr %5 %322 %29 -OpStore %302 %323 -%324 = OpLoad %5 %302 -%325 = OpBitwiseXor %5 %324 %29 -OpStore %302 %325 -%326 = OpLoad %5 %302 -%327 = OpShiftLeftLogical %5 %326 %123 -OpStore %302 %327 -%328 = OpLoad %5 %302 -%329 = OpShiftRightArithmetic %5 %328 %122 -OpStore %302 %329 -%330 = OpLoad %5 %302 -%331 = OpIAdd %5 %330 %23 -OpStore %302 %331 -%332 = OpLoad %5 %302 -%333 = OpISub %5 %332 %23 -OpStore %302 %333 -%335 = OpAccessChain %334 %305 %122 -%336 = OpLoad %5 %335 -%337 = OpIAdd %5 %336 %23 -%338 = OpAccessChain %334 %305 %122 -OpStore %338 %337 -%339 = OpAccessChain %334 %305 %122 -%340 = OpLoad %5 %339 -%341 = OpISub %5 %340 %23 -%342 = OpAccessChain %334 %305 %122 -OpStore %342 %341 +%415 = OpFunction %2 None %122 +%414 = OpLabel +%417 = OpVariable %418 Function %419 +%420 = OpVariable %421 Function %416 +OpBranch %422 +%422 = OpLabel +OpStore %417 %23 +%423 = OpLoad %5 %417 +%424 = OpIAdd %5 %423 %23 +OpStore %417 %424 +%425 = OpLoad %5 %417 +%426 = OpISub %5 %425 %23 +OpStore %417 %426 +%427 = OpLoad %5 %417 +%428 = OpLoad %5 %417 +%429 = OpIMul %5 %428 %427 +OpStore %417 %429 +%430 = OpLoad %5 %417 +%431 = OpLoad %5 %417 +%432 = OpFunctionCall %5 %138 %431 %430 +OpStore %417 %432 +%433 = OpLoad %5 %417 +%434 = OpFunctionCall %5 %187 %433 %23 +OpStore %417 %434 +%435 = OpLoad %5 %417 +%436 = OpBitwiseAnd %5 %435 %29 +OpStore %417 %436 +%437 = OpLoad %5 %417 +%438 = OpBitwiseOr %5 %437 %29 +OpStore %417 %438 +%439 = OpLoad %5 %417 +%440 = OpBitwiseXor %5 %439 %29 +OpStore %417 %440 +%441 = OpLoad %5 %417 +%442 = OpShiftLeftLogical %5 %441 %243 +OpStore %417 %442 +%443 = OpLoad %5 %417 +%444 = OpShiftRightArithmetic %5 %443 %157 +OpStore %417 %444 +%445 = OpLoad %5 %417 +%446 = OpIAdd %5 %445 %23 +OpStore %417 %446 +%447 = OpLoad %5 %417 +%448 = OpISub %5 %447 %23 +OpStore %417 %448 +%450 = OpAccessChain %449 %420 %157 +%451 = OpLoad %5 %450 +%452 = OpIAdd %5 %451 %23 +%453 = OpAccessChain %449 %420 %157 +OpStore %453 %452 +%454 = OpAccessChain %449 %420 %157 +%455 = OpLoad %5 %454 +%456 = OpISub %5 %455 %23 +%457 = OpAccessChain %449 %420 %157 +OpStore %457 %456 OpReturn OpFunctionEnd -%344 = OpFunction %2 None %104 -%343 = OpLabel -OpBranch %345 -%345 = OpLabel -%346 = OpSNegate %5 %23 -%347 = OpSNegate %5 %23 -%348 = OpSNegate %5 %347 -%349 = OpSNegate %5 %23 -%350 = OpSNegate %5 %349 -%351 = OpSNegate %5 %23 -%352 = OpSNegate %5 %351 -%353 = OpSNegate %5 %23 -%354 = OpSNegate %5 %353 -%355 = OpSNegate %5 %354 -%356 = OpSNegate %5 %23 -%357 = OpSNegate %5 %356 -%358 = OpSNegate %5 %357 -%359 = OpSNegate %5 %358 -%360 = OpSNegate %5 %23 -%361 = OpSNegate %5 %360 -%362 = OpSNegate %5 %361 -%363 = OpSNegate %5 %362 -%364 = OpSNegate %5 %363 -%365 = OpSNegate %5 %23 -%366 = OpSNegate %5 %365 -%367 = OpSNegate %5 %366 -%368 = OpSNegate %5 %367 -%369 = OpSNegate %5 %368 +%459 = OpFunction %2 None %122 +%458 = OpLabel +OpBranch %460 +%460 = OpLabel +%461 = OpSNegate %5 %23 +%462 = OpSNegate %5 %23 +%463 = OpSNegate %5 %462 +%464 = OpSNegate %5 %23 +%465 = OpSNegate %5 %464 +%466 = OpSNegate %5 %23 +%467 = OpSNegate %5 %466 +%468 = OpSNegate %5 %23 +%469 = OpSNegate %5 %468 +%470 = OpSNegate %5 %469 +%471 = OpSNegate %5 %23 +%472 = OpSNegate %5 %471 +%473 = OpSNegate %5 %472 +%474 = OpSNegate %5 %473 +%475 = OpSNegate %5 %23 +%476 = OpSNegate %5 %475 +%477 = OpSNegate %5 %476 +%478 = OpSNegate %5 %477 +%479 = OpSNegate %5 %478 +%480 = OpSNegate %5 %23 +%481 = OpSNegate %5 %480 +%482 = OpSNegate %5 %481 +%483 = OpSNegate %5 %482 +%484 = OpSNegate %5 %483 +%485 = OpFNegate %3 %17 +%486 = OpFNegate %3 %17 +%487 = OpFNegate %3 %486 +%488 = OpFNegate %3 %17 +%489 = OpFNegate %3 %488 +%490 = OpFNegate %3 %17 +%491 = OpFNegate %3 %490 +%492 = OpFNegate %3 %17 +%493 = OpFNegate %3 %492 +%494 = OpFNegate %3 %493 +%495 = OpFNegate %3 %17 +%496 = OpFNegate %3 %495 +%497 = OpFNegate %3 %496 +%498 = OpFNegate %3 %497 +%499 = OpFNegate %3 %17 +%500 = OpFNegate %3 %499 +%501 = OpFNegate %3 %500 +%502 = OpFNegate %3 %501 +%503 = OpFNegate %3 %502 +%504 = OpFNegate %3 %17 +%505 = OpFNegate %3 %504 +%506 = OpFNegate %3 %505 +%507 = OpFNegate %3 %506 +%508 = OpFNegate %3 %507 OpReturn OpFunctionEnd -%374 = OpFunction %2 None %104 -%370 = OpLabel -%373 = OpLoad %15 %371 -OpBranch %376 -%376 = OpLabel -%377 = OpFunctionCall %4 %26 -%378 = OpCompositeExtract %16 %373 0 -%379 = OpConvertUToF %3 %378 -%380 = OpCompositeExtract %16 %373 1 -%381 = OpBitcast %5 %380 -%382 = OpFunctionCall %4 %56 %379 %381 -%383 = OpFunctionCall %10 %94 %375 -%384 = OpFunctionCall %2 %103 -%385 = OpFunctionCall %2 %121 -%386 = OpFunctionCall %2 %234 -%387 = OpFunctionCall %2 %261 -%388 = OpFunctionCall %2 %300 +%513 = OpFunction %2 None %122 +%509 = OpLabel +%512 = OpLoad %15 %510 +OpBranch %515 +%515 = OpLabel +%516 = OpFunctionCall %4 %26 +%517 = OpCompositeExtract %16 %512 0 +%518 = OpConvertUToF %3 %517 +%519 = OpCompositeExtract %16 %512 1 +%520 = OpBitcast %5 %519 +%521 = OpFunctionCall %4 %74 %518 %520 +%522 = OpFunctionCall %10 %112 %514 +%523 = OpFunctionCall %2 %121 +%524 = OpFunctionCall %2 %242 +%525 = OpFunctionCall %2 %349 +%526 = OpFunctionCall %2 %376 +%527 = OpFunctionCall %2 %415 OpReturn OpFunctionEnd \ No newline at end of file diff --git a/naga/tests/out/spv/skybox.spvasm b/naga/tests/out/spv/skybox.spvasm index 4d541321a9..7bc7b30f6d 100644 --- a/naga/tests/out/spv/skybox.spvasm +++ b/naga/tests/out/spv/skybox.spvasm @@ -1,13 +1,13 @@ ; SPIR-V ; Version: 1.0 ; Generator: rspirv -; Bound: 98 +; Bound: 114 OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint Vertex %29 "vs_main" %22 %25 %27 -OpEntryPoint Fragment %90 "fs_main" %83 %86 %89 -OpExecutionMode %90 OriginUpperLeft +OpEntryPoint Vertex %46 "vs_main" %39 %42 %44 +OpEntryPoint Fragment %106 "fs_main" %99 %102 %105 +OpExecutionMode %106 OriginUpperLeft OpMemberDecorate %6 0 Offset 0 OpMemberDecorate %6 1 Offset 16 OpMemberDecorate %8 0 Offset 0 @@ -24,12 +24,12 @@ OpDecorate %17 DescriptorSet 0 OpDecorate %17 Binding 1 OpDecorate %19 DescriptorSet 0 OpDecorate %19 Binding 2 -OpDecorate %22 BuiltIn VertexIndex -OpDecorate %25 BuiltIn Position -OpDecorate %27 Location 0 -OpDecorate %83 BuiltIn FragCoord -OpDecorate %86 Location 0 -OpDecorate %89 Location 0 +OpDecorate %39 BuiltIn VertexIndex +OpDecorate %42 BuiltIn Position +OpDecorate %44 Location 0 +OpDecorate %99 BuiltIn FragCoord +OpDecorate %102 Location 0 +OpDecorate %105 Location 0 %2 = OpTypeVoid %4 = OpTypeFloat 32 %3 = OpTypeVector %4 4 @@ -49,91 +49,109 @@ OpDecorate %89 Location 0 %17 = OpVariable %18 UniformConstant %20 = OpTypePointer UniformConstant %13 %19 = OpVariable %20 UniformConstant -%23 = OpTypePointer Input %9 -%22 = OpVariable %23 Input -%26 = OpTypePointer Output %3 -%25 = OpVariable %26 Output -%28 = OpTypePointer Output %5 -%27 = OpVariable %28 Output -%30 = OpTypeFunction %2 -%31 = OpTypePointer Uniform %8 -%32 = OpConstant %9 0 -%34 = OpConstant %10 2 +%22 = OpTypeFunction %10 %10 %10 +%26 = OpTypeBool +%27 = OpConstant %10 0 +%29 = OpConstant %10 -2147483648 +%30 = OpConstant %10 -1 %35 = OpConstant %10 1 -%36 = OpConstant %4 4.0 -%37 = OpConstant %4 1.0 -%38 = OpConstant %4 0.0 -%40 = OpTypePointer Function %10 -%41 = OpConstantNull %10 -%43 = OpConstantNull %10 -%58 = OpTypePointer Uniform %7 -%59 = OpTypePointer Uniform %3 -%60 = OpConstant %9 1 -%67 = OpConstant %9 2 -%84 = OpTypePointer Input %3 -%83 = OpVariable %84 Input -%87 = OpTypePointer Input %5 -%86 = OpVariable %87 Input -%89 = OpVariable %26 Output -%95 = OpTypeSampledImage %12 -%29 = OpFunction %2 None %30 -%21 = OpLabel -%39 = OpVariable %40 Function %41 -%42 = OpVariable %40 Function %43 -%24 = OpLoad %9 %22 -%33 = OpAccessChain %31 %14 %32 -OpBranch %44 -%44 = OpLabel -%45 = OpBitcast %10 %24 -%46 = OpSDiv %10 %45 %34 -OpStore %39 %46 -%47 = OpBitcast %10 %24 -%48 = OpBitwiseAnd %10 %47 %35 -OpStore %42 %48 -%49 = OpLoad %10 %39 -%50 = OpConvertSToF %4 %49 -%51 = OpFMul %4 %50 %36 -%52 = OpFSub %4 %51 %37 -%53 = OpLoad %10 %42 -%54 = OpConvertSToF %4 %53 -%55 = OpFMul %4 %54 %36 -%56 = OpFSub %4 %55 %37 -%57 = OpCompositeConstruct %3 %52 %56 %38 %37 -%61 = OpAccessChain %59 %33 %60 %32 -%62 = OpLoad %3 %61 -%63 = OpVectorShuffle %5 %62 %62 0 1 2 -%64 = OpAccessChain %59 %33 %60 %60 -%65 = OpLoad %3 %64 -%66 = OpVectorShuffle %5 %65 %65 0 1 2 -%68 = OpAccessChain %59 %33 %60 %67 -%69 = OpLoad %3 %68 -%70 = OpVectorShuffle %5 %69 %69 0 1 2 -%71 = OpCompositeConstruct %11 %63 %66 %70 -%72 = OpTranspose %11 %71 -%73 = OpAccessChain %58 %33 %32 -%74 = OpLoad %7 %73 -%75 = OpMatrixTimesVector %3 %74 %57 -%76 = OpVectorShuffle %5 %75 %75 0 1 2 -%77 = OpMatrixTimesVector %5 %72 %76 -%78 = OpCompositeConstruct %6 %57 %77 -%79 = OpCompositeExtract %3 %78 0 -OpStore %25 %79 -%80 = OpCompositeExtract %5 %78 1 -OpStore %27 %80 +%40 = OpTypePointer Input %9 +%39 = OpVariable %40 Input +%43 = OpTypePointer Output %3 +%42 = OpVariable %43 Output +%45 = OpTypePointer Output %5 +%44 = OpVariable %45 Output +%47 = OpTypeFunction %2 +%48 = OpTypePointer Uniform %8 +%49 = OpConstant %9 0 +%51 = OpConstant %10 2 +%52 = OpConstant %4 4.0 +%53 = OpConstant %4 1.0 +%54 = OpConstant %4 0.0 +%56 = OpTypePointer Function %10 +%57 = OpConstantNull %10 +%59 = OpConstantNull %10 +%74 = OpTypePointer Uniform %7 +%75 = OpTypePointer Uniform %3 +%76 = OpConstant %9 1 +%83 = OpConstant %9 2 +%100 = OpTypePointer Input %3 +%99 = OpVariable %100 Input +%103 = OpTypePointer Input %5 +%102 = OpVariable %103 Input +%105 = OpVariable %43 Output +%111 = OpTypeSampledImage %12 +%21 = OpFunction %10 None %22 +%23 = OpFunctionParameter %10 +%24 = OpFunctionParameter %10 +%25 = OpLabel +%28 = OpIEqual %26 %24 %27 +%31 = OpIEqual %26 %23 %29 +%32 = OpIEqual %26 %24 %30 +%33 = OpLogicalAnd %26 %31 %32 +%34 = OpLogicalOr %26 %28 %33 +%36 = OpSelect %10 %34 %35 %24 +%37 = OpSDiv %10 %23 %36 +OpReturnValue %37 +OpFunctionEnd +%46 = OpFunction %2 None %47 +%38 = OpLabel +%55 = OpVariable %56 Function %57 +%58 = OpVariable %56 Function %59 +%41 = OpLoad %9 %39 +%50 = OpAccessChain %48 %14 %49 +OpBranch %60 +%60 = OpLabel +%61 = OpBitcast %10 %41 +%62 = OpFunctionCall %10 %21 %61 %51 +OpStore %55 %62 +%63 = OpBitcast %10 %41 +%64 = OpBitwiseAnd %10 %63 %35 +OpStore %58 %64 +%65 = OpLoad %10 %55 +%66 = OpConvertSToF %4 %65 +%67 = OpFMul %4 %66 %52 +%68 = OpFSub %4 %67 %53 +%69 = OpLoad %10 %58 +%70 = OpConvertSToF %4 %69 +%71 = OpFMul %4 %70 %52 +%72 = OpFSub %4 %71 %53 +%73 = OpCompositeConstruct %3 %68 %72 %54 %53 +%77 = OpAccessChain %75 %50 %76 %49 +%78 = OpLoad %3 %77 +%79 = OpVectorShuffle %5 %78 %78 0 1 2 +%80 = OpAccessChain %75 %50 %76 %76 +%81 = OpLoad %3 %80 +%82 = OpVectorShuffle %5 %81 %81 0 1 2 +%84 = OpAccessChain %75 %50 %76 %83 +%85 = OpLoad %3 %84 +%86 = OpVectorShuffle %5 %85 %85 0 1 2 +%87 = OpCompositeConstruct %11 %79 %82 %86 +%88 = OpTranspose %11 %87 +%89 = OpAccessChain %74 %50 %49 +%90 = OpLoad %7 %89 +%91 = OpMatrixTimesVector %3 %90 %73 +%92 = OpVectorShuffle %5 %91 %91 0 1 2 +%93 = OpMatrixTimesVector %5 %88 %92 +%94 = OpCompositeConstruct %6 %73 %93 +%95 = OpCompositeExtract %3 %94 0 +OpStore %42 %95 +%96 = OpCompositeExtract %5 %94 1 +OpStore %44 %96 OpReturn OpFunctionEnd -%90 = OpFunction %2 None %30 -%81 = OpLabel -%85 = OpLoad %3 %83 -%88 = OpLoad %5 %86 -%82 = OpCompositeConstruct %6 %85 %88 -%91 = OpLoad %12 %17 -%92 = OpLoad %13 %19 -OpBranch %93 -%93 = OpLabel -%94 = OpCompositeExtract %5 %82 1 -%96 = OpSampledImage %95 %91 %92 -%97 = OpImageSampleImplicitLod %3 %96 %94 -OpStore %89 %97 +%106 = OpFunction %2 None %47 +%97 = OpLabel +%101 = OpLoad %3 %99 +%104 = OpLoad %5 %102 +%98 = OpCompositeConstruct %6 %101 %104 +%107 = OpLoad %12 %17 +%108 = OpLoad %13 %19 +OpBranch %109 +%109 = OpLabel +%110 = OpCompositeExtract %5 %98 1 +%112 = OpSampledImage %111 %107 %108 +%113 = OpImageSampleImplicitLod %3 %112 %110 +OpStore %105 %113 OpReturn OpFunctionEnd \ No newline at end of file diff --git a/naga/tests/out/wgsl/operators.wgsl b/naga/tests/out/wgsl/operators.wgsl index 4a6f1c8ab4..0927b831a0 100644 --- a/naga/tests/out/wgsl/operators.wgsl +++ b/naga/tests/out/wgsl/operators.wgsl @@ -234,14 +234,22 @@ fn assignment() { } fn negation_avoids_prefix_decrement() { - const p0_ = -(1i); - const p1_ = -(-(1i)); - const p2_ = -(-(1i)); - const p3_ = -(-(1i)); - const p4_ = -(-(-(1i))); - const p5_ = -(-(-(-(1i)))); - const p6_ = -(-(-(-(-(1i))))); - const p7_ = -(-(-(-(-(1i))))); + const i0_ = -(1i); + const i1_ = -(-(1i)); + const i2_ = -(-(1i)); + const i3_ = -(-(1i)); + const i4_ = -(-(-(1i))); + const i5_ = -(-(-(-(1i)))); + const i6_ = -(-(-(-(-(1i))))); + const i7_ = -(-(-(-(-(1i))))); + const f0_ = -(1f); + const f1_ = -(-(1f)); + const f2_ = -(-(1f)); + const f3_ = -(-(1f)); + const f4_ = -(-(-(1f))); + const f5_ = -(-(-(-(1f)))); + const f6_ = -(-(-(-(-(1f))))); + const f7_ = -(-(-(-(-(1f))))); return; } diff --git a/player/src/bin/play.rs b/player/src/bin/play.rs index 7c8ec3f3cf..936e4a34ca 100644 --- a/player/src/bin/play.rs +++ b/player/src/bin/play.rs @@ -111,7 +111,7 @@ fn main() { } global.device_stop_capture(device); - global.device_poll(device, wgt::Maintain::wait()).unwrap(); + global.device_poll(device, wgt::PollType::wait()).unwrap(); } #[cfg(feature = "winit")] { @@ -203,7 +203,7 @@ fn main() { }, Event::LoopExiting => { log::info!("Closing"); - global.device_poll(device, wgt::Maintain::wait()).unwrap(); + global.device_poll(device, wgt::PollType::wait()).unwrap(); } _ => {} } diff --git a/player/tests/test.rs b/player/tests/test.rs index 4382f2f514..1254a7032f 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -133,7 +133,7 @@ impl Test<'_> { println!("\t\t\tWaiting..."); global - .device_poll(device_id, wgt::Maintain::wait()) + .device_poll(device_id, wgt::PollType::wait()) .unwrap(); for expect in self.expectations { diff --git a/tests/src/image.rs b/tests/src/image.rs index df74af309d..dee861b22d 100644 --- a/tests/src/image.rs +++ b/tests/src/image.rs @@ -574,7 +574,7 @@ impl ReadbackBuffers { ) -> Vec { let buffer_slice = buffer.slice(..); buffer_slice.map_async(MapMode::Read, |_| ()); - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); let (block_width, block_height) = self.texture_format.block_dimensions(); let expected_bytes_per_row = (self.texture_width / block_width) * self.texture_format.block_copy_size(aspect).unwrap_or(4); diff --git a/tests/src/init.rs b/tests/src/init.rs index 28c7f334a6..0553ee2126 100644 --- a/tests/src/init.rs +++ b/tests/src/init.rs @@ -42,7 +42,20 @@ pub fn initialize_instance(backends: wgpu::Backends, force_fxc: bool) -> Instanc dx12: wgpu::Dx12BackendOptions { shader_compiler: dx12_shader_compiler, }, - gl: wgpu::GlBackendOptions::from_env_or_default(), + gl: wgpu::GlBackendOptions { + fence_behavior: if cfg!(target_family = "wasm") { + // On WebGL, you cannot call Poll(Wait) with any timeout. This is because the + // browser does not things to block. However all of our tests are written to + // expect this behavior. This is the workaround to allow this to work. + // + // However on native you can wait, so we want to ensure that behavior as well. + wgpu::GlFenceBehavior::AutoFinish + } else { + wgpu::GlFenceBehavior::Normal + }, + ..Default::default() + } + .with_env(), // TODO(https://github.com/gfx-rs/wgpu/issues/7119): Enable noop backend? noop: wgpu::NoopBackendOptions::default(), }, diff --git a/tests/src/poll.rs b/tests/src/poll.rs index 399cb71393..cb7955b40f 100644 --- a/tests/src/poll.rs +++ b/tests/src/poll.rs @@ -2,7 +2,10 @@ use crate::TestingContext; impl TestingContext { /// Utility to allow future asynchronous polling. - pub async fn async_poll(&self, maintain: wgpu::Maintain) -> wgpu::MaintainResult { - self.device.poll(maintain) + pub async fn async_poll( + &self, + poll_type: wgpu::PollType, + ) -> Result { + self.device.poll(poll_type) } } diff --git a/tests/tests/bgra8unorm_storage.rs b/tests/tests/bgra8unorm_storage.rs index 698a4988b7..eaa549ab6f 100644 --- a/tests/tests/bgra8unorm_storage.rs +++ b/tests/tests/bgra8unorm_storage.rs @@ -142,9 +142,7 @@ static BGRA8_UNORM_STORAGE: GpuTestConfiguration = GpuTestConfiguration::new() let buffer_slice = readback_buffer.slice(..); buffer_slice.map_async(wgpu::MapMode::Read, Result::unwrap); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); { let texels = buffer_slice.get_mapped_range(); diff --git a/tests/tests/binding_array/buffers.rs b/tests/tests/binding_array/buffers.rs index 1ef9818302..9d5c26f894 100644 --- a/tests/tests/binding_array/buffers.rs +++ b/tests/tests/binding_array/buffers.rs @@ -257,7 +257,7 @@ async fn binding_array_buffers( let slice = readback_buffer.slice(..); slice.map_async(MapMode::Read, |_| {}); - ctx.device.poll(Maintain::Wait); + ctx.device.poll(PollType::Wait).unwrap(); let data = slice.get_mapped_range(); diff --git a/tests/tests/binding_array/samplers.rs b/tests/tests/binding_array/samplers.rs index d4ff2a24b5..6d8fd42c7e 100644 --- a/tests/tests/binding_array/samplers.rs +++ b/tests/tests/binding_array/samplers.rs @@ -243,7 +243,7 @@ async fn binding_array_samplers(ctx: TestingContext, partially_bound: bool) { ctx.queue.submit(Some(encoder.finish())); readback_buffer.slice(..).map_async(MapMode::Read, |_| {}); - ctx.device.poll(Maintain::Wait); + ctx.device.poll(PollType::Wait).unwrap(); let readback_buffer_slice = readback_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/buffer.rs b/tests/tests/buffer.rs index b3a48f178a..a23a0609bd 100644 --- a/tests/tests/buffer.rs +++ b/tests/tests/buffer.rs @@ -14,9 +14,7 @@ async fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: b0.slice(0..0) .map_async(wgpu::MapMode::Read, Result::unwrap); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); { let view = b0.slice(0..0).get_mapped_range(); @@ -50,9 +48,7 @@ async fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: b0.slice(0..0) .map_async(wgpu::MapMode::Write, Result::unwrap); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); //{ // let view = b0.slice(0..0).get_mapped_range_mut(); @@ -81,9 +77,7 @@ async fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: b1.unmap(); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); } #[gpu_test] @@ -122,9 +116,7 @@ static MAP_OFFSET: GpuTestConfiguration = GpuTestConfiguration::new().run_async( result.unwrap(); }); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); { let slice = write_buf.slice(32..48); @@ -148,9 +140,7 @@ static MAP_OFFSET: GpuTestConfiguration = GpuTestConfiguration::new().run_async( .slice(..) .map_async(wgpu::MapMode::Read, Result::unwrap); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let slice = read_buf.slice(..); let view = slice.get_mapped_range(); diff --git a/tests/tests/buffer_usages.rs b/tests/tests/buffer_usages.rs index 52848ab4f7..efb7636f65 100644 --- a/tests/tests/buffer_usages.rs +++ b/tests/tests/buffer_usages.rs @@ -139,9 +139,7 @@ async fn map_test( buffer.destroy(); } - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); if !before_unmap && !before_destroy { { diff --git a/tests/tests/cloneable_types.rs b/tests/tests/cloneable_types.rs index 91ee686cff..b38fbbd296 100644 --- a/tests/tests/cloneable_types.rs +++ b/tests/tests/cloneable_types.rs @@ -35,7 +35,7 @@ fn cloneable_buffers(ctx: TestingContext) { assert_eq!(&*data, &cloned_buffer_contents); }); - ctx.device.poll(wgpu::Maintain::Wait); + ctx.device.poll(wgpu::PollType::Wait).unwrap(); let data = buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/compute_pass_ownership.rs b/tests/tests/compute_pass_ownership.rs index c05185828e..168ad8bd78 100644 --- a/tests/tests/compute_pass_ownership.rs +++ b/tests/tests/compute_pass_ownership.rs @@ -52,9 +52,7 @@ async fn compute_pass_resource_ownership(ctx: TestingContext) { drop(pipeline); drop(bind_group); drop(indirect_buffer); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); } assert_compute_pass_executed_normally(encoder, gpu_buffer, cpu_buffer, buffer_size, ctx).await; @@ -102,9 +100,7 @@ async fn compute_pass_query_set_ownership_pipeline_statistics(ctx: TestingContex // Drop the query set. Then do a device poll to make sure it's not dropped too early, no matter what. drop(query_set); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); } assert_compute_pass_executed_normally(encoder, gpu_buffer, cpu_buffer, buffer_size, ctx).await; @@ -160,9 +156,7 @@ async fn compute_pass_query_set_ownership_timestamps(ctx: TestingContext) { // Drop the query sets. Then do a device poll to make sure they're not dropped too early, no matter what. drop(query_set_timestamp_writes); drop(query_set_write_timestamp); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); } assert_compute_pass_executed_normally(encoder, gpu_buffer, cpu_buffer, buffer_size, ctx).await; @@ -197,9 +191,7 @@ async fn compute_pass_keep_encoder_alive(ctx: TestingContext) { let mut cpass = cpass.forget_lifetime(); drop(encoder); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); // Record some draw commands. cpass.set_pipeline(&pipeline); @@ -223,9 +215,7 @@ async fn assert_compute_pass_executed_normally( encoder.copy_buffer_to_buffer(&gpu_buffer, 0, &cpu_buffer, 0, buffer_size); ctx.queue.submit([encoder.finish()]); cpu_buffer.slice(..).map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data = cpu_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/device.rs b/tests/tests/device.rs index 66c92340a0..40b6f55ce3 100644 --- a/tests/tests/device.rs +++ b/tests/tests/device.rs @@ -27,9 +27,7 @@ static CROSS_DEVICE_BIND_GROUP_USAGE: GpuTestConfiguration = GpuTestConfiguratio }); } - ctx.async_poll(wgpu::Maintain::Poll) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::Poll).await.unwrap(); }); #[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))] @@ -615,8 +613,9 @@ static DEVICE_DESTROY_THEN_LOST: GpuTestConfiguration = GpuTestConfiguration::ne // Make sure the device queues are empty, which ensures that the closure // has been called. assert!(ctx - .async_poll(wgpu::Maintain::wait()) + .async_poll(wgpu::PollType::wait()) .await + .unwrap() .is_queue_empty()); assert!( diff --git a/tests/tests/dispatch_workgroups_indirect.rs b/tests/tests/dispatch_workgroups_indirect.rs index 2c2e0aa0f3..c915abf75a 100644 --- a/tests/tests/dispatch_workgroups_indirect.rs +++ b/tests/tests/dispatch_workgroups_indirect.rs @@ -300,9 +300,7 @@ async fn run_test(ctx: &TestingContext, num_workgroups: &[u32; 3]) -> [u32; 3] { .slice(..) .map_async(wgpu::MapMode::Read, |_| {}); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let view = test_resources.readback_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/external_texture.rs b/tests/tests/external_texture.rs index 5a35c9930a..78d9588260 100644 --- a/tests/tests/external_texture.rs +++ b/tests/tests/external_texture.rs @@ -328,9 +328,7 @@ static IMAGE_BITMAP_IMPORT: GpuTestConfiguration = readback_buffer .slice(..) .map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let buffer = readback_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/life_cycle.rs b/tests/tests/life_cycle.rs index d8d21940c8..353fc2df20 100644 --- a/tests/tests/life_cycle.rs +++ b/tests/tests/life_cycle.rs @@ -14,9 +14,7 @@ static BUFFER_DESTROY: GpuTestConfiguration = buffer.destroy(); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); fail( &ctx.device, @@ -30,9 +28,7 @@ static BUFFER_DESTROY: GpuTestConfiguration = buffer.destroy(); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); buffer.destroy(); @@ -54,9 +50,7 @@ static BUFFER_DESTROY: GpuTestConfiguration = } let buffer = ctx.device.create_buffer(&descriptor); buffer.destroy(); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let buffer = ctx.device.create_buffer(&descriptor); buffer.destroy(); { @@ -65,16 +59,12 @@ static BUFFER_DESTROY: GpuTestConfiguration = let buffer = ctx.device.create_buffer(&descriptor); buffer.destroy(); let buffer = ctx.device.create_buffer(&descriptor); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); buffer.destroy(); } let buffer = ctx.device.create_buffer(&descriptor); buffer.destroy(); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); }); #[gpu_test] @@ -99,15 +89,11 @@ static TEXTURE_DESTROY: GpuTestConfiguration = texture.destroy(); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); texture.destroy(); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); texture.destroy(); diff --git a/tests/tests/mem_leaks.rs b/tests/tests/mem_leaks.rs index 75de0776e8..52d0610333 100644 --- a/tests/tests/mem_leaks.rs +++ b/tests/tests/mem_leaks.rs @@ -245,9 +245,9 @@ async fn draw_test_with_reports( // let report = global_report.hub_report(); // assert_eq!(report.command_buffers.num_allocated, 0); - ctx.async_poll(wgpu::Maintain::wait_for(submit_index)) + ctx.async_poll(wgpu::PollType::wait_for(submit_index)) .await - .panic_on_timeout(); + .unwrap(); let global_report = ctx.instance.generate_report().unwrap(); let report = global_report.hub_report(); diff --git a/tests/tests/occlusion_query/mod.rs b/tests/tests/occlusion_query/mod.rs index 98c50095ae..5284ae5879 100644 --- a/tests/tests/occlusion_query/mod.rs +++ b/tests/tests/occlusion_query/mod.rs @@ -115,9 +115,7 @@ static OCCLUSION_QUERY: GpuTestConfiguration = GpuTestConfiguration::new() mapping_buffer .slice(..) .map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let query_buffer_view = mapping_buffer.slice(..).get_mapped_range(); let query_data: &[u64; 3] = bytemuck::from_bytes(&query_buffer_view); diff --git a/tests/tests/oob_indexing.rs b/tests/tests/oob_indexing.rs index 332105ef2f..be5257b788 100644 --- a/tests/tests/oob_indexing.rs +++ b/tests/tests/oob_indexing.rs @@ -41,9 +41,7 @@ static RESTRICT_WORKGROUP_PRIVATE_FUNCTION_LET: GpuTestConfiguration = GpuTestCo .slice(..) .map_async(wgpu::MapMode::Read, |_| {}); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let view = test_resources.readback_buffer.slice(..).get_mapped_range(); @@ -444,9 +442,7 @@ async fn d3d12_restrict_dynamic_buffers(ctx: TestingContext) { .slice(..) .map_async(wgpu::MapMode::Read, |_| {}); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let view = readback_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/pipeline_cache.rs b/tests/tests/pipeline_cache.rs index c88a871c75..0149c33620 100644 --- a/tests/tests/pipeline_cache.rs +++ b/tests/tests/pipeline_cache.rs @@ -175,9 +175,7 @@ async fn validate_pipeline( encoder.copy_buffer_to_buffer(gpu_buffer, 0, cpu_buffer, 0, ARRAY_SIZE * 4); ctx.queue.submit([encoder.finish()]); cpu_buffer.slice(..).map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data = cpu_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/poll.rs b/tests/tests/poll.rs index 7e99cbcd7d..cb93efb303 100644 --- a/tests/tests/poll.rs +++ b/tests/tests/poll.rs @@ -3,7 +3,7 @@ use std::num::NonZeroU64; use wgpu::{ BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BufferBindingType, BufferDescriptor, BufferUsages, CommandBuffer, - CommandEncoderDescriptor, ComputePassDescriptor, Maintain, ShaderStages, + CommandEncoderDescriptor, ComputePassDescriptor, PollType, ShaderStages, }; use wgpu_test::{gpu_test, GpuTestConfiguration, TestingContext}; @@ -57,7 +57,7 @@ static WAIT: GpuTestConfiguration = GpuTestConfiguration::new().run_async(|ctx| let cmd_buf = generate_dummy_work(&ctx); ctx.queue.submit(Some(cmd_buf)); - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); }); #[gpu_test] @@ -66,8 +66,8 @@ static DOUBLE_WAIT: GpuTestConfiguration = let cmd_buf = generate_dummy_work(&ctx); ctx.queue.submit(Some(cmd_buf)); - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); + ctx.async_poll(PollType::wait()).await.unwrap(); }); #[gpu_test] @@ -76,9 +76,7 @@ static WAIT_ON_SUBMISSION: GpuTestConfiguration = let cmd_buf = generate_dummy_work(&ctx); let index = ctx.queue.submit(Some(cmd_buf)); - ctx.async_poll(Maintain::wait_for(index)) - .await - .panic_on_timeout(); + ctx.async_poll(PollType::wait_for(index)).await.unwrap(); }); #[gpu_test] @@ -87,12 +85,10 @@ static DOUBLE_WAIT_ON_SUBMISSION: GpuTestConfiguration = let cmd_buf = generate_dummy_work(&ctx); let index = ctx.queue.submit(Some(cmd_buf)); - ctx.async_poll(Maintain::wait_for(index.clone())) - .await - .panic_on_timeout(); - ctx.async_poll(Maintain::wait_for(index)) + ctx.async_poll(PollType::wait_for(index.clone())) .await - .panic_on_timeout(); + .unwrap(); + ctx.async_poll(PollType::wait_for(index)).await.unwrap(); }); #[gpu_test] @@ -103,12 +99,8 @@ static WAIT_OUT_OF_ORDER: GpuTestConfiguration = let index1 = ctx.queue.submit(Some(cmd_buf1)); let index2 = ctx.queue.submit(Some(cmd_buf2)); - ctx.async_poll(Maintain::wait_for(index2)) - .await - .panic_on_timeout(); - ctx.async_poll(Maintain::wait_for(index1)) - .await - .panic_on_timeout(); + ctx.async_poll(PollType::wait_for(index2)).await.unwrap(); + ctx.async_poll(PollType::wait_for(index1)).await.unwrap(); }); /// Submit a command buffer to the wrong device. A wait poll shouldn't hang. @@ -142,5 +134,5 @@ async fn wait_after_bad_submission(ctx: TestingContext) { // Specifically, the failed submission should not cause a new fence value to // be allocated that will not be signalled until further work is // successfully submitted, causing a greater fence value to be signalled. - device2.poll(wgpu::Maintain::Wait); + device2.poll(wgpu::PollType::Wait).unwrap(); } diff --git a/tests/tests/push_constants.rs b/tests/tests/push_constants.rs index 714f1b9189..4c0a936b93 100644 --- a/tests/tests/push_constants.rs +++ b/tests/tests/push_constants.rs @@ -144,9 +144,7 @@ async fn partial_update_test(ctx: TestingContext) { encoder.copy_buffer_to_buffer(&gpu_buffer, 0, &cpu_buffer, 0, 32); ctx.queue.submit([encoder.finish()]); cpu_buffer.slice(..).map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data = cpu_buffer.slice(..).get_mapped_range(); @@ -363,9 +361,7 @@ async fn render_pass_test(ctx: &TestingContext, use_render_bundle: bool) { let command_buffer = command_encoder.finish(); ctx.queue.submit([command_buffer]); cpu_buffer.slice(..).map_async(MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let mapped_data = cpu_buffer.slice(..).get_mapped_range(); let result = bytemuck::cast_slice::(&mapped_data).to_vec(); drop(mapped_data); diff --git a/tests/tests/ray_tracing/as_use_after_free.rs b/tests/tests/ray_tracing/as_use_after_free.rs index 5692c30c98..c6ea31a914 100644 --- a/tests/tests/ray_tracing/as_use_after_free.rs +++ b/tests/tests/ray_tracing/as_use_after_free.rs @@ -7,7 +7,7 @@ use wgpu::{ BlasBuildEntry, BlasGeometries, BlasGeometrySizeDescriptors, BlasTriangleGeometry, BlasTriangleGeometrySizeDescriptor, BufferAddress, BufferUsages, CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, CreateBlasDescriptor, CreateTlasDescriptor, - Maintain, TlasInstance, TlasPackage, VertexFormat, + PollType, TlasInstance, TlasPackage, VertexFormat, }; use wgpu_macros::gpu_test; use wgpu_test::{FailureCase, GpuTestConfiguration, TestParameters, TestingContext}; @@ -89,7 +89,7 @@ fn acceleration_structure_use_after_free(ctx: TestingContext) { // Drop the blas and ensure that if it was going to die, it is dead. drop(blas); - ctx.device.poll(Maintain::Wait); + ctx.device.poll(PollType::Wait).unwrap(); // build the tlas package to ensure the blas is dropped let mut encoder = ctx @@ -124,7 +124,7 @@ fn acceleration_structure_use_after_free(ctx: TestingContext) { // Drop the TLAS package and ensure that if it was going to die, it is dead. drop(tlas_package); - ctx.device.poll(Maintain::Wait); + ctx.device.poll(PollType::Wait).unwrap(); // Run the pass with the bind group that references the TLAS package. let mut encoder = ctx diff --git a/tests/tests/ray_tracing/scene/mod.rs b/tests/tests/ray_tracing/scene/mod.rs index bd3a08da05..85bed25cfd 100644 --- a/tests/tests/ray_tracing/scene/mod.rs +++ b/tests/tests/ray_tracing/scene/mod.rs @@ -95,7 +95,7 @@ fn acceleration_structure_build(ctx: &TestingContext, use_index_buffer: bool) { ctx.queue.submit(Some(encoder.finish())); - ctx.device.poll(wgpu::Maintain::Wait); + ctx.device.poll(wgpu::PollType::Wait).unwrap(); } #[gpu_test] diff --git a/tests/tests/regression/issue_3457.rs b/tests/tests/regression/issue_3457.rs index 386b5c34bb..3edd2c78b8 100644 --- a/tests/tests/regression/issue_3457.rs +++ b/tests/tests/regression/issue_3457.rs @@ -166,7 +166,7 @@ static PASS_RESET_VERTEX_BUFFER: GpuTestConfiguration = drop(vertex_buffer2); // Make sure the buffers are actually deleted. - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); let mut encoder2 = ctx .device diff --git a/tests/tests/regression/issue_4024.rs b/tests/tests/regression/issue_4024.rs index 263e55a720..c487222c7e 100644 --- a/tests/tests/regression/issue_4024.rs +++ b/tests/tests/regression/issue_4024.rs @@ -36,7 +36,7 @@ static QUEUE_SUBMITTED_CALLBACK_ORDERING: GpuTestConfiguration = GpuTestConfigur // Submit the work. ctx.queue.submit(Some(encoder.finish())); // Ensure the work is finished. - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); #[derive(Debug)] struct OrderingContext { @@ -74,7 +74,7 @@ static QUEUE_SUBMITTED_CALLBACK_ORDERING: GpuTestConfiguration = GpuTestConfigur }); // No GPU work is happening at this point, but we want to process callbacks. - ctx.async_poll(MaintainBase::Poll).await.panic_on_timeout(); + ctx.async_poll(MaintainBase::Poll).await.unwrap(); // Extract the ordering out of the arc. let ordering = Arc::into_inner(ordering).unwrap().into_inner(); diff --git a/tests/tests/regression/issue_4122.rs b/tests/tests/regression/issue_4122.rs index 1dc32f6528..27b66e1ae0 100644 --- a/tests/tests/regression/issue_4122.rs +++ b/tests/tests/regression/issue_4122.rs @@ -32,9 +32,7 @@ async fn fill_test(ctx: &TestingContext, range: Range, size: u64) -> bool { ctx.queue.submit(Some(encoder.finish())); cpu_buffer.slice(..).map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let buffer_slice = cpu_buffer.slice(..); let buffer_data = buffer_slice.get_mapped_range(); diff --git a/tests/tests/regression/issue_6827.rs b/tests/tests/regression/issue_6827.rs index a1e727119b..2cb1bbd039 100644 --- a/tests/tests/regression/issue_6827.rs +++ b/tests/tests/regression/issue_6827.rs @@ -73,7 +73,7 @@ async fn run_test(ctx: TestingContext, use_many_writes: bool) { let result_cell = result_cell.clone(); move |result| result_cell.set(result).unwrap() }); - device.poll(wgpu::Maintain::Wait); + device.poll(wgpu::PollType::Wait).unwrap(); result_cell .get() .as_ref() diff --git a/tests/tests/render_pass_ownership.rs b/tests/tests/render_pass_ownership.rs index cdbd1f45ff..92136899db 100644 --- a/tests/tests/render_pass_ownership.rs +++ b/tests/tests/render_pass_ownership.rs @@ -101,9 +101,7 @@ async fn render_pass_resource_ownership(ctx: TestingContext) { drop(vertex_buffer); drop(index_buffer); drop(occlusion_query_set); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); } assert_render_pass_executed_normally(encoder, gpu_buffer, cpu_buffer, buffer_size, ctx).await; @@ -172,9 +170,7 @@ async fn render_pass_query_set_ownership_pipeline_statistics(ctx: TestingContext // Drop the query set. Then do a device poll to make sure it's not dropped too early, no matter what. drop(query_set); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); } assert_render_pass_executed_normally(encoder, gpu_buffer, cpu_buffer, buffer_size, ctx).await; @@ -250,9 +246,7 @@ async fn render_pass_query_set_ownership_timestamps(ctx: TestingContext) { // Drop the query sets. Then do a device poll to make sure they're not dropped too early, no matter what. drop(query_set_timestamp_writes); drop(query_set_write_timestamp); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); } assert_render_pass_executed_normally(encoder, gpu_buffer, cpu_buffer, buffer_size, ctx).await; @@ -299,9 +293,7 @@ async fn render_pass_keep_encoder_alive(ctx: TestingContext) { let mut rpass = rpass.forget_lifetime(); drop(encoder); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); // Record some a draw command. rpass.set_pipeline(&pipeline); @@ -327,9 +319,7 @@ async fn assert_render_pass_executed_normally( encoder.copy_buffer_to_buffer(&gpu_buffer, 0, &cpu_buffer, 0, buffer_size); ctx.queue.submit([encoder.finish()]); cpu_buffer.slice(..).map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data = cpu_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/samplers.rs b/tests/tests/samplers.rs index 933cd52893..870a0e09a9 100644 --- a/tests/tests/samplers.rs +++ b/tests/tests/samplers.rs @@ -110,7 +110,7 @@ fn sampler_creation_failure(ctx: TestingContext) { let failed_count = sampler_storage.len(); sampler_storage.clear(); - ctx.device.poll(wgpu::Maintain::Wait); + ctx.device.poll(wgpu::PollType::Wait).unwrap(); for i in 0..failed_count { valid(&ctx.device, || { @@ -525,7 +525,7 @@ fn sampler_bind_group(ctx: TestingContext, group_type: GroupType) { let buffer_slice = transfer_buffer.slice(..); buffer_slice.map_async(wgpu::MapMode::Read, |_| {}); - ctx.device.poll(wgpu::Maintain::Wait); + ctx.device.poll(wgpu::PollType::Wait).unwrap(); let buffer_data = buffer_slice.get_mapped_range(); diff --git a/tests/tests/shader/array_size_overrides.rs b/tests/tests/shader/array_size_overrides.rs index f3c49005bc..2fd96f02a5 100644 --- a/tests/tests/shader/array_size_overrides.rs +++ b/tests/tests/shader/array_size_overrides.rs @@ -1,6 +1,6 @@ use std::mem::size_of_val; use wgpu::util::DeviceExt; -use wgpu::{BufferDescriptor, BufferUsages, Maintain, MapMode}; +use wgpu::{BufferDescriptor, BufferUsages, MapMode, PollType}; use wgpu_test::{fail_if, gpu_test, GpuTestConfiguration, TestParameters, TestingContext}; const SHADER: &str = r#" @@ -122,7 +122,7 @@ async fn array_size_overrides( ctx.queue.submit(Some(encoder.finish())); mapping_buffer.slice(..).map_async(MapMode::Read, |_| ()); - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); let mapped = mapping_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/shader/mod.rs b/tests/tests/shader/mod.rs index 07c0fffb17..9a3bae0d40 100644 --- a/tests/tests/shader/mod.rs +++ b/tests/tests/shader/mod.rs @@ -9,7 +9,7 @@ use std::{borrow::Cow, fmt::Debug}; use wgpu::{ Backends, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, ComputePassDescriptor, - ComputePipelineDescriptor, Maintain, MapMode, PipelineLayoutDescriptor, PushConstantRange, + ComputePipelineDescriptor, MapMode, PipelineLayoutDescriptor, PollType, PushConstantRange, ShaderModuleDescriptor, ShaderSource, ShaderStages, }; @@ -367,7 +367,7 @@ async fn shader_input_output_test( ctx.queue.submit(Some(encoder.finish())); mapping_buffer.slice(..).map_async(MapMode::Read, |_| ()); - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); let mapped = mapping_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/shader/workgroup_size_overrides.rs b/tests/tests/shader/workgroup_size_overrides.rs index 2624640f64..d61760707f 100644 --- a/tests/tests/shader/workgroup_size_overrides.rs +++ b/tests/tests/shader/workgroup_size_overrides.rs @@ -1,6 +1,6 @@ use std::mem::size_of_val; use wgpu::util::DeviceExt; -use wgpu::{BufferDescriptor, BufferUsages, Maintain, MapMode}; +use wgpu::{BufferDescriptor, BufferUsages, MapMode, PollType}; use wgpu_test::{fail_if, gpu_test, GpuTestConfiguration, TestParameters, TestingContext}; const SHADER: &str = r#" @@ -107,7 +107,7 @@ async fn workgroup_size_overrides( ctx.queue.submit(Some(encoder.finish())); mapping_buffer.slice(..).map_async(MapMode::Read, |_| ()); - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); let mapped = mapping_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/shader/zero_init_workgroup_mem.rs b/tests/tests/shader/zero_init_workgroup_mem.rs index beacb4fcc8..1aaf7341d1 100644 --- a/tests/tests/shader/zero_init_workgroup_mem.rs +++ b/tests/tests/shader/zero_init_workgroup_mem.rs @@ -4,7 +4,7 @@ use wgpu::{ include_wgsl, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding, BufferBindingType, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, ComputePassDescriptor, - ComputePipelineDescriptor, DownlevelFlags, Limits, Maintain, MapMode, PipelineLayoutDescriptor, + ComputePipelineDescriptor, DownlevelFlags, Limits, MapMode, PipelineLayoutDescriptor, PollType, ShaderStages, }; @@ -131,7 +131,7 @@ static ZERO_INIT_WORKGROUP_MEMORY: GpuTestConfiguration = GpuTestConfiguration:: ctx.queue.submit(Some(encoder.finish())); mapping_buffer.slice(..).map_async(MapMode::Read, |_| ()); - ctx.async_poll(Maintain::wait()).await.panic_on_timeout(); + ctx.async_poll(PollType::wait()).await.unwrap(); let mapped = mapping_buffer.slice(..).get_mapped_range(); diff --git a/tests/tests/shader_view_format/mod.rs b/tests/tests/shader_view_format/mod.rs index d967624829..363a01d1b3 100644 --- a/tests/tests/shader_view_format/mod.rs +++ b/tests/tests/shader_view_format/mod.rs @@ -184,9 +184,7 @@ async fn reinterpret( let slice = read_buffer.slice(..); slice.map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data: Vec = slice.get_mapped_range().to_vec(); let tolerance_data: [[u8; 4]; 4] = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [1, 1, 1, 0]]; diff --git a/tests/tests/texture_binding/mod.rs b/tests/tests/texture_binding/mod.rs index dfbc41f68c..30864c0370 100644 --- a/tests/tests/texture_binding/mod.rs +++ b/tests/tests/texture_binding/mod.rs @@ -2,8 +2,8 @@ use std::time::Duration; use wgpu::wgt::BufferDescriptor; use wgpu::{ include_wgsl, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferUsages, - ComputePassDescriptor, ComputePipelineDescriptor, DownlevelFlags, Extent3d, Features, Maintain, - MapMode, Origin3d, TexelCopyBufferInfo, TexelCopyBufferLayout, TexelCopyTextureInfo, + ComputePassDescriptor, ComputePipelineDescriptor, DownlevelFlags, Extent3d, Features, MapMode, + Origin3d, PollType, TexelCopyBufferInfo, TexelCopyBufferLayout, TexelCopyTextureInfo, TextureAspect, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, }; use wgpu_macros::gpu_test; @@ -178,7 +178,7 @@ fn single_scalar_load(ctx: TestingContext) { send.send(()).expect("Thread should wait for receive"); }); // Poll to run map. - ctx.device.poll(Maintain::Wait); + ctx.device.poll(PollType::Wait).unwrap(); recv.recv_timeout(Duration::from_secs(10)) .expect("mapping should not take this long"); let val = *bytemuck::from_bytes::<[f32; 4]>(&buffer.slice(..).get_mapped_range()); diff --git a/tests/tests/vertex_formats/mod.rs b/tests/tests/vertex_formats/mod.rs index f1df231fff..eeb0ccc408 100644 --- a/tests/tests/vertex_formats/mod.rs +++ b/tests/tests/vertex_formats/mod.rs @@ -376,15 +376,11 @@ async fn vertex_formats_common(ctx: TestingContext, tests: &[Test<'_>]) { // See https://github.com/gfx-rs/wgpu/issues/4732 for why this is split between two submissions // with a hard wait in between. ctx.queue.submit([encoder1.finish()]); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); ctx.queue.submit([encoder2.finish()]); let slice = cpu_buffer.slice(..); slice.map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data: Vec = bytemuck::cast_slice(&slice.get_mapped_range()).to_vec(); let case_name = format!("Case {:?}", test.case); diff --git a/tests/tests/vertex_indices/mod.rs b/tests/tests/vertex_indices/mod.rs index f246b0e350..77f6927bfe 100644 --- a/tests/tests/vertex_indices/mod.rs +++ b/tests/tests/vertex_indices/mod.rs @@ -455,15 +455,11 @@ async fn vertex_index_common(ctx: TestingContext) { // See https://github.com/gfx-rs/wgpu/issues/4732 for why this is split between two submissions // with a hard wait in between. ctx.queue.submit([encoder1.finish()]); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); ctx.queue.submit([encoder2.finish()]); let slice = cpu_buffer.slice(..); slice.map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data: Vec = bytemuck::cast_slice(&slice.get_mapped_range()).to_vec(); let case_name = format!( diff --git a/tests/tests/write_texture.rs b/tests/tests/write_texture.rs index 75118d1e96..12349945a8 100644 --- a/tests/tests/write_texture.rs +++ b/tests/tests/write_texture.rs @@ -84,9 +84,7 @@ static WRITE_TEXTURE_SUBSET_2D: GpuTestConfiguration = let slice = read_buffer.slice(..); slice.map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data: Vec = slice.get_mapped_range().to_vec(); for byte in &data[..(size as usize * 2)] { @@ -179,9 +177,7 @@ static WRITE_TEXTURE_SUBSET_3D: GpuTestConfiguration = let slice = read_buffer.slice(..); slice.map_async(wgpu::MapMode::Read, |_| ()); - ctx.async_poll(wgpu::Maintain::wait()) - .await - .panic_on_timeout(); + ctx.async_poll(wgpu::PollType::wait()).await.unwrap(); let data: Vec = slice.get_mapped_range().to_vec(); for byte in &data[..((size * size) as usize * 2)] { diff --git a/tests/validation_tests/noop.rs b/tests/validation_tests/noop.rs index 3fac4b4b06..a8543eb799 100644 --- a/tests/validation_tests/noop.rs +++ b/tests/validation_tests/noop.rs @@ -41,6 +41,6 @@ fn device_and_buffers() { assert_eq!(*result.unwrap(), [1, 2, 3, 4, 5, 6, 7, 8],); done.store(true, Relaxed); }); - device.poll(wgpu::Maintain::Wait); + device.poll(wgpu::PollType::Wait).unwrap(); assert!(done2.load(Relaxed)); } diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index f18ad71f8e..2493e618eb 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -1869,9 +1869,21 @@ impl Global { // Wait for all work to finish before configuring the surface. let snatch_guard = device.snatchable_lock.read(); let fence = device.fence.read(); - match device.maintain(fence, wgt::Maintain::Wait, snatch_guard) { - Ok((closures, _)) => { - user_callbacks = closures; + + let maintain_result; + (user_callbacks, maintain_result) = + device.maintain(fence, wgt::PollType::Wait, snatch_guard); + + match maintain_result { + // We're happy + Ok(wgt::PollStatus::QueueEmpty) => {} + Ok(wgt::PollStatus::WaitSucceeded) => { + // After the wait, the queue should be empty. It can only be non-empty + // if another thread is submitting at the same time. + break 'error E::GpuWaitTimeout; + } + Ok(wgt::PollStatus::Poll) => { + unreachable!("Cannot get a Poll result from a Wait action.") } Err(e) => { break 'error e.into(); @@ -1931,38 +1943,32 @@ impl Global { pub fn device_poll( &self, device_id: DeviceId, - maintain: wgt::Maintain, - ) -> Result { - api_log!("Device::poll {maintain:?}"); + poll_type: wgt::PollType, + ) -> Result { + api_log!("Device::poll {poll_type:?}"); let device = self.hub.devices.get(device_id); - let DevicePoll { - closures, - queue_empty, - } = Self::poll_single_device(&device, maintain)?; + let (closures, result) = Self::poll_single_device(&device, poll_type); closures.fire(); - Ok(queue_empty) + result } fn poll_single_device( device: &crate::device::Device, - maintain: wgt::Maintain, - ) -> Result { + poll_type: wgt::PollType, + ) -> (UserClosures, Result) { let snatch_guard = device.snatchable_lock.read(); let fence = device.fence.read(); - let (closures, queue_empty) = device.maintain(fence, maintain, snatch_guard)?; + let maintain_result = device.maintain(fence, poll_type, snatch_guard); // Some deferred destroys are scheduled in maintain so run this right after // to avoid holding on to them until the next device poll. device.deferred_resource_destruction(); - Ok(DevicePoll { - closures, - queue_empty, - }) + maintain_result } /// Poll all devices belonging to the specified backend. @@ -1974,7 +1980,7 @@ impl Global { fn poll_all_devices_of_api( &self, force_wait: bool, - closures: &mut UserClosures, + closure_list: &mut UserClosures, ) -> Result { profiling::scope!("poll_device"); @@ -1984,20 +1990,19 @@ impl Global { let device_guard = hub.devices.read(); for (_id, device) in device_guard.iter() { - let maintain = if force_wait { - wgt::Maintain::Wait + let poll_type = if force_wait { + wgt::PollType::Wait } else { - wgt::Maintain::Poll + wgt::PollType::Poll }; - let DevicePoll { - closures: cbs, - queue_empty, - } = Self::poll_single_device(device, maintain)?; + let (closures, result) = Self::poll_single_device(device, poll_type); - all_queue_empty &= queue_empty; + let is_queue_empty = matches!(result, Ok(wgt::PollStatus::QueueEmpty)); - closures.extend(cbs); + all_queue_empty &= is_queue_empty; + + closure_list.extend(closures); } } @@ -2265,8 +2270,3 @@ impl Global { ) } } - -struct DevicePoll { - closures: UserClosures, - queue_empty: bool, -} diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index 4d91d1d98f..1e585f3bbc 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -109,6 +109,17 @@ pub enum WaitIdleError { Device(#[from] DeviceError), #[error("Tried to wait using a submission index ({0}) that has not been returned by a successful submission (last successful submission: {1})")] WrongSubmissionIndex(SubmissionIndex, SubmissionIndex), + #[error("Timed out trying to wait for the given submission index.")] + Timeout, +} + +impl WaitIdleError { + pub fn to_poll_error(&self) -> Option { + match self { + WaitIdleError::Timeout => Some(wgt::PollError::Timeout), + _ => None, + } + } } /// Resource tracking for a device. diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index e4211ef2f0..497ba306fd 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -1301,17 +1301,22 @@ impl Queue { // This will schedule destruction of all resources that are no longer needed // by the user but used in the command stream, among other things. let fence_guard = RwLockWriteGuard::downgrade(fence); - let (closures, _) = - match self - .device - .maintain(fence_guard, wgt::Maintain::Poll, snatch_guard) - { - Ok(closures) => closures, - Err(WaitIdleError::Device(err)) => { - break 'error Err(QueueSubmitError::Queue(err)) - } - Err(WaitIdleError::WrongSubmissionIndex(..)) => unreachable!(), - }; + let (closures, result) = + self.device + .maintain(fence_guard, wgt::PollType::Poll, snatch_guard); + match result { + Ok(status) => { + debug_assert!(matches!( + status, + wgt::PollStatus::QueueEmpty | wgt::PollStatus::Poll + )); + } + Err(WaitIdleError::Device(err)) => break 'error Err(QueueSubmitError::Queue(err)), + Err(WaitIdleError::WrongSubmissionIndex(..)) => { + unreachable!("Cannot get WrongSubmissionIndex from Poll") + } + Err(WaitIdleError::Timeout) => unreachable!("Cannot get Timeout from Poll"), + }; Ok(closures) }; diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index d3e0f2c75a..dfe56b5b47 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -379,73 +379,133 @@ impl Device { assert!(self.queue.set(Arc::downgrade(queue)).is_ok()); } - /// Check this device for completed commands. + /// Check the current status of the GPU and process any submissions that have + /// finished. /// - /// The `maintain` argument tells how the maintenance function should behave, either - /// blocking or just polling the current state of the gpu. + /// The `poll_type` argument tells if this function should wait for a particular + /// submission index to complete, or if it should just poll the current status. /// - /// Return a pair `(closures, queue_empty)`, where: + /// This will process _all_ completed submissions, even if the caller only asked + /// us to poll to a given submission index. /// - /// - `closures` is a list of actions to take: mapping buffers, notifying the user + /// Return a pair `(closures, result)`, where: /// - /// - `queue_empty` is a boolean indicating whether there are more queue - /// submissions still in flight. (We have to take the locks needed to - /// produce this information for other reasons, so we might as well just - /// return it to our callers.) + /// - `closures` is a list of callbacks that need to be invoked informing the user + /// about various things occurring. These happen and should be handled even if + /// this function returns an error, hence they are outside of the result. + /// + /// - `results` is a boolean indicating the result of the wait operation, including + /// if there was a timeout or a validation error. pub(crate) fn maintain<'this>( &'this self, fence: crate::lock::RwLockReadGuard>>, - maintain: wgt::Maintain, + poll_type: wgt::PollType, snatch_guard: SnatchGuard, - ) -> Result<(UserClosures, bool), WaitIdleError> { + ) -> (UserClosures, Result) { profiling::scope!("Device::maintain"); - // Determine which submission index `maintain` represents. - let submission_index = match maintain { - wgt::Maintain::WaitForSubmissionIndex(submission_index) => { + let mut user_closures = UserClosures::default(); + + // If a wait was requested, determine which submission index to wait for. + let wait_submission_index = match poll_type { + wgt::PollType::WaitForSubmissionIndex(submission_index) => { let last_successful_submission_index = self .last_successful_submission_index .load(Ordering::Acquire); if submission_index > last_successful_submission_index { - return Err(WaitIdleError::WrongSubmissionIndex( + let result = Err(WaitIdleError::WrongSubmissionIndex( submission_index, last_successful_submission_index, )); + + return (user_closures, result); } - submission_index + Some(submission_index) } - wgt::Maintain::Wait => self - .last_successful_submission_index - .load(Ordering::Acquire), - wgt::Maintain::Poll => unsafe { self.raw().get_fence_value(fence.as_ref()) } - .map_err(|e| self.handle_hal_error(e))?, + wgt::PollType::Wait => Some( + self.last_successful_submission_index + .load(Ordering::Acquire), + ), + wgt::PollType::Poll => None, }; - // If necessary, wait for that submission to complete. - if maintain.is_wait() { - log::trace!("Device::maintain: waiting for submission index {submission_index}"); - unsafe { + // Wait for the submission index if requested. + if let Some(target_submission_index) = wait_submission_index { + log::trace!("Device::maintain: waiting for submission index {target_submission_index}"); + + let wait_result = unsafe { self.raw() - .wait(fence.as_ref(), submission_index, CLEANUP_WAIT_MS) + .wait(fence.as_ref(), target_submission_index, CLEANUP_WAIT_MS) + }; + + // This error match is only about `DeviceErrors`. At this stage we do not care if + // the wait succeeded or not, and the `Ok(bool)`` variant is ignored. + if let Err(e) = wait_result { + let hal_error: WaitIdleError = self.handle_hal_error(e).into(); + return (user_closures, Err(hal_error)); } - .map_err(|e| self.handle_hal_error(e))?; } - let (submission_closures, mapping_closures, queue_empty) = - if let Some(queue) = self.get_queue() { - queue.maintain(submission_index, &snatch_guard) + // Get the currently finished submission index. This may be higher than the requested + // wait, or it may be less than the requested wait if the wait failed. + let fence_value_result = unsafe { self.raw().get_fence_value(fence.as_ref()) }; + let current_finished_submission = match fence_value_result { + Ok(fence_value) => fence_value, + Err(e) => { + let hal_error: WaitIdleError = self.handle_hal_error(e).into(); + return (user_closures, Err(hal_error)); + } + }; + + // Maintain all finished submissions on the queue, updating the relevant user closures and collecting if the queue is empty. + // + // We don't use the result of the wait here, as we want to progress forward as far as possible + // and the wait could have been for submissions that finished long ago. + let mut queue_empty = false; + if let Some(queue) = self.get_queue() { + let queue_result = queue.maintain(current_finished_submission, &snatch_guard); + ( + user_closures.submissions, + user_closures.mappings, + queue_empty, + ) = queue_result + }; + + // Based on the queue empty status, and the current finished submission index, determine the result of the poll. + let result = if queue_empty { + if let Some(wait_submission_index) = wait_submission_index { + // Assert to ensure that if we received a queue empty status, the fence shows the correct value. + // This is defensive, as this should never be hit. + assert!( + current_finished_submission >= wait_submission_index, + "If the queue is empty, the current submission index ({}) should be at least the wait submission index ({})", + current_finished_submission, + wait_submission_index + ); + } + + Ok(wgt::PollStatus::QueueEmpty) + } else if let Some(wait_submission_index) = wait_submission_index { + // This is theoretically possible to succeed more than checking on the poll result + // as submissions could have finished in the time between the timeout resolving, + // the thread getting scheduled again, and us checking the fence value. + if current_finished_submission >= wait_submission_index { + Ok(wgt::PollStatus::WaitSucceeded) } else { - (SmallVec::new(), Vec::new(), true) - }; + Err(WaitIdleError::Timeout) + } + } else { + Ok(wgt::PollStatus::Poll) + }; // Detect if we have been destroyed and now need to lose the device. + // // If we are invalid (set at start of destroy) and our queue is empty, // and we have a DeviceLostClosure, return the closure to be called by // our caller. This will complete the steps for both destroy and for // "lose the device". - let mut device_lost_invocations = SmallVec::new(); let mut should_release_gpu_resource = false; if !self.is_valid() && queue_empty { // We can release gpu resources associated with this device (but not @@ -455,11 +515,13 @@ impl Device { // If we have a DeviceLostClosure, build an invocation with the // reason DeviceLostReason::Destroyed and no message. if let Some(device_lost_closure) = self.device_lost_closure.lock().take() { - device_lost_invocations.push(DeviceLostInvocation { - closure: device_lost_closure, - reason: DeviceLostReason::Destroyed, - message: String::new(), - }); + user_closures + .device_lost_invocations + .push(DeviceLostInvocation { + closure: device_lost_closure, + reason: DeviceLostReason::Destroyed, + message: String::new(), + }); } } @@ -471,12 +533,7 @@ impl Device { self.release_gpu_resources(); } - let closures = UserClosures { - mappings: mapping_closures, - submissions: submission_closures, - device_lost_invocations, - }; - Ok((closures, queue_empty)) + (user_closures, result) } pub(crate) fn create_buffer( diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index 99748a4f0d..b0b0400745 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -62,6 +62,8 @@ pub enum ConfigureSurfaceError { MissingDownlevelFlags(#[from] MissingDownlevelFlags), #[error("`SurfaceOutput` must be dropped before a new `Surface` is made")] PreviousOutputExists, + #[error("Failed to wait for GPU to come idle before reconfiguring the Surface")] + GpuWaitTimeout, #[error("Both `Surface` width and height must be non-zero. Wait to recreate the `Surface` until the window has non-zero area.")] ZeroArea, #[error("`Surface` width and height must be within the maximum supported texture size. Requested was ({width}, {height}), maximum extent for either dimension is {max_texture_dimension_2d}.")] @@ -99,6 +101,7 @@ impl From for ConfigureSurfaceError { match e { WaitIdleError::Device(d) => ConfigureSurfaceError::Device(d), WaitIdleError::WrongSubmissionIndex(..) => unreachable!(), + WaitIdleError::Timeout => ConfigureSurfaceError::GpuWaitTimeout, } } } diff --git a/wgpu-hal/src/gles/fence.rs b/wgpu-hal/src/gles/fence.rs index d87e0ad742..8622ae3752 100644 --- a/wgpu-hal/src/gles/fence.rs +++ b/wgpu-hal/src/gles/fence.rs @@ -14,7 +14,7 @@ struct GLFence { pub struct Fence { last_completed: AtomicFenceValue, pending: Vec, - fence_mode: wgt::GlFenceBehavior, + fence_behavior: wgt::GlFenceBehavior, } impl crate::DynFence for Fence {} @@ -29,7 +29,7 @@ impl Fence { Self { last_completed: AtomicFenceValue::new(0), pending: Vec::new(), - fence_mode: options.short_circuit_fences, + fence_behavior: options.fence_behavior, } } @@ -38,7 +38,7 @@ impl Fence { gl: &glow::Context, value: crate::FenceValue, ) -> Result<(), crate::DeviceError> { - if self.fence_mode.is_auto_finish() { + if self.fence_behavior.is_auto_finish() { *self.last_completed.get_mut() = value; return Ok(()); } @@ -57,7 +57,7 @@ impl Fence { pub fn get_latest(&self, gl: &glow::Context) -> crate::FenceValue { let mut max_value = self.last_completed.load(Ordering::Acquire); - if self.fence_mode.is_auto_finish() { + if self.fence_behavior.is_auto_finish() { return max_value; } @@ -82,7 +82,7 @@ impl Fence { } pub fn maintain(&mut self, gl: &glow::Context) { - if self.fence_mode.is_auto_finish() { + if self.fence_behavior.is_auto_finish() { return; } @@ -105,7 +105,7 @@ impl Fence { ) -> Result { let last_completed = self.last_completed.load(Ordering::Acquire); - if self.fence_mode.is_auto_finish() { + if self.fence_behavior.is_auto_finish() { return Ok(last_completed >= wait_value); } @@ -154,7 +154,7 @@ impl Fence { } pub fn destroy(self, gl: &glow::Context) { - if self.fence_mode.is_auto_finish() { + if self.fence_behavior.is_auto_finish() { return; } diff --git a/wgpu-types/Cargo.toml b/wgpu-types/Cargo.toml index 653f988b7b..1c63eb7b52 100644 --- a/wgpu-types/Cargo.toml +++ b/wgpu-types/Cargo.toml @@ -37,7 +37,7 @@ alloc_instead_of_core = "warn" [features] default = ["std"] -std = ["js-sys/std", "web-sys/std"] +std = ["js-sys/std", "web-sys/std", "thiserror/std"] strict_asserts = [] fragile-send-sync-non-atomic-wasm = [] serde = ["dep:serde"] @@ -47,6 +47,7 @@ counters = [] [dependencies] bitflags = { workspace = true, features = ["serde"] } log.workspace = true +thiserror = { workspace = true, optional = true } serde = { workspace = true, default-features = false, features = [ "alloc", "derive", diff --git a/wgpu-types/src/instance.rs b/wgpu-types/src/instance.rs index 29de317cf1..55dc2ed37e 100644 --- a/wgpu-types/src/instance.rs +++ b/wgpu-types/src/instance.rs @@ -230,7 +230,7 @@ pub struct GlBackendOptions { /// Which OpenGL ES 3 minor version to request, if using OpenGL ES. pub gles_minor_version: Gles3MinorVersion, /// Behavior of OpenGL fences. Affects how `on_completed_work_done` and `device.poll` behave. - pub short_circuit_fences: GlFenceBehavior, + pub fence_behavior: GlFenceBehavior, } impl GlBackendOptions { @@ -242,7 +242,7 @@ impl GlBackendOptions { let gles_minor_version = Gles3MinorVersion::from_env().unwrap_or_default(); Self { gles_minor_version, - short_circuit_fences: GlFenceBehavior::Normal, + fence_behavior: GlFenceBehavior::Normal, } } @@ -252,10 +252,10 @@ impl GlBackendOptions { #[must_use] pub fn with_env(self) -> Self { let gles_minor_version = self.gles_minor_version.with_env(); - let short_circuit_fences = self.short_circuit_fences.with_env(); + let short_circuit_fences = self.fence_behavior.with_env(); Self { gles_minor_version, - short_circuit_fences, + fence_behavior: short_circuit_fences, } } } @@ -472,7 +472,7 @@ pub enum GlFenceBehavior { /// /// This solves a very specific issue that arose due to a bug in wgpu-core that made /// many WebGL programs work when they "shouldn't" have. If you have code that is trying - /// to call `device.poll(wgpu::Maintain::Wait)` on WebGL, you need to enable this option + /// to call `device.poll(wgpu::PollType::Wait)` on WebGL, you need to enable this option /// for the "Wait" to behave how you would expect. /// /// Previously all `poll(Wait)` acted like the OpenGL fences were signalled even if they weren't. diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index c3e23069db..fbbcc7937b 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -3986,7 +3986,7 @@ impl Default for ColorWrites { /// Passed to `Device::poll` to control how and if it should block. #[derive(Clone, Debug)] -pub enum Maintain { +pub enum PollType { /// On wgpu-core based backends, block until the given submission has /// completed execution, and any callbacks have been invoked. /// @@ -3999,7 +3999,7 @@ pub enum Maintain { Poll, } -impl Maintain { +impl PollType { /// Construct a [`Self::Wait`] variant #[must_use] pub fn wait() -> Self { @@ -4018,7 +4018,7 @@ impl Maintain { Self::WaitForSubmissionIndex(submission_index) } - /// This maintain represents a wait of some kind. + /// This `PollType` represents a wait of some kind. #[must_use] pub fn is_wait(&self) -> bool { match *self { @@ -4029,39 +4029,57 @@ impl Maintain { /// Map on the wait index type. #[must_use] - pub fn map_index(self, func: F) -> Maintain + pub fn map_index(self, func: F) -> PollType where F: FnOnce(T) -> U, { match self { - Self::WaitForSubmissionIndex(i) => Maintain::WaitForSubmissionIndex(func(i)), - Self::Wait => Maintain::Wait, - Self::Poll => Maintain::Poll, + Self::WaitForSubmissionIndex(i) => PollType::WaitForSubmissionIndex(func(i)), + Self::Wait => PollType::Wait, + Self::Poll => PollType::Poll, } } } -/// Result of a maintain operation. -pub enum MaintainResult { +/// Error states after a device poll +#[derive(Debug)] +#[cfg_attr(feature = "std", derive(thiserror::Error))] +pub enum PollError { + /// The requested Wait timed out before the submission was completed. + #[cfg_attr( + feature = "std", + error("The requested Wait timed out before the submission was completed.") + )] + Timeout, +} + +/// Status of device poll operation. +#[derive(Debug, PartialEq, Eq)] +pub enum PollStatus { /// There are no active submissions in flight as of the beginning of the poll call. - /// Other submissions may have been queued on other threads at the same time. + /// Other submissions may have been queued on other threads during the call. /// - /// This implies that the given poll is complete. - SubmissionQueueEmpty, - /// More information coming soon - Ok, + /// This implies that the given Wait was satisfied before the timeout. + QueueEmpty, + + /// The requested Wait was satisfied before the timeout. + WaitSucceeded, + + /// This was a poll. + Poll, } -impl MaintainResult { - /// Returns true if the result is [`Self::SubmissionQueueEmpty`]. +impl PollStatus { + /// Returns true if the result is [`Self::QueueEmpty`]`. #[must_use] pub fn is_queue_empty(&self) -> bool { - matches!(self, Self::SubmissionQueueEmpty) + matches!(self, Self::QueueEmpty) } - /// Panics if the [`MaintainResult`] is not Ok. - pub fn panic_on_timeout(self) { - let _ = self; + /// Returns true if the result is either [`Self::WaitSucceeded`] or [`Self::QueueEmpty`]. + #[must_use] + pub fn wait_finished(&self) -> bool { + matches!(self, Self::WaitSucceeded | Self::QueueEmpty) } } diff --git a/wgpu/src/api/device.rs b/wgpu/src/api/device.rs index 94ee333fcb..7623022758 100644 --- a/wgpu/src/api/device.rs +++ b/wgpu/src/api/device.rs @@ -33,7 +33,7 @@ pub type DeviceDescriptor<'a> = wgt::DeviceDescriptor>; static_assertions::assert_impl_all!(DeviceDescriptor<'_>: Send, Sync); impl Device { - /// Check for resource cleanups and mapping callbacks. Will block if [`Maintain::Wait`] is passed. + /// Check for resource cleanups and mapping callbacks. Will block if [`PollType::Wait`] is passed. /// /// Return `true` if the queue is empty, or `false` if there are more queue /// submissions still in flight. (Note that, unless access to the [`Queue`] is @@ -42,8 +42,8 @@ impl Device { /// other threads could submit new work at any time.) /// /// When running on WebGPU, this is a no-op. `Device`s are automatically polled. - pub fn poll(&self, maintain: Maintain) -> MaintainResult { - self.inner.poll(maintain) + pub fn poll(&self, poll_type: PollType) -> Result { + self.inner.poll(poll_type) } /// The features which can be used on this device. diff --git a/wgpu/src/api/queue.rs b/wgpu/src/api/queue.rs index 9600c60279..8442f2aae1 100644 --- a/wgpu/src/api/queue.rs +++ b/wgpu/src/api/queue.rs @@ -39,11 +39,11 @@ pub struct SubmissionIndex { #[cfg(send_sync)] static_assertions::assert_impl_all!(SubmissionIndex: Send, Sync); -pub use wgt::Maintain as MaintainBase; +pub use wgt::PollType as MaintainBase; /// Passed to [`Device::poll`] to control how and if it should block. -pub type Maintain = wgt::Maintain; +pub type PollType = wgt::PollType; #[cfg(send_sync)] -static_assertions::assert_impl_all!(Maintain: Send, Sync); +static_assertions::assert_impl_all!(PollType: Send, Sync); /// A write-only view into a staging buffer. /// diff --git a/wgpu/src/api/surface.rs b/wgpu/src/api/surface.rs index 41f8b82075..bd2532d616 100644 --- a/wgpu/src/api/surface.rs +++ b/wgpu/src/api/surface.rs @@ -75,6 +75,13 @@ impl Surface<'_> { /// Initializes [`Surface`] for presentation. /// + /// If the surface is already configured, this will wait for the GPU to come idle + /// before recreating the swapchain to prevent race conditions. + /// + /// # Validation Errors + /// - Submissions that happen _during_ the configure may cause the + /// internal wait-for-idle to fail, raising a validation error. + /// /// # Panics /// /// - A old [`SurfaceTexture`] is still alive referencing an old surface. diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index 04621545e3..cb65d4ae97 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -2414,9 +2414,9 @@ impl dispatch::DeviceInterface for WebDevice { // No capturing api in webgpu } - fn poll(&self, _maintain: crate::Maintain) -> crate::MaintainResult { + fn poll(&self, _poll_type: crate::PollType) -> Result { // Device is polled automatically - crate::MaintainResult::SubmissionQueueEmpty + Ok(crate::PollStatus::QueueEmpty) } fn get_internal_counters(&self) -> crate::InternalCounters { diff --git a/wgpu/src/backend/wgpu_core.rs b/wgpu/src/backend/wgpu_core.rs index 539b6da3e3..649b4ea663 100644 --- a/wgpu/src/backend/wgpu_core.rs +++ b/wgpu/src/backend/wgpu_core.rs @@ -1645,14 +1645,17 @@ impl dispatch::DeviceInterface for CoreDevice { self.context.0.device_stop_capture(self.id); } - fn poll(&self, maintain: crate::Maintain) -> crate::MaintainResult { - let maintain_inner = maintain.map_index(|i| i.index); + fn poll(&self, poll_type: crate::PollType) -> Result { + let maintain_inner = poll_type.map_index(|i| i.index); match self.context.0.device_poll(self.id, maintain_inner) { - Ok(done) => match done { - true => wgt::MaintainResult::SubmissionQueueEmpty, - false => wgt::MaintainResult::Ok, - }, - Err(err) => self.context.handle_error_fatal(err, "Device::poll"), + Ok(status) => Ok(status), + Err(err) => { + if let Some(poll_error) = err.to_poll_error() { + return Err(poll_error); + } + + self.context.handle_error_fatal(err, "Device::poll") + } } } diff --git a/wgpu/src/dispatch.rs b/wgpu/src/dispatch.rs index 9ea9a33d1a..9a790dee34 100644 --- a/wgpu/src/dispatch.rs +++ b/wgpu/src/dispatch.rs @@ -192,7 +192,7 @@ pub trait DeviceInterface: CommonTraits { fn start_capture(&self); fn stop_capture(&self); - fn poll(&self, maintain: crate::Maintain) -> crate::MaintainResult; + fn poll(&self, poll_type: crate::PollType) -> Result; fn get_internal_counters(&self) -> crate::InternalCounters; fn generate_allocator_report(&self) -> Option; diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index ed0393c8a9..427d548cac 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -65,18 +65,19 @@ pub use wgt::{ CompositeAlphaMode, CopyExternalImageDestInfo, CoreCounters, DepthBiasState, DepthStencilState, DeviceLostReason, DeviceType, DownlevelCapabilities, DownlevelFlags, DownlevelLimits, Dx12BackendOptions, Dx12Compiler, DynamicOffset, Extent3d, Face, Features, FeaturesWGPU, - FeaturesWebGPU, FilterMode, FrontFace, GlBackendOptions, Gles3MinorVersion, HalCounters, - ImageSubresourceRange, IndexFormat, InstanceDescriptor, InstanceFlags, InternalCounters, - Limits, MaintainResult, MemoryHints, MultisampleState, NoopBackendOptions, Origin2d, Origin3d, - PipelineStatisticsTypes, PolygonMode, PowerPreference, PredefinedColorSpace, PresentMode, - PresentationTimestamp, PrimitiveState, PrimitiveTopology, PushConstantRange, QueryType, - RenderBundleDepthStencil, SamplerBindingType, SamplerBorderColor, ShaderLocation, ShaderModel, - ShaderRuntimeChecks, ShaderStages, StencilFaceState, StencilOperation, StencilState, - StorageTextureAccess, SurfaceCapabilities, SurfaceStatus, TexelCopyBufferLayout, TextureAspect, - TextureDimension, TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, - TextureSampleType, TextureTransition, TextureUsages, TextureUses, TextureViewDimension, - VertexAttribute, VertexFormat, VertexStepMode, WasmNotSend, WasmNotSendSync, WasmNotSync, - COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT, + FeaturesWebGPU, FilterMode, FrontFace, GlBackendOptions, GlFenceBehavior, Gles3MinorVersion, + HalCounters, ImageSubresourceRange, IndexFormat, InstanceDescriptor, InstanceFlags, + InternalCounters, Limits, MemoryHints, MultisampleState, NoopBackendOptions, Origin2d, + Origin3d, PipelineStatisticsTypes, PollError, PollStatus, PolygonMode, PowerPreference, + PredefinedColorSpace, PresentMode, PresentationTimestamp, PrimitiveState, PrimitiveTopology, + PushConstantRange, QueryType, RenderBundleDepthStencil, SamplerBindingType, SamplerBorderColor, + ShaderLocation, ShaderModel, ShaderRuntimeChecks, ShaderStages, StencilFaceState, + StencilOperation, StencilState, StorageTextureAccess, SurfaceCapabilities, SurfaceStatus, + TexelCopyBufferLayout, TextureAspect, TextureDimension, TextureFormat, + TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType, TextureTransition, + TextureUsages, TextureUses, TextureViewDimension, VertexAttribute, VertexFormat, + VertexStepMode, WasmNotSend, WasmNotSendSync, WasmNotSync, COPY_BUFFER_ALIGNMENT, + COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT, QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_STRIDE_ALIGNMENT, }; #[expect(deprecated)]