Skip to content

Commit

Permalink
Merge pull request #369 from mahkoh/jorth/unconditional-push-constants
Browse files Browse the repository at this point in the history
vulkan: use single push constant range per pipeline
  • Loading branch information
mahkoh authored Feb 17, 2025
2 parents 5a5f918 + 20716cd commit 31b509d
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 140 deletions.
12 changes: 1 addition & 11 deletions build/vulkan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}

Expand Down
50 changes: 20 additions & 30 deletions src/gfx_apis/vulkan/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use {
pub(super) struct VulkanPipeline {
pub(super) vert: Rc<VulkanShader>,
pub(super) _frag: Rc<VulkanShader>,
pub(super) frag_push_offset: u32,
pub(super) pipeline_layout: PipelineLayout,
pub(super) pipeline: Pipeline,
pub(super) _frag_descriptor_set_layout: Option<Rc<VulkanDescriptorSetLayout>>,
Expand All @@ -39,46 +38,32 @@ pub(super) struct PipelineCreateInfo {
pub(super) frag: Rc<VulkanShader>,
pub(super) blend: bool,
pub(super) src_has_alpha: bool,
pub(super) has_alpha_mult: bool,
pub(super) frag_descriptor_set_layout: Option<Rc<VulkanDescriptorSetLayout>>,
}

impl VulkanDevice {
pub(super) fn create_pipeline<V, F>(
pub(super) fn create_pipeline<P>(
&self,
info: PipelineCreateInfo,
) -> Result<Rc<VulkanPipeline>, VulkanError> {
self.create_pipeline_(info, size_of::<V>() as _, size_of::<F>() as _)
self.create_pipeline_(info, size_of::<P>() as _)
}

fn create_pipeline_(
&self,
info: PipelineCreateInfo,
vert_push_size: u32,
frag_push_size: u32,
push_size: u32,
) -> Result<Rc<VulkanPipeline>, 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
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
83 changes: 25 additions & 58 deletions src/gfx_apis/vulkan/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -74,7 +73,6 @@ pub struct VulkanRenderer {
pub(super) fill_frag_shader: Rc<VulkanShader>,
pub(super) tex_vert_shader: Rc<VulkanShader>,
pub(super) tex_frag_shader: Rc<VulkanShader>,
pub(super) tex_frag_mult_shader: Rc<VulkanShader>,
pub(super) tex_descriptor_set_layout: Rc<VulkanDescriptorSetLayout>,
pub(super) defunct: Cell<bool>,
pub(super) pending_cpu_jobs: CopyHashMap<u64, PendingJob>,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(),
Expand All @@ -238,42 +234,31 @@ impl VulkanRenderer {
}
let fill = self
.device
.create_pipeline::<FillVertPushConstants, FillFragPushConstants>(
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::<FillPushConstants>(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::<TexVertPushConstants, ()>(PipelineCreateInfo {
.create_pipeline::<TexPushConstants>(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::<TexVertPushConstants, TexFragPushConstants>(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! {
Expand Down Expand Up @@ -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);
}
Expand All @@ -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)
Expand All @@ -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);
}
}
Expand Down
22 changes: 4 additions & 18 deletions src/gfx_apis/vulkan/shaders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<VulkanDevice>,
Expand All @@ -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(
Expand Down
4 changes: 4 additions & 0 deletions src/gfx_apis/vulkan/shaders/fill.common.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
layout(push_constant, std430) uniform Data {
layout(offset = 0) vec2 pos[4];
layout(offset = 32) vec4 color;
} data;
5 changes: 1 addition & 4 deletions src/gfx_apis/vulkan/shaders/fill.frag
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
4 changes: 1 addition & 3 deletions src/gfx_apis/vulkan/shaders/fill.vert
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/gfx_apis/vulkan/shaders/frag_spec_const.glsl
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
layout(constant_id = 0) const bool src_has_alpha = false;
layout(constant_id = 1) const bool has_alpha_multiplier = false;
5 changes: 5 additions & 0 deletions src/gfx_apis/vulkan/shaders/tex.common.glsl
Original file line number Diff line number Diff line change
@@ -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;
20 changes: 8 additions & 12 deletions src/gfx_apis/vulkan/shaders/tex.frag
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit 31b509d

Please sign in to comment.