Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: adrien-ben/egui-ash-renderer
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 25f137a22a7596acbe391baabf610678e779613a
Choose a base ref
..
head repository: adrien-ben/egui-ash-renderer
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 50406add97ca00daaa5b7e27e44eb6f0868d84bf
Choose a head ref
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.3.0

- dev: bump simple_logger to 5.0
- add option to target srgb framebuffer
- allow gpu-allocator 0.26
- remove ultraviolet and fix viewport size issue
- allow updating dynamic rendering parameters

## 0.2.0

- egui >=0.26, <=0.27
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ log = "0.4"
egui = { version = ">=0.26, <=0.27", default-features = false }
ash = { version = "0.38", default-features = false, features = ["std"] }

gpu-allocator = { version = "0.25", default-features = false, features = ["vulkan"], optional = true }
gpu-allocator = { version = ">=0.25, <=0.26", default-features = false, features = ["vulkan"], optional = true }
vk-mem = { version = "0.3", default-features = false, optional = true }

[features]
@@ -28,7 +28,7 @@ gpu-allocator = ["dep:gpu-allocator"]
vk-mem = ["dep:vk-mem"]

[dev-dependencies]
simple_logger = "4.0"
simple_logger = "5.0"
winit = "0.29"
ash = { version = "0.38", default-features = false, features = ["debug", "linked", "std"] }
ash-window = "0.13"
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -15,29 +15,33 @@ This is meant to add support for egui in your existing Vulkan/ash applications.

| crate | egui | ash | gpu-allocator (feature) | vk-mem (feature) |
|--------|--------------|--------------|-------------------------|------------------|
| 0.3.0 | [0.26, 0.27] | 0.38 | 0.25 | 0.3.0 |
| 0.2.0 | [0.26, 0.27] | [0.34, 0.37] | 0.25 | 0.3.0 |
| 0.3.0 | [0.26, 0.27] | [0.34, 0.37] | [0.25, 0.26] | 0.3.0 |

## How it works

The renderer records drawing command to a command buffer supplied by the application. Here is a little breakdown of the features of this crate and how they work.

- Vertex/Index buffers
### Vertex/Index buffers

The renderer creates a vertex buffer and a index buffer that will be updated every time
`Renderer::cmd_draw` is called. If the vertex/index count is more than what the buffers can
actually hold then the buffers are resized (actually destroyed then re-created).

- Frames in flight
### Frames in flight

The renderer support having multiple frames in flight. You need to specify the number of frames
during initialization of the renderer. The renderer manages one vertex and index buffer per frame.

- No draw call execution
### No draw call execution

The `Renderer::cmd_draw` only record commands to a command buffer supplied by the application. It does not submit anything to the gpu.

- Managed textures
### sRGB/Linear framebuffer

You can indicate wether you will target an sRGB framebuffer or not by passing the option `srgb_framebuffer` when initializing the renderer.
When you target an sRGB framebuffer, the fragment shader will output linear color values, otherwise it will convert the colors to sRGB.

### Managed textures

Textures managed by egui must be kept in sync with the renderer. To do so, the user should call `Renderer::set_textures` and
`Renderer::free_textures`. The former must be call before submitting the command buffer for rendering and the latter must be
@@ -60,7 +64,7 @@ renderer.free_textures(output.textures_delta.free.as_slice()).unwrap();
> If you have multiple frames in flight you might want to hold a set of textures to free for each frame and call
`Renderer::free_textures` after waiting for the fence of the previous frame.

- Custom textures
### Custom textures

You can also render used managed textures in egui. You just need to call `Renderer::add_user_texture` and pass a
`vk::DescriptorSet` compatible with the layout used in the renderer's graphics pipeline
Binary file added assets/images/normals.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 21 additions & 18 deletions examples/common/mod.rs
Original file line number Diff line number Diff line change
@@ -115,7 +115,10 @@ impl App {
Arc::new(Mutex::new(allocator)),
vulkan_context.device.clone(),
swapchain.render_pass,
Options::default(),
Options {
srgb_framebuffer: true,
..Default::default()
},
)?
};

@@ -136,7 +139,10 @@ impl App {
Arc::new(Mutex::new(allocator)),
vulkan_context.device.clone(),
swapchain.render_pass,
Options::default(),
Options {
srgb_framebuffer: true,
..Default::default()
},
)?
};

@@ -146,7 +152,10 @@ impl App {
vulkan_context.physical_device,
vulkan_context.device.clone(),
swapchain.render_pass,
Options::default(),
Options {
srgb_framebuffer: true,
..Default::default()
},
)?;

Ok(Self {
@@ -805,20 +814,14 @@ fn create_vulkan_swapchain(
vulkan_context.surface_khr,
)?
};
if formats.len() == 1 && formats[0].format == vk::Format::UNDEFINED {
vk::SurfaceFormatKHR {
format: vk::Format::B8G8R8A8_UNORM,
color_space: vk::ColorSpaceKHR::SRGB_NONLINEAR,
}
} else {
*formats
.iter()
.find(|format| {
format.format == vk::Format::B8G8R8A8_UNORM
&& format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
})
.unwrap_or(&formats[0])
}

*formats
.iter()
.find(|format| {
format.format == vk::Format::R8G8B8A8_SRGB
&& format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
})
.unwrap_or(&formats[0])
};
log::debug!("Swapchain format: {format:?}");

@@ -1019,7 +1022,7 @@ fn record_command_buffers(
})
.clear_values(&[vk::ClearValue {
color: vk::ClearColorValue {
float32: [0.105, 0.105, 0.105, 1.0],
float32: [0.007, 0.007, 0.007, 1.0],
},
}]);

11 changes: 7 additions & 4 deletions examples/common/vulkan.rs
Original file line number Diff line number Diff line change
@@ -99,7 +99,7 @@ pub mod texture {
impl Texture {
/// Create a texture from an `u8` array containing an rgba image.
///
/// The image data is device local and it's format is R8G8B8A8_UNORM.
/// The image data is device local.
///
/// # Arguments
///
@@ -109,6 +109,7 @@ pub mod texture {
/// * `mem_properties` - The memory properties of the Vulkan physical device.
/// * `width` - The width of the image.
/// * `height` - The height of the image.
/// * `format` - The format of the image.
/// * `data` - The image data.
#[allow(dead_code)]
pub fn from_rgba8(
@@ -118,11 +119,12 @@ pub mod texture {
mem_properties: vk::PhysicalDeviceMemoryProperties,
width: u32,
height: u32,
format: vk::Format,
data: &[u8],
) -> RendererResult<Self> {
let (texture, staging_buff, staging_mem) =
execute_one_time_commands(device, transfer_queue, command_pool, |buffer| {
Self::cmd_from_rgba(device, buffer, mem_properties, width, height, data)
Self::cmd_from_rgba(device, buffer, mem_properties, width, height, format, data)
})??;

unsafe {
@@ -139,6 +141,7 @@ pub mod texture {
mem_properties: vk::PhysicalDeviceMemoryProperties,
width: u32,
height: u32,
format: vk::Format,
data: &[u8],
) -> RendererResult<(Self, vk::Buffer, vk::DeviceMemory)> {
let (buffer, buffer_mem) = create_and_fill_buffer(
@@ -160,7 +163,7 @@ pub mod texture {
.extent(extent)
.mip_levels(1)
.array_layers(1)
.format(vk::Format::R8G8B8A8_UNORM)
.format(format)
.tiling(vk::ImageTiling::OPTIMAL)
.initial_layout(vk::ImageLayout::UNDEFINED)
.usage(vk::ImageUsageFlags::TRANSFER_DST | vk::ImageUsageFlags::SAMPLED)
@@ -267,7 +270,7 @@ pub mod texture {
let create_info = vk::ImageViewCreateInfo::default()
.image(image)
.view_type(vk::ImageViewType::TYPE_2D)
.format(vk::Format::R8G8B8A8_UNORM)
.format(format)
.subresource_range(vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
129 changes: 90 additions & 39 deletions examples/textures.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod common;

use ash::vk;
use common::{vulkan::texture::Texture, App, VulkanContext};
use egui::{load::SizedTexture, Vec2, Widget};
use egui_ash_renderer::vulkan::*;
@@ -16,57 +17,37 @@ fn main() -> Result<(), Box<dyn Error>> {
let VulkanContext {
physical_device,
device,
graphics_queue,
command_pool,
..
} = &system.vulkan_context;

let image_bytes = include_bytes!("../assets/images/img2.jpg");
let image = image::load_from_memory(image_bytes).unwrap();
let width = image.width();
let height = image.height();
let data = image.to_rgba8().into_vec();

let memory_properties = unsafe {
system
.vulkan_context
.instance
.get_physical_device_memory_properties(*physical_device)
};

let mut texture = Texture::from_rgba8(
device,
*graphics_queue,
*command_pool,
memory_properties,
width,
height,
data.as_slice(),
)
.unwrap();

let descriptor_set_layout = create_vulkan_descriptor_set_layout(device).unwrap();
let descriptor_pool = create_vulkan_descriptor_pool(device, 2).unwrap();

let descriptor_pool = create_vulkan_descriptor_pool(device, 1).unwrap();
let mut srgb_texture = UserTexture::from_memory(
&mut system,
memory_properties,
descriptor_set_layout,
descriptor_pool,
vk::Format::R8G8B8A8_SRGB,
include_bytes!("../assets/images/img2.jpg"),
);

let descriptor_set = create_vulkan_descriptor_set(
device,
let mut linear_texture = UserTexture::from_memory(
&mut system,
memory_properties,
descriptor_set_layout,
descriptor_pool,
texture.image_view,
texture.sampler,
)
.unwrap();

let texture_id = system.renderer.add_user_texture(descriptor_set);

let egui_texture = SizedTexture {
id: texture_id,
size: Vec2 {
x: width as f32,
y: height as f32,
},
};
vk::Format::R8G8B8A8_UNORM,
include_bytes!("../assets/images/normals.jpg"),
);

let mut show_srgb_texture = true;

system.run( move |_, ctx| {
egui::Window::new("Managed texture")
@@ -78,7 +59,17 @@ fn main() -> Result<(), Box<dyn Error>> {
egui::Window::new("Used defined texture")
.show(ctx, |ui| {
ui.label("This texture is loaded and managed by the user.");
egui::Image::new(egui_texture).fit_to_original_size(0.8).ui(ui);
ui.horizontal(|ui| {
ui.radio_value(&mut show_srgb_texture, true, "sRGB");
ui.radio_value(&mut show_srgb_texture, false, "Linear");
});

let texture = if show_srgb_texture {
srgb_texture.egui_texture
} else {
linear_texture.egui_texture
};
egui::Image::new(texture).fit_to_original_size(0.8).ui(ui);
});
},
move |vulkan_ctx| {
@@ -87,10 +78,70 @@ fn main() -> Result<(), Box<dyn Error>> {
let device = &vulkan_ctx.device;
device.destroy_descriptor_pool(descriptor_pool, None);
device.destroy_descriptor_set_layout(descriptor_set_layout, None);
texture.destroy(device);
srgb_texture.texture.destroy(device);
linear_texture.texture.destroy(device);
}
}
)?;

Ok(())
}

struct UserTexture {
texture: Texture,
_set: vk::DescriptorSet,
egui_texture: SizedTexture,
}

impl UserTexture {
fn from_memory(
app: &mut App,
memory_properties: vk::PhysicalDeviceMemoryProperties,
set_layout: vk::DescriptorSetLayout,
set_pool: vk::DescriptorPool,
format: vk::Format,
data: &[u8],
) -> Self {
let image = image::load_from_memory(data).unwrap();
let width = image.width();
let height = image.height();
let data = image.to_rgba8().into_vec();

let texture = Texture::from_rgba8(
&app.vulkan_context.device,
app.vulkan_context.graphics_queue,
app.vulkan_context.command_pool,
memory_properties,
width,
height,
format,
data.as_slice(),
)
.unwrap();

let set = create_vulkan_descriptor_set(
&app.vulkan_context.device,
set_layout,
set_pool,
texture.image_view,
texture.sampler,
)
.unwrap();

let texture_id = app.renderer.add_user_texture(set);

let egui_texture = SizedTexture {
id: texture_id,
size: Vec2 {
x: width as f32,
y: height as f32,
},
};

Self {
texture,
_set: set,
egui_texture,
}
}
}
Loading