1
0
Fork 0
forked from wry/wry

vulkan: don't hardcode argb8888 in pipelines

This commit is contained in:
Julian Orth 2024-09-04 21:42:58 +02:00
parent 19dffba7d4
commit c81f35bdf1
2 changed files with 119 additions and 67 deletions

View file

@ -1,21 +1,21 @@
use { use {
crate::{ crate::gfx_apis::vulkan::{
format::ARGB8888, descriptor::VulkanDescriptorSetLayout, device::VulkanDevice, shaders::VulkanShader,
gfx_apis::vulkan::{ util::OnDrop, VulkanError,
descriptor::VulkanDescriptorSetLayout, device::VulkanDevice, shaders::VulkanShader,
util::OnDrop, VulkanError,
},
}, },
arrayvec::ArrayVec, arrayvec::ArrayVec,
ash::vk::{ ash::{
BlendFactor, BlendOp, ColorComponentFlags, CullModeFlags, DynamicState, FrontFace, vk,
GraphicsPipelineCreateInfo, Pipeline, PipelineCache, PipelineColorBlendAttachmentState, vk::{
PipelineColorBlendStateCreateInfo, PipelineDynamicStateCreateInfo, BlendFactor, BlendOp, ColorComponentFlags, CullModeFlags, DynamicState, FrontFace,
PipelineInputAssemblyStateCreateInfo, PipelineLayout, PipelineLayoutCreateInfo, GraphicsPipelineCreateInfo, Pipeline, PipelineCache, PipelineColorBlendAttachmentState,
PipelineMultisampleStateCreateInfo, PipelineRasterizationStateCreateInfo, PipelineColorBlendStateCreateInfo, PipelineDynamicStateCreateInfo,
PipelineRenderingCreateInfo, PipelineShaderStageCreateInfo, PipelineInputAssemblyStateCreateInfo, PipelineLayout, PipelineLayoutCreateInfo,
PipelineVertexInputStateCreateInfo, PipelineViewportStateCreateInfo, PolygonMode, PipelineMultisampleStateCreateInfo, PipelineRasterizationStateCreateInfo,
PrimitiveTopology, PushConstantRange, SampleCountFlags, ShaderStageFlags, PipelineRenderingCreateInfo, PipelineShaderStageCreateInfo,
PipelineVertexInputStateCreateInfo, PipelineViewportStateCreateInfo, PolygonMode,
PrimitiveTopology, PushConstantRange, SampleCountFlags, ShaderStageFlags,
},
}, },
std::{mem, rc::Rc, slice}, std::{mem, rc::Rc, slice},
}; };
@ -30,6 +30,7 @@ pub(super) struct VulkanPipeline {
} }
pub(super) struct PipelineCreateInfo { pub(super) struct PipelineCreateInfo {
pub(super) format: vk::Format,
pub(super) vert: Rc<VulkanShader>, pub(super) vert: Rc<VulkanShader>,
pub(super) frag: Rc<VulkanShader>, pub(super) frag: Rc<VulkanShader>,
pub(super) alpha: bool, pub(super) alpha: bool,
@ -128,7 +129,7 @@ impl VulkanDevice {
.viewport_count(1) .viewport_count(1)
.scissor_count(1); .scissor_count(1);
let mut pipeline_rendering_create_info = PipelineRenderingCreateInfo::default() let mut pipeline_rendering_create_info = PipelineRenderingCreateInfo::default()
.color_attachment_formats(slice::from_ref(&ARGB8888.vk_format)); .color_attachment_formats(slice::from_ref(&info.format));
let create_info = GraphicsPipelineCreateInfo::default() let create_info = GraphicsPipelineCreateInfo::default()
.push_next(&mut pipeline_rendering_create_info) .push_next(&mut pipeline_rendering_create_info)
.stages(&stages) .stages(&stages)

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
async_engine::{AsyncEngine, SpawnedFuture}, async_engine::{AsyncEngine, SpawnedFuture},
format::Format, format::{Format, XRGB8888},
gfx_api::{ gfx_api::{
AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer, AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer,
GfxTexture, ReleaseSync, SyncFile, GfxTexture, ReleaseSync, SyncFile,
@ -9,6 +9,7 @@ use {
gfx_apis::vulkan::{ gfx_apis::vulkan::{
allocator::VulkanAllocator, allocator::VulkanAllocator,
command::{VulkanCommandBuffer, VulkanCommandPool}, command::{VulkanCommandBuffer, VulkanCommandPool},
descriptor::VulkanDescriptorSetLayout,
device::VulkanDevice, device::VulkanDevice,
fence::VulkanFence, fence::VulkanFence,
image::{VulkanImage, VulkanImageMemory}, image::{VulkanImage, VulkanImageMemory},
@ -28,6 +29,7 @@ use {
}, },
ahash::AHashMap, ahash::AHashMap,
ash::{ ash::{
vk,
vk::{ vk::{
AccessFlags2, AttachmentLoadOp, AttachmentStoreOp, BufferImageCopy, AccessFlags2, AttachmentLoadOp, AttachmentStoreOp, BufferImageCopy,
BufferMemoryBarrier2, ClearColorValue, ClearValue, CommandBuffer, BufferMemoryBarrier2, ClearColorValue, ClearValue, CommandBuffer,
@ -56,8 +58,7 @@ use {
pub struct VulkanRenderer { pub struct VulkanRenderer {
pub(super) formats: Rc<AHashMap<u32, GfxFormat>>, pub(super) formats: Rc<AHashMap<u32, GfxFormat>>,
pub(super) device: Rc<VulkanDevice>, pub(super) device: Rc<VulkanDevice>,
pub(super) fill_pipeline: Rc<VulkanPipeline>, pub(super) pipelines: CopyHashMap<vk::Format, Rc<VulkanFormatPipelines>>,
pub(super) tex_pipelines: EnumMap<TexCopyType, EnumMap<TexSourceType, Rc<VulkanPipeline>>>,
pub(super) command_pool: Rc<VulkanCommandPool>, pub(super) command_pool: Rc<VulkanCommandPool>,
pub(super) command_buffers: Stack<Rc<VulkanCommandBuffer>>, pub(super) command_buffers: Stack<Rc<VulkanCommandBuffer>>,
pub(super) wait_semaphores: Stack<Rc<VulkanSemaphore>>, pub(super) wait_semaphores: Stack<Rc<VulkanSemaphore>>,
@ -70,6 +71,13 @@ pub struct VulkanRenderer {
pub(super) buffer_resv_user: BufferResvUser, pub(super) buffer_resv_user: BufferResvUser,
pub(super) eng: Rc<AsyncEngine>, pub(super) eng: Rc<AsyncEngine>,
pub(super) ring: Rc<IoUring>, pub(super) ring: Rc<IoUring>,
pub(super) fill_vert_shader: Rc<VulkanShader>,
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_opaque_shader: Rc<VulkanShader>,
pub(super) tex_frag_mult_alpha_shader: Rc<VulkanShader>,
pub(super) tex_descriptor_set_layout: Rc<VulkanDescriptorSetLayout>,
} }
pub(super) struct UsedTexture { pub(super) struct UsedTexture {
@ -112,46 +120,25 @@ pub(super) struct PendingFrame {
_release_fence: Option<Rc<VulkanFence>>, _release_fence: Option<Rc<VulkanFence>>,
} }
pub(super) struct VulkanFormatPipelines {
pub(super) fill: Rc<VulkanPipeline>,
pub(super) tex: EnumMap<TexCopyType, EnumMap<TexSourceType, Rc<VulkanPipeline>>>,
}
impl VulkanDevice { impl VulkanDevice {
pub fn create_renderer( pub fn create_renderer(
self: &Rc<Self>, self: &Rc<Self>,
eng: &Rc<AsyncEngine>, eng: &Rc<AsyncEngine>,
ring: &Rc<IoUring>, ring: &Rc<IoUring>,
) -> Result<Rc<VulkanRenderer>, VulkanError> { ) -> Result<Rc<VulkanRenderer>, VulkanError> {
let fill_pipeline = self.create_pipeline::<FillVertPushConstants, FillFragPushConstants>( let fill_vert_shader = self.create_shader(FILL_VERT)?;
PipelineCreateInfo { let fill_frag_shader = self.create_shader(FILL_FRAG)?;
vert: self.create_shader(FILL_VERT)?,
frag: self.create_shader(FILL_FRAG)?,
alpha: true,
frag_descriptor_set_layout: None,
},
)?;
let sampler = self.create_sampler()?; let sampler = self.create_sampler()?;
let tex_descriptor_set_layout = self.create_descriptor_set_layout(&sampler)?; let tex_descriptor_set_layout = self.create_descriptor_set_layout(&sampler)?;
let tex_vert_shader = self.create_shader(TEX_VERT)?; let tex_vert_shader = self.create_shader(TEX_VERT)?;
let tex_frag_shader = self.create_shader(TEX_FRAG)?; let tex_frag_shader = self.create_shader(TEX_FRAG)?;
let tex_frag_mult_opaque_shader = self.create_shader(TEX_FRAG_MULT_OPAQUE)?; let tex_frag_mult_opaque_shader = self.create_shader(TEX_FRAG_MULT_OPAQUE)?;
let tex_frag_mult_alpha_shader = self.create_shader(TEX_FRAG_MULT_ALPHA)?; let tex_frag_mult_alpha_shader = self.create_shader(TEX_FRAG_MULT_ALPHA)?;
let create_tex_pipeline = |alpha| {
self.create_pipeline::<TexVertPushConstants, ()>(PipelineCreateInfo {
vert: tex_vert_shader.clone(),
frag: tex_frag_shader.clone(),
alpha,
frag_descriptor_set_layout: Some(tex_descriptor_set_layout.clone()),
})
};
let create_tex_mult_pipeline = |frag: &Rc<VulkanShader>| {
self.create_pipeline::<TexVertPushConstants, TexFragPushConstants>(PipelineCreateInfo {
vert: tex_vert_shader.clone(),
frag: frag.clone(),
alpha: true,
frag_descriptor_set_layout: Some(tex_descriptor_set_layout.clone()),
})
};
let tex_opaque_pipeline = create_tex_pipeline(false)?;
let tex_alpha_pipeline = create_tex_pipeline(true)?;
let tex_mult_opaque_pipeline = create_tex_mult_pipeline(&tex_frag_mult_opaque_shader)?;
let tex_mult_alpha_pipeline = create_tex_mult_pipeline(&tex_frag_mult_alpha_shader)?;
let command_pool = self.create_command_pool()?; let command_pool = self.create_command_pool()?;
let formats: AHashMap<u32, _> = self let formats: AHashMap<u32, _> = self
.formats .formats
@ -178,20 +165,10 @@ impl VulkanDevice {
}) })
.collect(); .collect();
let allocator = self.create_allocator()?; let allocator = self.create_allocator()?;
Ok(Rc::new(VulkanRenderer { let render = Rc::new(VulkanRenderer {
formats: Rc::new(formats), formats: Rc::new(formats),
device: self.clone(), device: self.clone(),
fill_pipeline, pipelines: Default::default(),
tex_pipelines: enum_map! {
TexCopyType::Identity => enum_map! {
TexSourceType::HasAlpha => tex_alpha_pipeline.clone(),
TexSourceType::Opaque => tex_opaque_pipeline.clone(),
},
TexCopyType::Multiply => enum_map! {
TexSourceType::HasAlpha => tex_mult_alpha_pipeline.clone(),
TexSourceType::Opaque => tex_mult_opaque_pipeline.clone(),
},
},
command_pool, command_pool,
command_buffers: Default::default(), command_buffers: Default::default(),
wait_semaphores: Default::default(), wait_semaphores: Default::default(),
@ -204,11 +181,79 @@ impl VulkanDevice {
buffer_resv_user: Default::default(), buffer_resv_user: Default::default(),
eng: eng.clone(), eng: eng.clone(),
ring: ring.clone(), ring: ring.clone(),
})) fill_vert_shader,
fill_frag_shader,
tex_vert_shader,
tex_frag_shader,
tex_frag_mult_opaque_shader,
tex_frag_mult_alpha_shader,
tex_descriptor_set_layout,
});
render.get_or_create_pipelines(XRGB8888.vk_format)?;
Ok(render)
} }
} }
impl VulkanRenderer { impl VulkanRenderer {
fn get_or_create_pipelines(
&self,
format: vk::Format,
) -> Result<Rc<VulkanFormatPipelines>, VulkanError> {
if let Some(pl) = self.pipelines.get(&format) {
return Ok(pl);
}
let fill = self
.device
.create_pipeline::<FillVertPushConstants, FillFragPushConstants>(
PipelineCreateInfo {
format,
vert: self.fill_vert_shader.clone(),
frag: self.fill_frag_shader.clone(),
alpha: true,
frag_descriptor_set_layout: None,
},
)?;
let create_tex_pipeline = |alpha| {
self.device
.create_pipeline::<TexVertPushConstants, ()>(PipelineCreateInfo {
format,
vert: self.tex_vert_shader.clone(),
frag: self.tex_frag_shader.clone(),
alpha,
frag_descriptor_set_layout: Some(self.tex_descriptor_set_layout.clone()),
})
};
let create_tex_mult_pipeline = |frag: &Rc<VulkanShader>| {
self.device
.create_pipeline::<TexVertPushConstants, TexFragPushConstants>(PipelineCreateInfo {
format,
vert: self.tex_vert_shader.clone(),
frag: frag.clone(),
alpha: true,
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(&self.tex_frag_mult_opaque_shader)?;
let tex_mult_alpha = create_tex_mult_pipeline(&self.tex_frag_mult_alpha_shader)?;
let pipelines = Rc::new(VulkanFormatPipelines {
fill,
tex: enum_map! {
TexCopyType::Identity => enum_map! {
TexSourceType::HasAlpha => tex_alpha.clone(),
TexSourceType::Opaque => tex_opaque.clone(),
},
TexCopyType::Multiply => enum_map! {
TexSourceType::HasAlpha => tex_mult_alpha.clone(),
TexSourceType::Opaque => tex_mult_opaque.clone(),
},
},
});
self.pipelines.set(format, pipelines.clone());
Ok(pipelines)
}
pub(super) fn allocate_point(&self) -> u64 { pub(super) fn allocate_point(&self) -> u64 {
self.last_point.fetch_add(1) + 1 self.last_point.fetch_add(1) + 1
} }
@ -350,7 +395,13 @@ impl VulkanRenderer {
} }
} }
fn record_draws(&self, buf: CommandBuffer, opts: &[GfxApiOpt]) -> Result<(), VulkanError> { fn record_draws(
&self,
buf: CommandBuffer,
fb: &VulkanImage,
opts: &[GfxApiOpt],
) -> Result<(), VulkanError> {
let pipelines = self.get_or_create_pipelines(fb.format.vk_format)?;
let dev = &self.device.device; let dev = &self.device.device;
let mut current_pipeline = None; let mut current_pipeline = None;
let mut bind = |pipeline: &VulkanPipeline| { let mut bind = |pipeline: &VulkanPipeline| {
@ -365,7 +416,7 @@ impl VulkanRenderer {
match opt { match opt {
GfxApiOpt::Sync => {} GfxApiOpt::Sync => {}
GfxApiOpt::FillRect(r) => { GfxApiOpt::FillRect(r) => {
bind(&self.fill_pipeline); bind(&pipelines.fill);
let vert = FillVertPushConstants { let vert = FillVertPushConstants {
pos: r.rect.to_points(), pos: r.rect.to_points(),
}; };
@ -375,16 +426,16 @@ impl VulkanRenderer {
unsafe { unsafe {
dev.cmd_push_constants( dev.cmd_push_constants(
buf, buf,
self.fill_pipeline.pipeline_layout, pipelines.fill.pipeline_layout,
ShaderStageFlags::VERTEX, ShaderStageFlags::VERTEX,
0, 0,
uapi::as_bytes(&vert), uapi::as_bytes(&vert),
); );
dev.cmd_push_constants( dev.cmd_push_constants(
buf, buf,
self.fill_pipeline.pipeline_layout, pipelines.fill.pipeline_layout,
ShaderStageFlags::FRAGMENT, ShaderStageFlags::FRAGMENT,
self.fill_pipeline.frag_push_offset, pipelines.fill.frag_push_offset,
uapi::as_bytes(&frag), uapi::as_bytes(&frag),
); );
dev.cmd_draw(buf, 4, 1, 0, 0); dev.cmd_draw(buf, 4, 1, 0, 0);
@ -400,7 +451,7 @@ impl VulkanRenderer {
true => TexSourceType::HasAlpha, true => TexSourceType::HasAlpha,
false => TexSourceType::Opaque, false => TexSourceType::Opaque,
}; };
let pipeline = &self.tex_pipelines[copy_type][source_type]; let pipeline = &pipelines.tex[copy_type][source_type];
bind(pipeline); bind(pipeline);
let vert = TexVertPushConstants { let vert = TexVertPushConstants {
pos: c.target.to_points(), pos: c.target.to_points(),
@ -944,7 +995,7 @@ impl VulkanRenderer {
self.initial_barriers(buf.buffer, fb); self.initial_barriers(buf.buffer, fb);
self.begin_rendering(buf.buffer, fb, clear); self.begin_rendering(buf.buffer, fb, clear);
self.set_viewport(buf.buffer, fb); self.set_viewport(buf.buffer, fb);
self.record_draws(buf.buffer, opts)?; self.record_draws(buf.buffer, fb, opts)?;
self.end_rendering(buf.buffer); self.end_rendering(buf.buffer);
self.copy_bridge_to_dmabuf(buf.buffer, fb); self.copy_bridge_to_dmabuf(buf.buffer, fb);
self.final_barriers(buf.buffer, fb); self.final_barriers(buf.buffer, fb);