From: Josh Simmons Date: Sat, 25 May 2024 08:44:30 +0000 (+0200) Subject: narcissus-gpu: Add push constants function X-Git-Url: https://git.nega.tv//gitweb.cgi?a=commitdiff_plain;h=3308f92007b443b6b2ca286f54c8ac6a77602db0;p=josh%2Fnarcissus narcissus-gpu: Add push constants function --- diff --git a/engine/narcissus-gpu/src/backend/vulkan/mod.rs b/engine/narcissus-gpu/src/backend/vulkan/mod.rs index a7fbb8e..c8f2da5 100644 --- a/engine/narcissus-gpu/src/backend/vulkan/mod.rs +++ b/engine/narcissus-gpu/src/backend/vulkan/mod.rs @@ -21,8 +21,8 @@ use crate::{ Frame, GlobalBarrier, GpuConcurrent, GraphicsPipelineDesc, Image, ImageBarrier, ImageBlit, ImageDesc, ImageDimension, ImageLayout, ImageTiling, ImageViewDesc, IndexType, MemoryLocation, Offset2d, Offset3d, PersistentBuffer, Pipeline, Sampler, SamplerAddressMode, SamplerCompareOp, - SamplerDesc, SamplerFilter, SwapchainConfigurator, SwapchainImage, SwapchainOutOfDateError, - ThreadToken, TransientBuffer, TypedBind, + SamplerDesc, SamplerFilter, ShaderStageFlags, SwapchainConfigurator, SwapchainImage, + SwapchainOutOfDateError, ThreadToken, TransientBuffer, TypedBind, }; mod allocator; @@ -1688,6 +1688,37 @@ impl Device for VulkanDevice { } } + unsafe fn cmd_push_constants_unchecked( + &self, + cmd_encoder: &mut CmdEncoder, + stage_flags: ShaderStageFlags, + offset: u32, + size: u32, + src: *const u8, + ) { + let cmd_encoder = self.cmd_encoder_mut(cmd_encoder); + let command_buffer = cmd_encoder.command_buffer; + + let VulkanBoundPipeline { + pipeline_layout, + pipeline_bind_point: _, + } = cmd_encoder + .bound_pipeline + .as_ref() + .expect("cannot push constants without a pipeline bound") + .clone(); + + let stage_flags = vulkan_shader_stage_flags(stage_flags); + self.device_fn.cmd_push_constants( + command_buffer, + pipeline_layout, + stage_flags, + offset, + size, + src as *const std::ffi::c_void, + ) + } + fn cmd_copy_buffer_to_image( &self, cmd_encoder: &mut CmdEncoder, diff --git a/engine/narcissus-gpu/src/lib.rs b/engine/narcissus-gpu/src/lib.rs index 7843961..def3cad 100644 --- a/engine/narcissus-gpu/src/lib.rs +++ b/engine/narcissus-gpu/src/lib.rs @@ -830,6 +830,15 @@ pub trait Device { image_barriers: &[ImageBarrier], ); + unsafe fn cmd_push_constants_unchecked( + &self, + cmd_encoder: &mut CmdEncoder, + stage_flags: ShaderStageFlags, + offset: u32, + size: u32, + src: *const u8, + ); + fn cmd_copy_buffer_to_image( &self, cmd_encoder: &mut CmdEncoder, @@ -887,7 +896,44 @@ pub trait Device { fn end_frame<'device>(&'device self, frame: Frame<'device>); } +#[cold] +fn overflow() -> ! { + panic!("overflow") +} + pub trait DeviceExt: Device { + fn cmd_push_constants( + &self, + cmd_encoder: &mut CmdEncoder, + stage_flags: ShaderStageFlags, + offset: usize, + data: &T, + ) { + let size = std::mem::size_of_val(data); + let src = data as *const _ as *const u8; + + // # Safety + // + // The memory region from `src` through `src` + `size` must be valid as it's + // directly derived from `data`. + // + // This function will propagate undefined values from T, for example, padding + // bytes, however we promise not to materialize a rust reference to any such + // data. + unsafe { + if size >= u32::MAX as usize || offset >= u32::MAX as usize { + overflow(); + } + self.cmd_push_constants_unchecked( + cmd_encoder, + stage_flags, + offset as u32, + size as u32, + src, + ) + } + } + fn create_persistent_buffer_with_data<'a, T: ?Sized>( &'a self, memory_location: MemoryLocation,