Skip to content

Commit

Permalink
Add 'PaintLimits' concept, filled in depending on limitations from th…
Browse files Browse the repository at this point in the history
…e underlying graphics API
  • Loading branch information
LPGhatguy committed Nov 20, 2024
1 parent 36fb0b6 commit 240e426
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 24 deletions.
24 changes: 24 additions & 0 deletions crates/yakui-core/src/paint/paint_dom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ use super::layers::PaintLayers;
use super::primitives::{PaintMesh, Vertex};
use super::texture::{Texture, TextureChange};

#[derive(Debug, Clone, Copy, Default)]
/// Contains all information about the limits of the paint device.
pub struct PaintLimits {
/// Maximum texture size of a 1D texture.
pub max_texture_size_1d: u32,
/// Maximum texture size of a 2D texture.
pub max_texture_size_2d: u32,
/// Maximum texture size of a 3D texture.
pub max_texture_size_3d: u32,
}

/// Contains all information about how to paint the current set of widgets.
#[derive(Debug)]
pub struct PaintDom {
Expand All @@ -22,6 +33,7 @@ pub struct PaintDom {
surface_size: Vec2,
unscaled_viewport: Rect,
scale_factor: f32,
limits: Option<PaintLimits>,

layers: PaintLayers,
clip_stack: Vec<Rect>,
Expand All @@ -36,11 +48,23 @@ impl PaintDom {
surface_size: Vec2::ONE,
unscaled_viewport: Rect::ONE,
scale_factor: 1.0,
limits: None,

layers: PaintLayers::new(),
clip_stack: Vec::new(),
}
}

/// Gets the paint limits.
pub fn limits(&self) -> Option<PaintLimits> {
self.limits
}

/// Sets the paint limits, should be called once by rendering backends.
pub fn set_limit(&mut self, limits: PaintLimits) {
self.limits = Some(limits);
}

/// Prepares the PaintDom to be updated for the frame.
pub fn start(&mut self) {
self.texture_edits.clear();
Expand Down
7 changes: 6 additions & 1 deletion crates/yakui-core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::geometry::{Rect, Vec2};
use crate::id::ManagedTextureId;
use crate::input::InputState;
use crate::layout::LayoutDom;
use crate::paint::{PaintDom, Texture};
use crate::paint::{PaintDom, PaintLimits, Texture};

/// The entrypoint for yakui.
#[derive(Debug)]
Expand Down Expand Up @@ -120,4 +120,9 @@ impl Yakui {
pub fn layout_dom(&self) -> &LayoutDom {
&self.layout
}

/// Sets the paint limits, should be called once by rendering backends.
pub fn set_paint_limit(&mut self, limits: PaintLimits) {
self.paint.set_limit(limits)
}
}
57 changes: 35 additions & 22 deletions crates/yakui-vulkan/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ use std::{collections::HashMap, ffi::CStr, io::Cursor};
pub use vulkan_context::VulkanContext;
use vulkan_texture::{UploadQueue, NO_TEXTURE_ID};
pub use vulkan_texture::{VulkanTexture, VulkanTextureCreateInfo};

use yakui_core as yakui;
use yakui_core::geometry::UVec2;
use yakui_core::paint::PaintLimits;
use yakui_core::{paint::Vertex as YakuiVertex, ManagedTextureId};

/// A struct wrapping everything needed to render yakui on Vulkan. This will be your main entry point.
Expand Down Expand Up @@ -67,7 +66,7 @@ pub struct Options {
struct DrawCall {
index_offset: u32,
index_count: u32,
clip: Option<yakui::geometry::Rect>,
clip: Option<yakui_core::geometry::Rect>,
texture_id: u32,
workflow: Workflow,
}
Expand Down Expand Up @@ -103,11 +102,11 @@ enum Workflow {
unsafe impl bytemuck::Zeroable for Workflow {}
unsafe impl bytemuck::Pod for Workflow {}

impl From<yakui::paint::Pipeline> for Workflow {
fn from(p: yakui::paint::Pipeline) -> Self {
impl From<yakui_core::paint::Pipeline> for Workflow {
fn from(p: yakui_core::paint::Pipeline) -> Self {
match p {
yakui::paint::Pipeline::Main => Workflow::Main,
yakui::paint::Pipeline::Text => Workflow::Text,
yakui_core::paint::Pipeline::Main => Workflow::Main,
yakui_core::paint::Pipeline::Text => Workflow::Text,
_ => panic!("Unknown pipeline {p:?}"),
}
}
Expand All @@ -116,9 +115,9 @@ impl From<yakui::paint::Pipeline> for Workflow {
#[repr(C)]
#[derive(Clone, Copy, Default, Debug)]
struct Vertex {
position: yakui::geometry::Vec2,
texcoord: yakui::geometry::Vec2,
color: yakui::geometry::Vec4,
position: yakui_core::geometry::Vec2,
texcoord: yakui_core::geometry::Vec2,
color: yakui_core::geometry::Vec4,
}

impl From<&YakuiVertex> for Vertex {
Expand All @@ -137,7 +136,17 @@ impl YakuiVulkan {
/// ## Safety
/// - `vulkan_context` must have valid members
/// - the members of `render_surface` must have been created with the same [`ash::Device`] as `vulkan_context`.
pub fn new(vulkan_context: &VulkanContext, options: Options) -> Self {
pub fn new(
state: &mut yakui_core::Yakui,
vulkan_context: &VulkanContext,
options: Options,
) -> Self {
state.set_paint_limit(PaintLimits {
max_texture_size_1d: vulkan_context.properties.limits.max_image_dimension1_d,
max_texture_size_2d: vulkan_context.properties.limits.max_image_dimension2_d,
max_texture_size_3d: vulkan_context.properties.limits.max_image_dimension3_d,
});

let device = vulkan_context.device;
let descriptors = Descriptors::new(vulkan_context);

Expand Down Expand Up @@ -502,7 +511,7 @@ impl YakuiVulkan {
}
}

/// Create and add a "user managed" texture to this [`YakuiVulkan`] instance. Returns a [`yakui::TextureId`] that can be used
/// Create and add a "user managed" texture to this [`YakuiVulkan`] instance. Returns a [`yakui_core::TextureId`] that can be used
/// to refer to the texture in your GUI code.
///
/// ## Safety
Expand All @@ -511,24 +520,24 @@ impl YakuiVulkan {
&mut self,
vulkan_context: &VulkanContext,
texture_create_info: VulkanTextureCreateInfo<Vec<u8>>,
) -> yakui::TextureId {
) -> yakui_core::TextureId {
let texture = VulkanTexture::new(
vulkan_context,
&mut self.descriptors,
texture_create_info,
&mut self.uploads,
);
yakui::TextureId::User(self.user_textures.insert(texture).to_bits())
yakui_core::TextureId::User(self.user_textures.insert(texture).to_bits())
}

/// Add a "user managed" texture to this [`YakuiVulkan`] instance from an existing [`ash::vk::Image`].
/// Returns a [`yakui::TextureId`] that can be used to refer to the texture in your GUI code.
/// Returns a [`yakui_core::TextureId`] that can be used to refer to the texture in your GUI code.
///
/// ## Safety
/// - `vulkan_context` must be the same as the one used to create this instance
/// - `image` must have been created from the same `vulkan_context`
pub fn add_user_texture(&mut self, texture: VulkanTexture) -> yakui::TextureId {
yakui::TextureId::User(self.user_textures.insert(texture).to_bits())
pub fn add_user_texture(&mut self, texture: VulkanTexture) -> yakui_core::TextureId {
yakui_core::TextureId::User(self.user_textures.insert(texture).to_bits())
}

/// Clean up all Vulkan related handles on this instance. You'll probably want to call this when the program ends, but
Expand Down Expand Up @@ -560,8 +569,12 @@ impl YakuiVulkan {
&mut self.descriptors
}

fn update_textures(&mut self, vulkan_context: &VulkanContext, paint: &yakui::paint::PaintDom) {
use yakui::paint::TextureChange;
fn update_textures(
&mut self,
vulkan_context: &VulkanContext,
paint: &yakui_core::paint::PaintDom,
) {
use yakui_core::paint::TextureChange;
if !self.initial_textures_synced {
self.initial_textures_synced = true;
for (id, texture) in paint.textures() {
Expand Down Expand Up @@ -620,7 +633,7 @@ impl YakuiVulkan {
fn build_draw_calls(
&mut self,
vulkan_context: &VulkanContext,
paint: &yakui::paint::PaintDom,
paint: &yakui_core::paint::PaintDom,
) -> Vec<DrawCall> {
let mut vertices: Vec<Vertex> = Default::default();
let mut indices: Vec<u32> = Default::default();
Expand All @@ -643,11 +656,11 @@ impl YakuiVulkan {
let texture_id = call
.texture
.and_then(|id| match id {
yakui::TextureId::Managed(managed) => {
yakui_core::TextureId::Managed(managed) => {
let texture = self.yakui_managed_textures.get(&managed)?;
Some(texture.id)
}
yakui::TextureId::User(bits) => {
yakui_core::TextureId::User(bits) => {
let texture = self
.user_textures
.get(thunderdome::Index::from_bits(bits)?)?;
Expand Down
4 changes: 4 additions & 0 deletions crates/yakui-vulkan/src/vulkan_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub struct VulkanContext<'a> {
pub queue: vk::Queue,
/// Memory properties used for [`crate::YakuiVulkan`]'s allocation commands
pub memory_properties: vk::PhysicalDeviceMemoryProperties,
/// Device properties used for setting paint limits
pub properties: vk::PhysicalDeviceProperties,
}

impl<'a> VulkanContext<'a> {
Expand All @@ -26,11 +28,13 @@ impl<'a> VulkanContext<'a> {
device: &'a ash::Device,
queue: vk::Queue,
memory_properties: vk::PhysicalDeviceMemoryProperties,
properties: vk::PhysicalDeviceProperties,
) -> Self {
Self {
device,
queue,
memory_properties,
properties,
}
}

Expand Down
11 changes: 10 additions & 1 deletion crates/yakui-wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use bytemuck::{Pod, Zeroable};
use glam::UVec2;
use thunderdome::{Arena, Index};
use yakui_core::geometry::{Rect, Vec2, Vec4};
use yakui_core::paint::{PaintDom, Pipeline, Texture, TextureChange, TextureFormat};
use yakui_core::paint::{PaintDom, PaintLimits, Pipeline, Texture, TextureChange, TextureFormat};
use yakui_core::{ManagedTextureId, TextureId};

use self::bindgroup_cache::TextureBindgroupCache;
Expand All @@ -27,6 +27,7 @@ use self::samplers::Samplers;
use self::texture::{GpuManagedTexture, GpuTexture};

pub struct YakuiWgpu {
limits: PaintLimits,
main_pipeline: PipelineCache,
text_pipeline: PipelineCache,
samplers: Samplers,
Expand Down Expand Up @@ -69,6 +70,12 @@ impl Vertex {

impl YakuiWgpu {
pub fn new(device: &wgpu::Device, queue: &wgpu::Queue) -> Self {
let limits = PaintLimits {
max_texture_size_1d: device.limits().max_texture_dimension_1d,
max_texture_size_2d: device.limits().max_texture_dimension_2d,
max_texture_size_3d: device.limits().max_texture_dimension_3d,
};

let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("yakui Bind Group Layout"),
entries: &[
Expand Down Expand Up @@ -124,6 +131,7 @@ impl YakuiWgpu {
);

Self {
limits,
main_pipeline,
text_pipeline,
samplers,
Expand Down Expand Up @@ -203,6 +211,7 @@ impl YakuiWgpu {
) {
profiling::scope!("yakui-wgpu paint_with_encoder");

state.set_paint_limit(self.limits);
let paint = state.paint();

self.update_textures(device, paint, queue);
Expand Down

0 comments on commit 240e426

Please sign in to comment.