From 20716cdd1e78ca0010fbe9ec46af8208ccf382ba Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Mon, 17 Feb 2025 12:15:01 +0100 Subject: [PATCH] vulkan: use single push constant range per pipeline --- build/vulkan.rs | 12 +-- src/gfx_apis/vulkan/pipeline.rs | 50 +++++------ src/gfx_apis/vulkan/renderer.rs | 83 ++++++------------- src/gfx_apis/vulkan/shaders.rs | 22 +---- src/gfx_apis/vulkan/shaders/fill.common.glsl | 4 + src/gfx_apis/vulkan/shaders/fill.frag | 5 +- src/gfx_apis/vulkan/shaders/fill.vert | 4 +- .../vulkan/shaders/frag_spec_const.glsl | 1 + src/gfx_apis/vulkan/shaders/tex.common.glsl | 5 ++ src/gfx_apis/vulkan/shaders/tex.frag | 20 ++--- src/gfx_apis/vulkan/shaders/tex.vert | 5 +- 11 files changed, 71 insertions(+), 140 deletions(-) create mode 100644 src/gfx_apis/vulkan/shaders/fill.common.glsl create mode 100644 src/gfx_apis/vulkan/shaders/tex.common.glsl diff --git a/build/vulkan.rs b/build/vulkan.rs index 64bd682f..37f2d7c9 100644 --- a/build/vulkan.rs +++ b/build/vulkan.rs @@ -12,17 +12,7 @@ pub fn main() -> anyhow::Result<()> { compile_simple("fill.frag")?; compile_simple("fill.vert")?; compile_simple("tex.vert")?; - compile_tex_frag("tex.frag.spv", false)?; - compile_tex_frag("tex.frag.mult.spv", true)?; - Ok(()) -} - -fn compile_tex_frag(out: &str, alpha_multiplier: bool) -> anyhow::Result<()> { - let mut opts = CompileOptions::new().unwrap(); - if alpha_multiplier { - opts.add_macro_definition("ALPHA_MULTIPLIER", None); - } - compile_shader("tex.frag", out, Some(opts)).with_context(|| out.to_string())?; + compile_simple("tex.frag")?; Ok(()) } diff --git a/src/gfx_apis/vulkan/pipeline.rs b/src/gfx_apis/vulkan/pipeline.rs index f99c9167..c1382295 100644 --- a/src/gfx_apis/vulkan/pipeline.rs +++ b/src/gfx_apis/vulkan/pipeline.rs @@ -27,7 +27,6 @@ use { pub(super) struct VulkanPipeline { pub(super) vert: Rc, pub(super) _frag: Rc, - pub(super) frag_push_offset: u32, pub(super) pipeline_layout: PipelineLayout, pub(super) pipeline: Pipeline, pub(super) _frag_descriptor_set_layout: Option>, @@ -39,46 +38,32 @@ pub(super) struct PipelineCreateInfo { pub(super) frag: Rc, pub(super) blend: bool, pub(super) src_has_alpha: bool, + pub(super) has_alpha_mult: bool, pub(super) frag_descriptor_set_layout: Option>, } impl VulkanDevice { - pub(super) fn create_pipeline( + pub(super) fn create_pipeline

( &self, info: PipelineCreateInfo, ) -> Result, VulkanError> { - self.create_pipeline_(info, size_of::() as _, size_of::() as _) + self.create_pipeline_(info, size_of::

() as _) } fn create_pipeline_( &self, info: PipelineCreateInfo, - vert_push_size: u32, - frag_push_size: u32, + push_size: u32, ) -> Result, VulkanError> { let pipeline_layout = { - let mut push_constant_ranges = ArrayVec::<_, 2>::new(); - let mut push_constant_offset = 0; - if vert_push_size > 0 { + let mut push_constant_ranges = ArrayVec::<_, 1>::new(); + if push_size > 0 { push_constant_ranges.push( PushConstantRange::default() - .stage_flags(ShaderStageFlags::VERTEX) + .stage_flags(ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT) .offset(0) - .size(vert_push_size), + .size(push_size), ); - push_constant_offset += vert_push_size; - } - if frag_push_size > 0 { - push_constant_ranges.push( - PushConstantRange::default() - .stage_flags(ShaderStageFlags::FRAGMENT) - .offset(push_constant_offset) - .size(frag_push_size), - ); - #[expect(unused_assignments)] - { - push_constant_offset += frag_push_size; - } } let mut descriptor_set_layouts = ArrayVec::<_, 1>::new(); descriptor_set_layouts @@ -91,12 +76,18 @@ impl VulkanDevice { }; let destroy_layout = OnDrop(|| unsafe { self.device.destroy_pipeline_layout(pipeline_layout, None) }); - let mut frag_spec_data = ArrayVec::<_, 4>::new(); - frag_spec_data.extend((info.src_has_alpha as u32).to_ne_bytes()); - let frag_spec_entries = [SpecializationMapEntry::default() - .constant_id(0) - .size(4) - .offset(0)]; + let mut frag_spec_data = ArrayVec::<_, 8>::new(); + let mut frag_spec_entries = ArrayVec::<_, 2>::new(); + let mut frag_spec_entry = |data: &[u8]| { + let entry = SpecializationMapEntry::default() + .constant_id(frag_spec_entries.len() as _) + .size(data.len() as _) + .offset(frag_spec_data.len() as _); + frag_spec_entries.push(entry); + frag_spec_data.extend(data.iter().copied()); + }; + frag_spec_entry(&(info.src_has_alpha as u32).to_ne_bytes()); + frag_spec_entry(&(info.has_alpha_mult as u32).to_ne_bytes()); let frag_spec = SpecializationInfo::default() .map_entries(&frag_spec_entries) .data(&frag_spec_data); @@ -173,7 +164,6 @@ impl VulkanDevice { Ok(Rc::new(VulkanPipeline { vert: info.vert, _frag: info.frag, - frag_push_offset: vert_push_size, pipeline_layout, pipeline, _frag_descriptor_set_layout: info.frag_descriptor_set_layout, diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 4e8d8e72..d8e44fca 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -17,8 +17,7 @@ use { pipeline::{PipelineCreateInfo, VulkanPipeline}, semaphore::VulkanSemaphore, shaders::{ - FillFragPushConstants, FillVertPushConstants, TexFragPushConstants, - TexVertPushConstants, VulkanShader, FILL_FRAG, FILL_VERT, TEX_FRAG, TEX_FRAG_MULT, + FillPushConstants, TexPushConstants, VulkanShader, FILL_FRAG, FILL_VERT, TEX_FRAG, TEX_VERT, }, VulkanError, @@ -74,7 +73,6 @@ pub struct VulkanRenderer { pub(super) fill_frag_shader: Rc, pub(super) tex_vert_shader: Rc, pub(super) tex_frag_shader: Rc, - pub(super) tex_frag_mult_shader: Rc, pub(super) tex_descriptor_set_layout: Rc, pub(super) defunct: Cell, pub(super) pending_cpu_jobs: CopyHashMap, @@ -159,7 +157,6 @@ impl VulkanDevice { let tex_descriptor_set_layout = self.create_descriptor_set_layout(&sampler)?; let tex_vert_shader = self.create_shader(TEX_VERT)?; let tex_frag_shader = self.create_shader(TEX_FRAG)?; - let tex_frag_mult_shader = self.create_shader(TEX_FRAG_MULT)?; let gfx_command_buffers = self.create_command_pool(self.graphics_queue_idx)?; let transfer_command_buffers = self .distinct_transfer_queue_family_idx @@ -217,7 +214,6 @@ impl VulkanDevice { fill_frag_shader, tex_vert_shader, tex_frag_shader, - tex_frag_mult_shader, tex_descriptor_set_layout, defunct: Cell::new(false), pending_cpu_jobs: Default::default(), @@ -238,42 +234,31 @@ impl VulkanRenderer { } let fill = self .device - .create_pipeline::( - PipelineCreateInfo { - format, - vert: self.fill_vert_shader.clone(), - frag: self.fill_frag_shader.clone(), - blend: true, - src_has_alpha: true, - frag_descriptor_set_layout: None, - }, - )?; - let create_tex_pipeline = |src_has_alpha| { + .create_pipeline::(PipelineCreateInfo { + format, + vert: self.fill_vert_shader.clone(), + frag: self.fill_frag_shader.clone(), + blend: true, + src_has_alpha: true, + has_alpha_mult: false, + frag_descriptor_set_layout: None, + })?; + let create_tex_pipeline = |src_has_alpha, has_alpha_mult| { self.device - .create_pipeline::(PipelineCreateInfo { + .create_pipeline::(PipelineCreateInfo { format, vert: self.tex_vert_shader.clone(), frag: self.tex_frag_shader.clone(), - blend: src_has_alpha, - src_has_alpha, - frag_descriptor_set_layout: Some(self.tex_descriptor_set_layout.clone()), - }) - }; - let create_tex_mult_pipeline = |src_has_alpha: bool| { - self.device - .create_pipeline::(PipelineCreateInfo { - format, - vert: self.tex_vert_shader.clone(), - frag: self.tex_frag_mult_shader.clone(), - blend: true, + blend: src_has_alpha || has_alpha_mult, src_has_alpha, + has_alpha_mult, frag_descriptor_set_layout: Some(self.tex_descriptor_set_layout.clone()), }) }; - let tex_opaque = create_tex_pipeline(false)?; - let tex_alpha = create_tex_pipeline(true)?; - let tex_mult_opaque = create_tex_mult_pipeline(false)?; - let tex_mult_alpha = create_tex_mult_pipeline(true)?; + let tex_opaque = create_tex_pipeline(false, false)?; + let tex_alpha = create_tex_pipeline(true, false)?; + let tex_mult_opaque = create_tex_pipeline(false, true)?; + let tex_mult_alpha = create_tex_pipeline(true, true)?; let pipelines = Rc::new(VulkanFormatPipelines { fill, tex: static_map! { @@ -514,26 +499,17 @@ impl VulkanRenderer { GfxApiOpt::Sync => {} GfxApiOpt::FillRect(r) => { bind(&pipelines.fill); - let vert = FillVertPushConstants { + let push = FillPushConstants { pos: r.rect.to_points(), - }; - let frag = FillFragPushConstants { color: r.color.to_array_srgb(), }; unsafe { dev.cmd_push_constants( buf, pipelines.fill.pipeline_layout, - ShaderStageFlags::VERTEX, + ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, 0, - uapi::as_bytes(&vert), - ); - dev.cmd_push_constants( - buf, - pipelines.fill.pipeline_layout, - ShaderStageFlags::FRAGMENT, - pipelines.fill.frag_push_offset, - uapi::as_bytes(&frag), + uapi::as_bytes(&push), ); dev.cmd_draw(buf, 4, 1, 0, 0); } @@ -559,9 +535,10 @@ impl VulkanRenderer { }; let pipeline = &pipelines.tex[copy_type][source_type]; bind(pipeline); - let vert = TexVertPushConstants { + let push = TexPushConstants { pos: c.target.to_points(), tex_pos: c.source.to_points(), + alpha: c.alpha.unwrap_or_default(), }; let image_info = DescriptorImageInfo::default() .image_view(tex.texture_view) @@ -580,20 +557,10 @@ impl VulkanRenderer { dev.cmd_push_constants( buf, pipeline.pipeline_layout, - ShaderStageFlags::VERTEX, + ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, 0, - uapi::as_bytes(&vert), + uapi::as_bytes(&push), ); - if let Some(alpha) = c.alpha { - let frag = TexFragPushConstants { alpha }; - dev.cmd_push_constants( - buf, - pipeline.pipeline_layout, - ShaderStageFlags::FRAGMENT, - size_of_val(&vert) as _, - uapi::as_bytes(&frag), - ); - } dev.cmd_draw(buf, 4, 1, 0, 0); } } diff --git a/src/gfx_apis/vulkan/shaders.rs b/src/gfx_apis/vulkan/shaders.rs index f1f796c3..ff99f114 100644 --- a/src/gfx_apis/vulkan/shaders.rs +++ b/src/gfx_apis/vulkan/shaders.rs @@ -9,7 +9,6 @@ pub const FILL_VERT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/fill.vert pub const FILL_FRAG: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/fill.frag.spv")); pub const TEX_VERT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/tex.vert.spv")); pub const TEX_FRAG: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/tex.frag.spv")); -pub const TEX_FRAG_MULT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/tex.frag.mult.spv")); pub struct VulkanShader { pub(super) device: Rc, @@ -18,35 +17,22 @@ pub struct VulkanShader { #[derive(Copy, Clone, Debug)] #[repr(C)] -pub struct FillVertPushConstants { +pub struct FillPushConstants { pub pos: [[f32; 2]; 4], -} - -unsafe impl Packed for FillVertPushConstants {} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct FillFragPushConstants { pub color: [f32; 4], } -unsafe impl Packed for FillFragPushConstants {} +unsafe impl Packed for FillPushConstants {} #[derive(Copy, Clone, Debug)] #[repr(C)] -pub struct TexVertPushConstants { +pub struct TexPushConstants { pub pos: [[f32; 2]; 4], pub tex_pos: [[f32; 2]; 4], -} - -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct TexFragPushConstants { pub alpha: f32, } -unsafe impl Packed for TexVertPushConstants {} -unsafe impl Packed for TexFragPushConstants {} +unsafe impl Packed for TexPushConstants {} impl VulkanDevice { pub(super) fn create_shader( diff --git a/src/gfx_apis/vulkan/shaders/fill.common.glsl b/src/gfx_apis/vulkan/shaders/fill.common.glsl new file mode 100644 index 00000000..d49c75a8 --- /dev/null +++ b/src/gfx_apis/vulkan/shaders/fill.common.glsl @@ -0,0 +1,4 @@ +layout(push_constant, std430) uniform Data { + layout(offset = 0) vec2 pos[4]; + layout(offset = 32) vec4 color; +} data; diff --git a/src/gfx_apis/vulkan/shaders/fill.frag b/src/gfx_apis/vulkan/shaders/fill.frag index 44200841..c6424d9d 100644 --- a/src/gfx_apis/vulkan/shaders/fill.frag +++ b/src/gfx_apis/vulkan/shaders/fill.frag @@ -1,10 +1,7 @@ #version 450 #include "frag_spec_const.glsl" - -layout(push_constant, std430) uniform Data { - layout(offset = 32) vec4 color; -} data; +#include "fill.common.glsl" layout(location = 0) out vec4 out_color; diff --git a/src/gfx_apis/vulkan/shaders/fill.vert b/src/gfx_apis/vulkan/shaders/fill.vert index 62abce65..8b4a7aa7 100644 --- a/src/gfx_apis/vulkan/shaders/fill.vert +++ b/src/gfx_apis/vulkan/shaders/fill.vert @@ -1,9 +1,7 @@ #version 450 //#extension GL_EXT_debug_printf : enable -layout(push_constant, std430) uniform Data { - layout(offset = 0) vec2 pos[4]; -} data; +#include "fill.common.glsl" void main() { vec2 pos; diff --git a/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl b/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl index e83f8a52..b2be1f76 100644 --- a/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl +++ b/src/gfx_apis/vulkan/shaders/frag_spec_const.glsl @@ -1 +1,2 @@ layout(constant_id = 0) const bool src_has_alpha = false; +layout(constant_id = 1) const bool has_alpha_multiplier = false; diff --git a/src/gfx_apis/vulkan/shaders/tex.common.glsl b/src/gfx_apis/vulkan/shaders/tex.common.glsl new file mode 100644 index 00000000..61f3ef3c --- /dev/null +++ b/src/gfx_apis/vulkan/shaders/tex.common.glsl @@ -0,0 +1,5 @@ +layout(push_constant, std430) uniform Data { + layout(offset = 0) vec2 pos[4]; + layout(offset = 32) vec2 tex_pos[4]; + layout(offset = 64) float mul; +} data; diff --git a/src/gfx_apis/vulkan/shaders/tex.frag b/src/gfx_apis/vulkan/shaders/tex.frag index 94585572..2d5a29ad 100644 --- a/src/gfx_apis/vulkan/shaders/tex.frag +++ b/src/gfx_apis/vulkan/shaders/tex.frag @@ -1,24 +1,20 @@ #version 450 #include "frag_spec_const.glsl" +#include "tex.common.glsl" -#ifdef ALPHA_MULTIPLIER -layout(push_constant, std430) uniform Data { - layout(offset = 64) float mul; -} data; -#endif layout(set = 0, binding = 0) uniform sampler2D tex; layout(location = 0) in vec2 tex_pos; layout(location = 0) out vec4 out_color; void main() { -#ifdef ALPHA_MULTIPLIER - if (src_has_alpha) { - out_color = textureLod(tex, tex_pos, 0) * data.mul; + if (has_alpha_multiplier) { + if (src_has_alpha) { + out_color = textureLod(tex, tex_pos, 0) * data.mul; + } else { + out_color = vec4(textureLod(tex, tex_pos, 0).rgb * data.mul, data.mul); + } } else { - out_color = vec4(textureLod(tex, tex_pos, 0).rgb * data.mul, data.mul); + out_color = textureLod(tex, tex_pos, 0); } -#else // !ALPHA_MULTIPLIER - out_color = textureLod(tex, tex_pos, 0); -#endif } diff --git a/src/gfx_apis/vulkan/shaders/tex.vert b/src/gfx_apis/vulkan/shaders/tex.vert index 5a013dd5..7390b4a4 100644 --- a/src/gfx_apis/vulkan/shaders/tex.vert +++ b/src/gfx_apis/vulkan/shaders/tex.vert @@ -1,10 +1,7 @@ #version 450 //#extension GL_EXT_debug_printf : enable -layout(push_constant, std430) uniform Data { - layout(offset = 0) vec2 pos[4]; - layout(offset = 32) vec2 tex_pos[4]; -} data; +#include "tex.common.glsl" layout(location = 0) out vec2 tex_pos;