scissor attempt

This commit is contained in:
Aleksander
2025-09-23 17:43:19 +02:00
parent 5e6852e5d0
commit 8d41d8bbd1
8 changed files with 143 additions and 70 deletions

View File

@@ -111,6 +111,14 @@ pub struct Rectangle {
pub round_units: u8,
}
#[derive(Clone, Copy)]
pub struct Scissor {
pub x: u32,
pub y: u32,
pub w: u32,
pub h: u32,
}
pub struct RenderPrimitive {
pub(super) boundary: Boundary,
pub(super) transform: Mat4,
@@ -122,6 +130,7 @@ pub enum PrimitivePayload {
Rectangle(Rectangle),
Text(Rc<RefCell<Buffer>>),
Sprite(Option<CustomGlyph>), //option because we want as_slice
Scissor(Scissor),
}
fn draw_widget(

View File

@@ -8,7 +8,7 @@ use vulkano::{
PrimaryCommandBufferAbstract, RenderingAttachmentInfo, RenderingInfo, SubpassContents,
},
device::Queue,
format::Format,
format::{ClearValue, Format},
image::{Image, ImageCreateInfo, ImageType, ImageUsage, view::ImageView},
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter},
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
@@ -44,14 +44,26 @@ impl<T> WCommandBuffer<T> {
}
}
#[derive(Clone, Copy)]
pub enum WGfxClearMode {
Keep,
Clear([f32; 4]),
}
impl WCommandBuffer<CmdBufGfx> {
pub fn begin_rendering(&mut self, render_target: Arc<ImageView>) -> anyhow::Result<()> {
pub fn begin_rendering(&mut self, render_target: Arc<ImageView>, clear_mode: WGfxClearMode) -> anyhow::Result<()> {
self.command_buffer.begin_rendering(RenderingInfo {
contents: SubpassContents::SecondaryCommandBuffers,
color_attachments: vec![Some(RenderingAttachmentInfo {
load_op: AttachmentLoadOp::Clear,
load_op: match &clear_mode {
WGfxClearMode::Keep => AttachmentLoadOp::Load,
WGfxClearMode::Clear(_) => AttachmentLoadOp::Clear,
},
store_op: AttachmentStoreOp::Store,
clear_value: Some([0.0, 0.0, 0.0, 0.0].into()),
clear_value: match &clear_mode {
WGfxClearMode::Keep => None,
WGfxClearMode::Clear(color) => Some(ClearValue::Float(*color)),
},
..RenderingAttachmentInfo::image_view(render_target)
})],
..Default::default()

View File

@@ -3,9 +3,10 @@ use std::{cell::RefCell, rc::Rc, sync::Arc};
use cosmic_text::Buffer;
use glam::{Mat4, Vec2, Vec3};
use slotmap::{SlotMap, new_key_type};
use vulkano::{buffer::view, pipeline::graphics::viewport};
use crate::{
drawing,
drawing::{self, Scissor},
gfx::{WGfx, cmd::GfxCommandBuffer},
};
@@ -24,10 +25,11 @@ struct RendererPass<'a> {
text_areas: Vec<TextArea<'a>>,
text_renderer: TextRenderer,
rect_renderer: RectRenderer,
scissor: Option<Scissor>,
}
impl RendererPass<'_> {
fn new(text_atlas: &mut TextAtlas, rect_pipeline: RectPipeline) -> anyhow::Result<Self> {
fn new(text_atlas: &mut TextAtlas, rect_pipeline: RectPipeline, scissor: Option<Scissor>) -> anyhow::Result<Self> {
let text_renderer = TextRenderer::new(text_atlas)?;
let rect_renderer = RectRenderer::new(rect_pipeline)?;
@@ -36,6 +38,7 @@ impl RendererPass<'_> {
text_renderer,
rect_renderer,
text_areas: Vec::new(),
scissor,
})
}
@@ -49,6 +52,19 @@ impl RendererPass<'_> {
if self.submitted {
return Ok(());
}
let vk_scissor = if let Some(scissor) = self.scissor {
viewport::Scissor {
offset: [scissor.x, scissor.y],
extent: [scissor.w, scissor.h],
}
} else {
viewport::Scissor::default()
};
// TODO?
// cmd_buf.command_buffer.set_scissor(0, smallvec::smallvec![vk_scissor])?;
self.submitted = true;
self.rect_renderer.render(gfx, viewport, cmd_buf)?;
@@ -152,10 +168,7 @@ impl Context {
self.dirty = true;
}
let size = Vec2::new(
resolution[0] as f32 / pixel_scale,
resolution[1] as f32 / pixel_scale,
);
let size = Vec2::new(resolution[0] as f32 / pixel_scale, resolution[1] as f32 / pixel_scale);
let fov = 0.4;
let aspect_ratio = size.x / size.y;
@@ -187,22 +200,28 @@ impl Context {
let atlas = shared.atlas_map.get_mut(self.shared_ctx_key).unwrap();
let mut passes = vec![RendererPass::new(
&mut atlas.text_atlas,
shared.rect_pipeline.clone(),
)?];
let mut passes = Vec::<RendererPass>::new();
let mut needs_new_pass = true;
let mut next_scissor: Option<Scissor> = None;
for primitive in primitives {
if needs_new_pass {
passes.push(RendererPass::new(
&mut atlas.text_atlas,
shared.rect_pipeline.clone(),
next_scissor,
)?);
next_scissor = None;
needs_new_pass = false;
}
let pass = passes.last_mut().unwrap(); // always safe
match &primitive.payload {
drawing::PrimitivePayload::Rectangle(rectangle) => {
pass.rect_renderer.add_rect(
primitive.boundary,
*rectangle,
&primitive.transform,
primitive.depth,
);
pass
.rect_renderer
.add_rect(primitive.boundary, *rectangle, &primitive.transform, primitive.depth);
}
drawing::PrimitivePayload::Text(text) => {
pass.text_areas.push(TextArea {
@@ -230,16 +249,16 @@ impl Context {
transform: primitive.transform,
});
}
drawing::PrimitivePayload::Scissor(scissor) => {
next_scissor = Some(*scissor);
needs_new_pass = true;
}
}
}
let pass = passes.last_mut().unwrap();
pass.submit(
&shared.gfx,
&mut self.viewport,
cmd_buf,
&mut atlas.text_atlas,
)?;
for mut pass in passes {
pass.submit(&shared.gfx, &mut self.viewport, cmd_buf, &mut atlas.text_atlas)?
}
Ok(())
}

View File

@@ -43,8 +43,7 @@ impl ModelBuffer {
})
}
pub fn clear(&mut self) {
self.models.clear(); // note: capacity is being preserved here
pub const fn begin(&mut self) {
self.idx = 0;
}
@@ -83,9 +82,7 @@ impl ModelBuffer {
}*/
if self.idx == self.models.len() as u32 {
self
.models
.resize(self.models.len() * 2, Default::default());
self.models.resize((self.models.len() * 2).max(1), Default::default());
//log::info!("ModelBuffer: resized to {}", self.models.len());
}
@@ -96,12 +93,7 @@ impl ModelBuffer {
ret
}
pub fn register_pos_size(
&mut self,
pos: &glam::Vec2,
size: &glam::Vec2,
transform: &Mat4,
) -> u32 {
pub fn register_pos_size(&mut self, pos: &glam::Vec2, size: &glam::Vec2, transform: &Mat4) -> u32 {
let mut model = glam::Mat4::from_translation(Vec3::new(pos.x, pos.y, 0.0));
model *= *transform;
model *= glam::Mat4::from_scale(Vec3::new(size.x, size.y, 1.0));

View File

@@ -75,12 +75,11 @@ pub struct RectRenderer {
impl RectRenderer {
pub fn new(pipeline: RectPipeline) -> anyhow::Result<Self> {
const BUFFER_SIZE: usize = 128;
const BUFFER_SIZE: usize = 32;
let vert_buffer = pipeline.gfx.empty_buffer(
BufferUsage::VERTEX_BUFFER | BufferUsage::TRANSFER_DST,
BUFFER_SIZE as _,
)?;
let vert_buffer = pipeline
.gfx
.empty_buffer(BufferUsage::VERTEX_BUFFER | BufferUsage::TRANSFER_DST, BUFFER_SIZE as _)?;
Ok(Self {
model_buffer: ModelBuffer::new(&pipeline.gfx)?,
@@ -92,17 +91,15 @@ impl RectRenderer {
})
}
pub fn add_rect(
&mut self,
boundary: Boundary,
rectangle: Rectangle,
transform: &Mat4,
depth: f32,
) {
let in_model_idx =
self
.model_buffer
.register_pos_size(&boundary.pos, &boundary.size, transform);
pub fn begin(&mut self) {
self.rect_vertices.clear();
self.model_buffer.begin();
}
pub fn add_rect(&mut self, boundary: Boundary, rectangle: Rectangle, transform: &Mat4, depth: f32) {
let in_model_idx = self
.model_buffer
.register_pos_size(&boundary.pos, &boundary.size, transform);
self.rect_vertices.push(RectVertex {
in_model_idx,
@@ -123,10 +120,10 @@ impl RectRenderer {
fn upload_verts(&mut self) -> anyhow::Result<()> {
if self.vert_buffer_size < self.rect_vertices.len() {
let new_size = self.vert_buffer_size * 2;
self.vert_buffer = self.pipeline.gfx.empty_buffer(
BufferUsage::VERTEX_BUFFER | BufferUsage::TRANSFER_DST,
new_size as _,
)?;
self.vert_buffer = self
.pipeline
.gfx
.empty_buffer(BufferUsage::VERTEX_BUFFER | BufferUsage::TRANSFER_DST, new_size as _)?;
self.vert_buffer_size = new_size;
}