Update the debug UI
This commit is contained in:
parent
ff7c13c8fb
commit
61833168e5
|
@ -1788,8 +1788,10 @@ name = "pathfinder_gpu"
|
|||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.23.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pathfinder_color 0.5.0",
|
||||
"pathfinder_geometry 0.5.1",
|
||||
"pathfinder_resources 0.5.0",
|
||||
|
@ -1837,6 +1839,7 @@ dependencies = [
|
|||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dispatch 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"half 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"io-surface 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
//!
|
||||
//! The debug font atlas was generated using: https://evanw.github.io/font-texture-generator/
|
||||
|
||||
use crate::gpu::renderer::{RenderStats, RenderTime};
|
||||
use pathfinder_geometry::vector::{Vector2I, vec2i};
|
||||
use crate::gpu::options::RendererLevel;
|
||||
use crate::gpu::perf::{RenderStats, RenderTime};
|
||||
use pathfinder_geometry::rect::RectI;
|
||||
use pathfinder_geometry::vector::{Vector2I, vec2i};
|
||||
use pathfinder_gpu::Device;
|
||||
use pathfinder_gpu::allocator::GPUMemoryAllocator;
|
||||
use pathfinder_resources::ResourceLoader;
|
||||
use pathfinder_ui::{FONT_ASCENT, LINE_HEIGHT, PADDING, UIPresenter, WINDOW_COLOR};
|
||||
use std::collections::VecDeque;
|
||||
|
@ -27,35 +29,39 @@ use std::time::Duration;
|
|||
|
||||
const SAMPLE_BUFFER_SIZE: usize = 60;
|
||||
|
||||
const STATS_WINDOW_WIDTH: i32 = 325;
|
||||
const STATS_WINDOW_WIDTH: i32 = 275;
|
||||
const STATS_WINDOW_HEIGHT: i32 = LINE_HEIGHT * 4 + PADDING + 2;
|
||||
|
||||
const PERFORMANCE_WINDOW_WIDTH: i32 = 400;
|
||||
const PERFORMANCE_WINDOW_HEIGHT: i32 = LINE_HEIGHT * 4 + PADDING + 2;
|
||||
const PERFORMANCE_WINDOW_HEIGHT_D3D9: i32 = LINE_HEIGHT * 8 + PADDING + 2;
|
||||
const PERFORMANCE_WINDOW_HEIGHT_D3D11: i32 = LINE_HEIGHT * 10 + PADDING + 2;
|
||||
|
||||
pub struct DebugUIPresenter<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
const INFO_WINDOW_WIDTH: i32 = 425;
|
||||
const INFO_WINDOW_HEIGHT: i32 = LINE_HEIGHT * 2 + PADDING + 2;
|
||||
|
||||
pub struct DebugUIPresenter<D> where D: Device {
|
||||
pub ui_presenter: UIPresenter<D>,
|
||||
cpu_samples: SampleBuffer<RenderStats>,
|
||||
gpu_samples: SampleBuffer<RenderTime>,
|
||||
backend_name: &'static str,
|
||||
device_name: String,
|
||||
renderer_level: RendererLevel,
|
||||
}
|
||||
|
||||
impl<D> DebugUIPresenter<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
pub fn new(
|
||||
device: &D,
|
||||
resources: &dyn ResourceLoader,
|
||||
framebuffer_size: Vector2I,
|
||||
) -> DebugUIPresenter<D> {
|
||||
impl<D> DebugUIPresenter<D> where D: Device {
|
||||
pub fn new(device: &D,
|
||||
resources: &dyn ResourceLoader,
|
||||
framebuffer_size: Vector2I,
|
||||
renderer_level: RendererLevel)
|
||||
-> DebugUIPresenter<D> {
|
||||
let ui_presenter = UIPresenter::new(device, resources, framebuffer_size);
|
||||
DebugUIPresenter {
|
||||
ui_presenter,
|
||||
cpu_samples: SampleBuffer::new(),
|
||||
gpu_samples: SampleBuffer::new(),
|
||||
backend_name: device.backend_name(),
|
||||
device_name: device.device_name(),
|
||||
renderer_level,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,84 +70,222 @@ where
|
|||
self.gpu_samples.push(rendering_time);
|
||||
}
|
||||
|
||||
pub fn draw(&self, device: &D) {
|
||||
self.draw_stats_window(device);
|
||||
self.draw_performance_window(device);
|
||||
pub fn draw(&self, device: &D, allocator: &mut GPUMemoryAllocator<D>) {
|
||||
self.draw_stats_window(device, allocator);
|
||||
self.draw_performance_window(device, allocator);
|
||||
self.draw_info_window(device, allocator);
|
||||
}
|
||||
|
||||
fn draw_stats_window(&self, device: &D) {
|
||||
#[inline]
|
||||
pub fn set_framebuffer_size(&mut self, new_framebuffer_size: Vector2I) {
|
||||
self.ui_presenter.set_framebuffer_size(new_framebuffer_size)
|
||||
}
|
||||
|
||||
fn draw_info_window(&self, device: &D, allocator: &mut GPUMemoryAllocator<D>) {
|
||||
let framebuffer_size = self.ui_presenter.framebuffer_size();
|
||||
let bottom = framebuffer_size.y() - PADDING;
|
||||
let window_rect = RectI::new(
|
||||
vec2i(framebuffer_size.x() - PADDING - INFO_WINDOW_WIDTH,
|
||||
bottom - INFO_WINDOW_HEIGHT),
|
||||
vec2i(INFO_WINDOW_WIDTH, INFO_WINDOW_HEIGHT),
|
||||
);
|
||||
|
||||
self.ui_presenter.draw_solid_rounded_rect(device, allocator, window_rect, WINDOW_COLOR);
|
||||
|
||||
let origin = window_rect.origin() + vec2i(PADDING, PADDING + FONT_ASCENT);
|
||||
let level = match self.renderer_level {
|
||||
RendererLevel::D3D9 => "D3D9",
|
||||
RendererLevel::D3D11 => "D3D11",
|
||||
};
|
||||
self.ui_presenter.draw_text(device,
|
||||
allocator,
|
||||
&format!("{} ({} level)", self.backend_name, level),
|
||||
origin + vec2i(0, LINE_HEIGHT * 0),
|
||||
false);
|
||||
self.ui_presenter.draw_text(device,
|
||||
allocator,
|
||||
&self.device_name,
|
||||
origin + vec2i(0, LINE_HEIGHT * 1),
|
||||
false);
|
||||
|
||||
}
|
||||
|
||||
fn performance_window_size(&self) -> Vector2I {
|
||||
match self.renderer_level {
|
||||
RendererLevel::D3D9 => vec2i(PERFORMANCE_WINDOW_WIDTH, PERFORMANCE_WINDOW_HEIGHT_D3D9),
|
||||
RendererLevel::D3D11 => {
|
||||
vec2i(PERFORMANCE_WINDOW_WIDTH, PERFORMANCE_WINDOW_HEIGHT_D3D11)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_stats_window(&self, device: &D, allocator: &mut GPUMemoryAllocator<D>) {
|
||||
let performance_window_height = self.performance_window_size().y();
|
||||
|
||||
let framebuffer_size = self.ui_presenter.framebuffer_size();
|
||||
let bottom = framebuffer_size.y() - PADDING;
|
||||
let window_rect = RectI::new(
|
||||
vec2i(framebuffer_size.x() - PADDING - STATS_WINDOW_WIDTH,
|
||||
bottom - PERFORMANCE_WINDOW_HEIGHT - PADDING - STATS_WINDOW_HEIGHT),
|
||||
vec2i(STATS_WINDOW_WIDTH, STATS_WINDOW_HEIGHT),
|
||||
);
|
||||
bottom -
|
||||
PADDING -
|
||||
INFO_WINDOW_HEIGHT -
|
||||
performance_window_height -
|
||||
PADDING -
|
||||
STATS_WINDOW_HEIGHT),
|
||||
vec2i(STATS_WINDOW_WIDTH, STATS_WINDOW_HEIGHT));
|
||||
|
||||
self.ui_presenter.draw_solid_rounded_rect(device, window_rect, WINDOW_COLOR);
|
||||
self.ui_presenter.draw_solid_rounded_rect(device, allocator, window_rect, WINDOW_COLOR);
|
||||
|
||||
let mean_cpu_sample = self.cpu_samples.mean();
|
||||
let origin = window_rect.origin() + vec2i(PADDING, PADDING + FONT_ASCENT);
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("Paths: {}", mean_cpu_sample.path_count),
|
||||
origin,
|
||||
false,
|
||||
);
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
&format!("Solid Tiles: {}", mean_cpu_sample.solid_tile_count),
|
||||
allocator,
|
||||
&format!("Tiles: {}", mean_cpu_sample.total_tile_count),
|
||||
origin + vec2i(0, LINE_HEIGHT * 1),
|
||||
false,
|
||||
);
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
&format!("Alpha Tiles: {}", mean_cpu_sample.alpha_tile_count),
|
||||
allocator,
|
||||
&format!("Masks: {}", mean_cpu_sample.alpha_tile_count),
|
||||
origin + vec2i(0, LINE_HEIGHT * 2),
|
||||
false,
|
||||
);
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("Fills: {}", mean_cpu_sample.fill_count),
|
||||
origin + vec2i(0, LINE_HEIGHT * 3),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
fn draw_performance_window(&self, device: &D) {
|
||||
fn draw_performance_window(&self, device: &D, allocator: &mut GPUMemoryAllocator<D>) {
|
||||
let performance_window_size = self.performance_window_size();
|
||||
|
||||
let framebuffer_size = self.ui_presenter.framebuffer_size();
|
||||
let bottom = framebuffer_size.y() - PADDING;
|
||||
let window_rect = RectI::new(
|
||||
vec2i(framebuffer_size.x() - PADDING - PERFORMANCE_WINDOW_WIDTH,
|
||||
bottom - PERFORMANCE_WINDOW_HEIGHT),
|
||||
vec2i(PERFORMANCE_WINDOW_WIDTH, PERFORMANCE_WINDOW_HEIGHT),
|
||||
);
|
||||
vec2i(framebuffer_size.x() - PADDING - performance_window_size.x(),
|
||||
bottom - INFO_WINDOW_HEIGHT - PADDING - performance_window_size.y()),
|
||||
performance_window_size);
|
||||
|
||||
self.ui_presenter.draw_solid_rounded_rect(device, window_rect, WINDOW_COLOR);
|
||||
self.ui_presenter.draw_solid_rounded_rect(device, allocator, window_rect, WINDOW_COLOR);
|
||||
|
||||
let mean_cpu_sample = self.cpu_samples.mean();
|
||||
let origin = window_rect.origin() + vec2i(PADDING, PADDING + FONT_ASCENT);
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
&format!("CPU: {:.3} ms", duration_to_ms(mean_cpu_sample.cpu_build_time)),
|
||||
origin,
|
||||
false,
|
||||
);
|
||||
|
||||
let mean_gpu_sample = self.gpu_samples.mean();
|
||||
let origin = window_rect.origin() + vec2i(PADDING, PADDING + FONT_ASCENT);
|
||||
|
||||
let mut current_y = 0;
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
&format!("GPU: {:.3} ms", duration_to_ms(mean_gpu_sample.gpu_time)),
|
||||
origin + vec2i(0, LINE_HEIGHT * 1),
|
||||
allocator,
|
||||
&format!("Drawcalls: {}", mean_cpu_sample.drawcall_count),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
|
||||
let wallclock_time = f64::max(duration_to_ms(mean_gpu_sample.gpu_time),
|
||||
duration_to_ms(mean_cpu_sample.cpu_build_time));
|
||||
current_y += LINE_HEIGHT;
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("VRAM Alloc.: {:.1} MB",
|
||||
mean_cpu_sample.gpu_bytes_allocated as f64 / (1024.0 * 1024.0)),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
current_y += LINE_HEIGHT;
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("VRAM Commit: {:.1} MB",
|
||||
mean_cpu_sample.gpu_bytes_committed as f64 / (1024.0 * 1024.0)),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
current_y += LINE_HEIGHT;
|
||||
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("CPU: {:.3} ms", duration_to_ms(mean_cpu_sample.cpu_build_time)),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
current_y += LINE_HEIGHT;
|
||||
|
||||
match self.renderer_level {
|
||||
RendererLevel::D3D11 => {
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("GPU Dice: {:.3} ms", duration_to_ms(mean_gpu_sample.dice_time)),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
current_y += LINE_HEIGHT;
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("GPU Bin: {:.3} ms", duration_to_ms(mean_gpu_sample.bin_time)),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
current_y += LINE_HEIGHT;
|
||||
}
|
||||
RendererLevel::D3D9 => {}
|
||||
}
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("GPU Fill: {:.3} ms", duration_to_ms(mean_gpu_sample.fill_time)),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
current_y += LINE_HEIGHT;
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("GPU Comp.: {:.3} ms", duration_to_ms(mean_gpu_sample.composite_time)),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
current_y += LINE_HEIGHT;
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("GPU Other: {:.3} ms", duration_to_ms(mean_gpu_sample.other_time)),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
current_y += LINE_HEIGHT;
|
||||
|
||||
let mut wallclock_time = match self.renderer_level {
|
||||
RendererLevel::D3D11 => {
|
||||
duration_to_ms(mean_cpu_sample.cpu_build_time) +
|
||||
duration_to_ms(mean_gpu_sample.fill_time)
|
||||
}
|
||||
RendererLevel::D3D9 => {
|
||||
f64::max(duration_to_ms(mean_cpu_sample.cpu_build_time),
|
||||
duration_to_ms(mean_gpu_sample.fill_time))
|
||||
}
|
||||
};
|
||||
wallclock_time += duration_to_ms(mean_gpu_sample.composite_time) +
|
||||
duration_to_ms(mean_gpu_sample.dice_time) +
|
||||
duration_to_ms(mean_gpu_sample.bin_time) +
|
||||
duration_to_ms(mean_gpu_sample.other_time);
|
||||
self.ui_presenter.draw_text(
|
||||
device,
|
||||
allocator,
|
||||
&format!("Wallclock: {:.3} ms", wallclock_time),
|
||||
origin + vec2i(0, LINE_HEIGHT * 3),
|
||||
origin + vec2i(0, current_y),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,69 +7,88 @@ shaders/gl3/blit.fs.glsl
|
|||
shaders/gl3/blit.vs.glsl
|
||||
shaders/gl3/clear.fs.glsl
|
||||
shaders/gl3/clear.vs.glsl
|
||||
shaders/gl3/debug_solid.fs.glsl
|
||||
shaders/gl3/debug_solid.vs.glsl
|
||||
shaders/gl3/debug_texture.fs.glsl
|
||||
shaders/gl3/debug_texture.vs.glsl
|
||||
shaders/gl3/d3d9/fill.fs.glsl
|
||||
shaders/gl3/d3d9/fill.vs.glsl
|
||||
shaders/gl3/d3d9/tile.fs.glsl
|
||||
shaders/gl3/d3d9/tile.vs.glsl
|
||||
shaders/gl3/d3d9/tile_clip_combine.fs.glsl
|
||||
shaders/gl3/d3d9/tile_clip_combine.vs.glsl
|
||||
shaders/gl3/d3d9/tile_clip_copy.fs.glsl
|
||||
shaders/gl3/d3d9/tile_clip_copy.vs.glsl
|
||||
shaders/gl3/d3d9/tile_copy.fs.glsl
|
||||
shaders/gl3/d3d9/tile_copy.vs.glsl
|
||||
shaders/gl3/debug/solid.fs.glsl
|
||||
shaders/gl3/debug/solid.vs.glsl
|
||||
shaders/gl3/debug/texture.fs.glsl
|
||||
shaders/gl3/debug/texture.vs.glsl
|
||||
shaders/gl3/demo_ground.fs.glsl
|
||||
shaders/gl3/demo_ground.vs.glsl
|
||||
shaders/gl3/fill.fs.glsl
|
||||
shaders/gl3/fill.vs.glsl
|
||||
shaders/gl3/reproject.fs.glsl
|
||||
shaders/gl3/reproject.vs.glsl
|
||||
shaders/gl3/stencil.fs.glsl
|
||||
shaders/gl3/stencil.vs.glsl
|
||||
shaders/gl3/tile.fs.glsl
|
||||
shaders/gl3/tile.vs.glsl
|
||||
shaders/gl3/tile_clip.fs.glsl
|
||||
shaders/gl3/tile_clip.vs.glsl
|
||||
shaders/gl3/tile_copy.fs.glsl
|
||||
shaders/gl3/tile_copy.vs.glsl
|
||||
shaders/gl4/blit.fs.glsl
|
||||
shaders/gl4/blit.vs.glsl
|
||||
shaders/gl4/clear.fs.glsl
|
||||
shaders/gl4/clear.vs.glsl
|
||||
shaders/gl4/debug_solid.fs.glsl
|
||||
shaders/gl4/debug_solid.vs.glsl
|
||||
shaders/gl4/debug_texture.fs.glsl
|
||||
shaders/gl4/debug_texture.vs.glsl
|
||||
shaders/gl4/d3d11/bin.cs.glsl
|
||||
shaders/gl4/d3d11/bound.cs.glsl
|
||||
shaders/gl4/d3d11/dice.cs.glsl
|
||||
shaders/gl4/d3d11/fill.cs.glsl
|
||||
shaders/gl4/d3d11/propagate.cs.glsl
|
||||
shaders/gl4/d3d11/sort.cs.glsl
|
||||
shaders/gl4/d3d11/tile.cs.glsl
|
||||
shaders/gl4/d3d9/fill.fs.glsl
|
||||
shaders/gl4/d3d9/fill.vs.glsl
|
||||
shaders/gl4/d3d9/tile.fs.glsl
|
||||
shaders/gl4/d3d9/tile.vs.glsl
|
||||
shaders/gl4/d3d9/tile_clip_combine.fs.glsl
|
||||
shaders/gl4/d3d9/tile_clip_combine.vs.glsl
|
||||
shaders/gl4/d3d9/tile_clip_copy.fs.glsl
|
||||
shaders/gl4/d3d9/tile_clip_copy.vs.glsl
|
||||
shaders/gl4/d3d9/tile_copy.fs.glsl
|
||||
shaders/gl4/d3d9/tile_copy.vs.glsl
|
||||
shaders/gl4/debug/solid.fs.glsl
|
||||
shaders/gl4/debug/solid.vs.glsl
|
||||
shaders/gl4/debug/texture.fs.glsl
|
||||
shaders/gl4/debug/texture.vs.glsl
|
||||
shaders/gl4/demo_ground.fs.glsl
|
||||
shaders/gl4/demo_ground.vs.glsl
|
||||
shaders/gl4/fill.fs.glsl
|
||||
shaders/gl4/fill.vs.glsl
|
||||
shaders/gl4/reproject.fs.glsl
|
||||
shaders/gl4/reproject.vs.glsl
|
||||
shaders/gl4/stencil.fs.glsl
|
||||
shaders/gl4/stencil.vs.glsl
|
||||
shaders/gl4/tile.fs.glsl
|
||||
shaders/gl4/tile.vs.glsl
|
||||
shaders/gl4/tile_clip.fs.glsl
|
||||
shaders/gl4/tile_clip.vs.glsl
|
||||
shaders/gl4/tile_copy.fs.glsl
|
||||
shaders/gl4/tile_copy.vs.glsl
|
||||
shaders/metal/blit.fs.metal
|
||||
shaders/metal/blit.vs.metal
|
||||
shaders/metal/clear.fs.metal
|
||||
shaders/metal/clear.vs.metal
|
||||
shaders/metal/debug_solid.fs.metal
|
||||
shaders/metal/debug_solid.vs.metal
|
||||
shaders/metal/debug_texture.fs.metal
|
||||
shaders/metal/debug_texture.vs.metal
|
||||
shaders/metal/d3d11/bin.cs.metal
|
||||
shaders/metal/d3d11/bound.cs.metal
|
||||
shaders/metal/d3d11/dice.cs.metal
|
||||
shaders/metal/d3d11/fill.cs.metal
|
||||
shaders/metal/d3d11/propagate.cs.metal
|
||||
shaders/metal/d3d11/sort.cs.metal
|
||||
shaders/metal/d3d11/tile.cs.metal
|
||||
shaders/metal/d3d9/fill.fs.metal
|
||||
shaders/metal/d3d9/fill.vs.metal
|
||||
shaders/metal/d3d9/tile.fs.metal
|
||||
shaders/metal/d3d9/tile.vs.metal
|
||||
shaders/metal/d3d9/tile_clip_combine.fs.metal
|
||||
shaders/metal/d3d9/tile_clip_combine.vs.metal
|
||||
shaders/metal/d3d9/tile_clip_copy.fs.metal
|
||||
shaders/metal/d3d9/tile_clip_copy.vs.metal
|
||||
shaders/metal/d3d9/tile_copy.fs.metal
|
||||
shaders/metal/d3d9/tile_copy.vs.metal
|
||||
shaders/metal/debug/solid.fs.metal
|
||||
shaders/metal/debug/solid.vs.metal
|
||||
shaders/metal/debug/texture.fs.metal
|
||||
shaders/metal/debug/texture.vs.metal
|
||||
shaders/metal/demo_ground.fs.metal
|
||||
shaders/metal/demo_ground.vs.metal
|
||||
shaders/metal/fill.cs.metal
|
||||
shaders/metal/fill.fs.metal
|
||||
shaders/metal/fill.vs.metal
|
||||
shaders/metal/reproject.fs.metal
|
||||
shaders/metal/reproject.vs.metal
|
||||
shaders/metal/stencil.fs.metal
|
||||
shaders/metal/stencil.vs.metal
|
||||
shaders/metal/tile.fs.metal
|
||||
shaders/metal/tile.vs.metal
|
||||
shaders/metal/tile_clip.fs.metal
|
||||
shaders/metal/tile_clip.vs.metal
|
||||
shaders/metal/tile_copy.fs.metal
|
||||
shaders/metal/tile_copy.vs.metal
|
||||
textures/area-lut.png
|
||||
textures/debug-corner-fill.png
|
||||
textures/debug-corner-outline.png
|
||||
|
|
|
@ -3,36 +3,47 @@ TARGET_DIR?=../resources/shaders
|
|||
EMPTY=
|
||||
|
||||
SHADERS=\
|
||||
d3d9/fill.fs.glsl \
|
||||
d3d9/fill.vs.glsl \
|
||||
d3d9/tile.fs.glsl \
|
||||
d3d9/tile.vs.glsl \
|
||||
d3d9/tile_clip_combine.fs.glsl \
|
||||
d3d9/tile_clip_combine.vs.glsl \
|
||||
d3d9/tile_clip_copy.fs.glsl \
|
||||
d3d9/tile_clip_copy.vs.glsl \
|
||||
d3d9/tile_copy.fs.glsl \
|
||||
d3d9/tile_copy.vs.glsl \
|
||||
debug/solid.fs.glsl \
|
||||
debug/solid.vs.glsl \
|
||||
debug/texture.fs.glsl \
|
||||
debug/texture.vs.glsl \
|
||||
blit.fs.glsl \
|
||||
blit.vs.glsl \
|
||||
clear.fs.glsl \
|
||||
clear.vs.glsl \
|
||||
debug_solid.fs.glsl \
|
||||
debug_solid.vs.glsl \
|
||||
debug_texture.fs.glsl \
|
||||
debug_texture.vs.glsl \
|
||||
demo_ground.fs.glsl \
|
||||
demo_ground.vs.glsl \
|
||||
fill.fs.glsl \
|
||||
fill.vs.glsl \
|
||||
reproject.fs.glsl \
|
||||
reproject.vs.glsl \
|
||||
stencil.fs.glsl \
|
||||
stencil.vs.glsl \
|
||||
tile.fs.glsl \
|
||||
tile.vs.glsl \
|
||||
tile_clip.fs.glsl \
|
||||
tile_clip.vs.glsl \
|
||||
tile_copy.fs.glsl \
|
||||
tile_copy.vs.glsl \
|
||||
$(EMPTY)
|
||||
|
||||
COMPUTE_SHADERS=\
|
||||
fill.cs.glsl \
|
||||
d3d11/bin.cs.glsl \
|
||||
d3d11/bound.cs.glsl \
|
||||
d3d11/dice.cs.glsl \
|
||||
d3d11/fill.cs.glsl \
|
||||
d3d11/propagate.cs.glsl \
|
||||
d3d11/sort.cs.glsl \
|
||||
d3d11/tile.cs.glsl \
|
||||
$(EMPTY)
|
||||
|
||||
INCLUDES=\
|
||||
fill.inc.glsl \
|
||||
d3d11/fill_compute.inc.glsl \
|
||||
fill_area.inc.glsl \
|
||||
tile_fragment.inc.glsl \
|
||||
tile_vertex.inc.glsl \
|
||||
$(EMPTY)
|
||||
|
||||
OUT=\
|
||||
|
@ -58,6 +69,10 @@ HEADER="// Automatically generated from files in pathfinder/shaders/. Do not edi
|
|||
|
||||
GLSL_SED_ARGS=-e "s/\#version .*//" -e "s/\#line.*$$//"
|
||||
|
||||
GLSL_SHADER_TYPE.fs=frag
|
||||
GLSL_SHADER_TYPE.vs=vert
|
||||
GLSL_SHADER_TYPE.cs=comp
|
||||
|
||||
all: $(OUT)
|
||||
|
||||
.PHONY: clean
|
||||
|
@ -65,29 +80,14 @@ all: $(OUT)
|
|||
clean:
|
||||
rm -f $(OUT)
|
||||
|
||||
build/metal/%.fs.spv: %.fs.glsl $(INCLUDES)
|
||||
mkdir -p build/metal && glslangValidator $(GLSLANGFLAGS_METAL) -G$(GLSL_VERSION) -S frag -o $@ $<
|
||||
build/metal/%.spv: %.glsl $(INCLUDES)
|
||||
mkdir -p $(dir $@) && glslangValidator $(GLSLANGFLAGS_METAL) -G$(GLSL_VERSION) -S $(GLSL_SHADER_TYPE$(suffix $(basename $(notdir $<)))) -o $@ $<
|
||||
|
||||
$(TARGET_DIR)/gl3/%.fs.glsl: %.fs.glsl $(INCLUDES)
|
||||
mkdir -p $(TARGET_DIR)/gl3 && echo $(GLSL_VERSION_HEADER) > $@ && echo $(HEADER) >> $@ && ( glslangValidator $(GLSLANGFLAGS) -S frag -E $< | sed $(GLSL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )
|
||||
$(TARGET_DIR)/gl3/%.glsl: %.glsl $(INCLUDES)
|
||||
mkdir -p $(dir $@) && echo $(GLSL_VERSION_HEADER) > $@ && echo $(HEADER) >> $@ && ( glslangValidator $(GLSLANGFLAGS) -S $(GLSL_SHADER_TYPE$(suffix $(basename $(notdir $<)))) -E $< | sed $(GLSL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )
|
||||
|
||||
$(TARGET_DIR)/gl4/%.fs.glsl: %.fs.glsl $(INCLUDES)
|
||||
mkdir -p $(TARGET_DIR)/gl4 && echo $(GLSL_VERSION_HEADER) > $@ && echo $(HEADER) >> $@ && ( glslangValidator $(GLSLANGFLAGS) -S frag -E $< | sed $(GLSL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )
|
||||
$(TARGET_DIR)/gl4/%.glsl: %.glsl $(INCLUDES)
|
||||
mkdir -p $(dir $@) && echo $(GLSL_VERSION_HEADER) > $@ && echo $(HEADER) >> $@ && ( glslangValidator $(GLSLANGFLAGS) -S $(GLSL_SHADER_TYPE$(suffix $(basename $(notdir $<)))) -E $< | sed $(GLSL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )
|
||||
|
||||
build/metal/%.vs.spv: %.vs.glsl $(INCLUDES)
|
||||
mkdir -p build/metal && glslangValidator $(GLSLANGFLAGS_METAL) -G$(GLSL_VERSION) -S vert -o $@ $<
|
||||
|
||||
$(TARGET_DIR)/gl3/%.vs.glsl: %.vs.glsl $(INCLUDES)
|
||||
mkdir -p $(TARGET_DIR)/gl3 && echo $(GLSL_VERSION_HEADER) > $@ && echo $(HEADER) >> $@ && ( glslangValidator $(GLSLANGFLAGS) -S vert -E $< | sed $(GLSL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )
|
||||
|
||||
$(TARGET_DIR)/gl4/%.vs.glsl: %.vs.glsl $(INCLUDES)
|
||||
mkdir -p $(TARGET_DIR)/gl3 && echo $(GLSL_VERSION_HEADER) > $@ && echo $(HEADER) >> $@ && ( glslangValidator $(GLSLANGFLAGS) -S vert -E $< | sed $(GLSL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )
|
||||
|
||||
build/metal/%.cs.spv: %.cs.glsl $(INCLUDES)
|
||||
mkdir -p build/metal && glslangValidator $(GLSLANGFLAGS_METAL) -G$(GLSL_COMPUTE_VERSION) -S comp -o $@ $<
|
||||
|
||||
$(TARGET_DIR)/gl4/%.cs.glsl: %.cs.glsl $(INCLUDES)
|
||||
mkdir -p $(TARGET_DIR)/gl4 && echo $(GLSL_VERSION_HEADER) > $@ && echo $(HEADER) >> $@ && ( glslangValidator $(GLSLANGFLAGS) -S vert -E $< | sed $(GLSL_SED_ARGS) >> $@ ) || ( rm $@ && exit 1 )
|
||||
|
||||
$(TARGET_DIR)/metal/%.metal: build/metal/%.spv
|
||||
mkdir -p $(TARGET_DIR)/metal && echo $(HEADER) > $@ && ( $(SPIRVCROSS) $(SPIRVCROSSFLAGS) $< >> $@ ) || ( rm $@ && exit 1 )
|
||||
$(TARGET_DIR)/metal/%.metal: build/metal/%.spv
|
||||
mkdir -p $(dir $@) && echo $(HEADER) > $@ && ( $(SPIRVCROSS) $(SPIRVCROSSFLAGS) $< >> $@ ) || ( rm $@ && exit 1 )
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/debug_solid.fs.glsl
|
||||
// pathfinder/shaders/debug/solid.fs.glsl
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
|
@ -1,6 +1,6 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/debug_solid.vs.glsl
|
||||
// pathfinder/shaders/debug/solid.vs.glsl
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
|
@ -1,6 +1,6 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/debug_texture.fs.glsl
|
||||
// pathfinder/shaders/debug/texture.fs.glsl
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
|
@ -1,6 +1,6 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/debug_texture.vs.glsl
|
||||
// pathfinder/shaders/debug/texture.vs.glsl
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
302
ui/src/lib.rs
302
ui/src/lib.rs
|
@ -20,9 +20,10 @@ use hashbrown::HashMap;
|
|||
use pathfinder_color::ColorU;
|
||||
use pathfinder_geometry::rect::RectI;
|
||||
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2i};
|
||||
use pathfinder_gpu::{BlendFactor, BlendState, BufferData, BufferTarget, BufferUploadMode, Device};
|
||||
use pathfinder_gpu::{Primitive, RenderOptions, RenderState, RenderTarget, TextureFormat};
|
||||
use pathfinder_gpu::{UniformData, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
||||
use pathfinder_gpu::allocator::{BufferTag, GPUMemoryAllocator};
|
||||
use pathfinder_gpu::{BlendFactor, BlendState, BufferTarget, Device, Primitive, RenderOptions};
|
||||
use pathfinder_gpu::{RenderState, RenderTarget, TextureFormat, UniformData, VertexAttrClass};
|
||||
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
|
||||
use pathfinder_resources::ResourceLoader;
|
||||
use pathfinder_simd::default::F32x4;
|
||||
use serde_json;
|
||||
|
@ -71,9 +72,7 @@ pub struct UIPresenter<D> where D: Device {
|
|||
framebuffer_size: Vector2I,
|
||||
|
||||
texture_program: DebugTextureProgram<D>,
|
||||
texture_vertex_array: DebugTextureVertexArray<D>,
|
||||
solid_program: DebugSolidProgram<D>,
|
||||
solid_vertex_array: DebugSolidVertexArray<D>,
|
||||
font: DebugFont,
|
||||
|
||||
font_texture: D::Texture,
|
||||
|
@ -85,11 +84,9 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
pub fn new(device: &D, resources: &dyn ResourceLoader, framebuffer_size: Vector2I)
|
||||
-> UIPresenter<D> {
|
||||
let texture_program = DebugTextureProgram::new(device, resources);
|
||||
let texture_vertex_array = DebugTextureVertexArray::new(device, &texture_program);
|
||||
let font = DebugFont::load(resources);
|
||||
|
||||
let solid_program = DebugSolidProgram::new(device, resources);
|
||||
let solid_vertex_array = DebugSolidVertexArray::new(device, &solid_program);
|
||||
|
||||
let font_texture = device.create_texture_from_png(resources,
|
||||
FONT_PNG_NAME,
|
||||
|
@ -108,10 +105,8 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
framebuffer_size,
|
||||
|
||||
texture_program,
|
||||
texture_vertex_array,
|
||||
font,
|
||||
solid_program,
|
||||
solid_vertex_array,
|
||||
|
||||
font_texture,
|
||||
corner_fill_texture,
|
||||
|
@ -128,16 +123,25 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
}
|
||||
|
||||
|
||||
pub fn draw_solid_rect(&self, device: &D, rect: RectI, color: ColorU) {
|
||||
self.draw_rect(device, rect, color, true);
|
||||
pub fn draw_solid_rect(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
rect: RectI,
|
||||
color: ColorU) {
|
||||
self.draw_rect(device, allocator, rect, color, true);
|
||||
}
|
||||
|
||||
pub fn draw_rect_outline(&self, device: &D, rect: RectI, color: ColorU) {
|
||||
self.draw_rect(device, rect, color, false);
|
||||
pub fn draw_rect_outline(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
rect: RectI,
|
||||
color: ColorU) {
|
||||
self.draw_rect(device, allocator, rect, color, false);
|
||||
}
|
||||
|
||||
fn draw_rect(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
rect: RectI,
|
||||
color: ColorU,
|
||||
filled: bool) {
|
||||
|
@ -150,12 +154,14 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
|
||||
if filled {
|
||||
self.draw_solid_rects_with_vertex_data(device,
|
||||
allocator,
|
||||
&vertex_data,
|
||||
&QUAD_INDICES,
|
||||
color,
|
||||
true);
|
||||
} else {
|
||||
self.draw_solid_rects_with_vertex_data(device,
|
||||
allocator,
|
||||
&vertex_data,
|
||||
&RECT_LINE_INDICES,
|
||||
color,
|
||||
|
@ -165,39 +171,60 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
|
||||
fn draw_solid_rects_with_vertex_data(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
vertex_data: &[DebugSolidVertex],
|
||||
index_data: &[u32],
|
||||
color: ColorU,
|
||||
filled: bool) {
|
||||
device.allocate_buffer(&self.solid_vertex_array.vertex_buffer,
|
||||
BufferData::Memory(vertex_data),
|
||||
BufferTarget::Vertex);
|
||||
device.allocate_buffer(&self.solid_vertex_array.index_buffer,
|
||||
BufferData::Memory(index_data),
|
||||
BufferTarget::Index);
|
||||
let vertex_buffer_id =
|
||||
allocator.allocate_buffer::<DebugSolidVertex>(device,
|
||||
vertex_data.len() as u64,
|
||||
BufferTag("SolidVertexDebug"));
|
||||
let index_buffer_id = allocator.allocate_buffer::<u32>(device,
|
||||
index_data.len() as u64,
|
||||
BufferTag("SolidIndexDebug"));
|
||||
{
|
||||
let vertex_buffer = allocator.get_buffer(vertex_buffer_id);
|
||||
let index_buffer = allocator.get_buffer(index_buffer_id);
|
||||
device.upload_to_buffer(&vertex_buffer, 0, vertex_data, BufferTarget::Vertex);
|
||||
device.upload_to_buffer(&index_buffer, 0, index_data, BufferTarget::Index);
|
||||
let solid_vertex_array = DebugSolidVertexArray::new(device,
|
||||
&self.solid_program,
|
||||
vertex_buffer,
|
||||
index_buffer);
|
||||
|
||||
let primitive = if filled { Primitive::Triangles } else { Primitive::Lines };
|
||||
device.draw_elements(index_data.len() as u32, &RenderState {
|
||||
target: &RenderTarget::Default,
|
||||
program: &self.solid_program.program,
|
||||
vertex_array: &self.solid_vertex_array.vertex_array,
|
||||
primitive,
|
||||
uniforms: &[
|
||||
(&self.solid_program.framebuffer_size_uniform,
|
||||
UniformData::Vec2(self.framebuffer_size.0.to_f32x2())),
|
||||
(&self.solid_program.color_uniform, get_color_uniform(color)),
|
||||
],
|
||||
textures: &[],
|
||||
images: &[],
|
||||
viewport: RectI::new(Vector2I::default(), self.framebuffer_size),
|
||||
options: RenderOptions {
|
||||
blend: Some(alpha_blend_state()),
|
||||
..RenderOptions::default()
|
||||
},
|
||||
});
|
||||
let primitive = if filled { Primitive::Triangles } else { Primitive::Lines };
|
||||
device.draw_elements(index_data.len() as u32, &RenderState {
|
||||
target: &RenderTarget::Default,
|
||||
program: &self.solid_program.program,
|
||||
vertex_array: &solid_vertex_array.vertex_array,
|
||||
primitive,
|
||||
uniforms: &[
|
||||
(&self.solid_program.framebuffer_size_uniform,
|
||||
UniformData::Vec2(self.framebuffer_size.0.to_f32x2())),
|
||||
(&self.solid_program.color_uniform, get_color_uniform(color)),
|
||||
],
|
||||
textures: &[],
|
||||
images: &[],
|
||||
storage_buffers: &[],
|
||||
viewport: RectI::new(Vector2I::default(), self.framebuffer_size),
|
||||
options: RenderOptions {
|
||||
blend: Some(alpha_blend_state()),
|
||||
..RenderOptions::default()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
allocator.free_buffer(index_buffer_id);
|
||||
allocator.free_buffer(vertex_buffer_id);
|
||||
}
|
||||
|
||||
pub fn draw_text(&self, device: &D, string: &str, origin: Vector2I, invert: bool) {
|
||||
pub fn draw_text(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
string: &str,
|
||||
origin: Vector2I,
|
||||
invert: bool) {
|
||||
let mut next = origin;
|
||||
let char_count = string.chars().count();
|
||||
let mut vertex_data = Vec::with_capacity(char_count * 4);
|
||||
|
@ -227,6 +254,7 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
|
||||
let color = if invert { INVERTED_TEXT_COLOR } else { TEXT_COLOR };
|
||||
self.draw_texture_with_vertex_data(device,
|
||||
allocator,
|
||||
&vertex_data,
|
||||
&index_data,
|
||||
&self.font_texture,
|
||||
|
@ -235,6 +263,7 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
|
||||
pub fn draw_texture(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
origin: Vector2I,
|
||||
texture: &D::Texture,
|
||||
color: ColorU) {
|
||||
|
@ -247,7 +276,12 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
DebugTextureVertex::new(position_rect.lower_left(), tex_coord_rect.lower_left()),
|
||||
];
|
||||
|
||||
self.draw_texture_with_vertex_data(device, &vertex_data, &QUAD_INDICES, texture, color);
|
||||
self.draw_texture_with_vertex_data(device,
|
||||
allocator,
|
||||
&vertex_data,
|
||||
&QUAD_INDICES,
|
||||
texture,
|
||||
color);
|
||||
}
|
||||
|
||||
pub fn measure_text(&self, string: &str) -> i32 {
|
||||
|
@ -268,10 +302,14 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
SEGMENT_SIZE * segment_count as i32 + (segment_count - 1) as i32
|
||||
}
|
||||
|
||||
pub fn draw_solid_rounded_rect(&self, device: &D, rect: RectI, color: ColorU) {
|
||||
pub fn draw_solid_rounded_rect(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
rect: RectI,
|
||||
color: ColorU) {
|
||||
let corner_texture = self.corner_texture(true);
|
||||
let corner_rects = CornerRects::new(device, rect, corner_texture);
|
||||
self.draw_rounded_rect_corners(device, color, corner_texture, &corner_rects);
|
||||
self.draw_rounded_rect_corners(device, allocator, color, corner_texture, &corner_rects);
|
||||
|
||||
let solid_rect_mid = RectI::from_points(corner_rects.upper_left.upper_right(),
|
||||
corner_rects.lower_right.lower_left());
|
||||
|
@ -302,16 +340,21 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 8));
|
||||
|
||||
self.draw_solid_rects_with_vertex_data(device,
|
||||
allocator,
|
||||
&vertex_data,
|
||||
&index_data[0..18],
|
||||
color,
|
||||
true);
|
||||
}
|
||||
|
||||
pub fn draw_rounded_rect_outline(&self, device: &D, rect: RectI, color: ColorU) {
|
||||
pub fn draw_rounded_rect_outline(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
rect: RectI,
|
||||
color: ColorU) {
|
||||
let corner_texture = self.corner_texture(false);
|
||||
let corner_rects = CornerRects::new(device, rect, corner_texture);
|
||||
self.draw_rounded_rect_corners(device, color, corner_texture, &corner_rects);
|
||||
self.draw_rounded_rect_corners(device, allocator, color, corner_texture, &corner_rects);
|
||||
|
||||
let vertex_data = vec![
|
||||
DebugSolidVertex::new(corner_rects.upper_left.upper_right()),
|
||||
|
@ -325,18 +368,34 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
];
|
||||
|
||||
let index_data = &OUTLINE_RECT_LINE_INDICES;
|
||||
self.draw_solid_rects_with_vertex_data(device, &vertex_data, index_data, color, false);
|
||||
self.draw_solid_rects_with_vertex_data(device,
|
||||
allocator,
|
||||
&vertex_data,
|
||||
index_data,
|
||||
color,
|
||||
false);
|
||||
}
|
||||
|
||||
// TODO(pcwalton): `LineSegment2I`.
|
||||
fn draw_line(&self, device: &D, from: Vector2I, to: Vector2I, color: ColorU) {
|
||||
fn draw_line(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
from: Vector2I,
|
||||
to: Vector2I,
|
||||
color: ColorU) {
|
||||
let vertex_data = vec![DebugSolidVertex::new(from), DebugSolidVertex::new(to)];
|
||||
self.draw_solid_rects_with_vertex_data(device, &vertex_data, &[0, 1], color, false);
|
||||
self.draw_solid_rects_with_vertex_data(device,
|
||||
allocator,
|
||||
&vertex_data,
|
||||
&[0, 1],
|
||||
color,
|
||||
false);
|
||||
|
||||
}
|
||||
|
||||
fn draw_rounded_rect_corners(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
color: ColorU,
|
||||
texture: &D::Texture,
|
||||
corner_rects: &CornerRects) {
|
||||
|
@ -387,7 +446,12 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 8));
|
||||
index_data.extend(QUAD_INDICES.iter().map(|&index| index + 12));
|
||||
|
||||
self.draw_texture_with_vertex_data(device, &vertex_data, &index_data, texture, color);
|
||||
self.draw_texture_with_vertex_data(device,
|
||||
allocator,
|
||||
&vertex_data,
|
||||
&index_data,
|
||||
texture,
|
||||
color);
|
||||
}
|
||||
|
||||
fn corner_texture(&self, filled: bool) -> &D::Texture {
|
||||
|
@ -396,44 +460,66 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
|
||||
fn draw_texture_with_vertex_data(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
vertex_data: &[DebugTextureVertex],
|
||||
index_data: &[u32],
|
||||
texture: &D::Texture,
|
||||
color: ColorU) {
|
||||
device.allocate_buffer(&self.texture_vertex_array.vertex_buffer,
|
||||
BufferData::Memory(vertex_data),
|
||||
BufferTarget::Vertex);
|
||||
device.allocate_buffer(&self.texture_vertex_array.index_buffer,
|
||||
BufferData::Memory(index_data),
|
||||
BufferTarget::Index);
|
||||
let vertex_buffer_id =
|
||||
allocator.allocate_buffer::<DebugTextureVertex>(device,
|
||||
vertex_data.len() as u64,
|
||||
BufferTag("TextureVertexDebug"));
|
||||
let index_buffer_id = allocator.allocate_buffer::<u32>(device,
|
||||
index_data.len() as u64,
|
||||
BufferTag("TextureIndexDebug"));
|
||||
{
|
||||
let vertex_buffer = allocator.get_buffer(vertex_buffer_id);
|
||||
let index_buffer = allocator.get_buffer(index_buffer_id);
|
||||
device.upload_to_buffer(&vertex_buffer, 0, vertex_data, BufferTarget::Vertex);
|
||||
device.upload_to_buffer(&index_buffer, 0, index_data, BufferTarget::Index);
|
||||
|
||||
device.draw_elements(index_data.len() as u32, &RenderState {
|
||||
target: &RenderTarget::Default,
|
||||
program: &self.texture_program.program,
|
||||
vertex_array: &self.texture_vertex_array.vertex_array,
|
||||
primitive: Primitive::Triangles,
|
||||
textures: &[(&self.texture_program.texture, &texture)],
|
||||
images: &[],
|
||||
uniforms: &[
|
||||
(&self.texture_program.framebuffer_size_uniform,
|
||||
UniformData::Vec2(self.framebuffer_size.0.to_f32x2())),
|
||||
(&self.texture_program.color_uniform, get_color_uniform(color)),
|
||||
(&self.texture_program.texture_size_uniform,
|
||||
UniformData::Vec2(device.texture_size(&texture).0.to_f32x2()))
|
||||
],
|
||||
viewport: RectI::new(Vector2I::default(), self.framebuffer_size),
|
||||
options: RenderOptions {
|
||||
blend: Some(alpha_blend_state()),
|
||||
..RenderOptions::default()
|
||||
},
|
||||
});
|
||||
let texture_vertex_array = DebugTextureVertexArray::new(device,
|
||||
&self.texture_program,
|
||||
vertex_buffer,
|
||||
index_buffer);
|
||||
|
||||
device.draw_elements(index_data.len() as u32, &RenderState {
|
||||
target: &RenderTarget::Default,
|
||||
program: &self.texture_program.program,
|
||||
vertex_array: &texture_vertex_array.vertex_array,
|
||||
primitive: Primitive::Triangles,
|
||||
textures: &[(&self.texture_program.texture, &texture)],
|
||||
images: &[],
|
||||
storage_buffers: &[],
|
||||
uniforms: &[
|
||||
(&self.texture_program.framebuffer_size_uniform,
|
||||
UniformData::Vec2(self.framebuffer_size.0.to_f32x2())),
|
||||
(&self.texture_program.color_uniform, get_color_uniform(color)),
|
||||
(&self.texture_program.texture_size_uniform,
|
||||
UniformData::Vec2(device.texture_size(&texture).0.to_f32x2()))
|
||||
],
|
||||
viewport: RectI::new(Vector2I::default(), self.framebuffer_size),
|
||||
options: RenderOptions {
|
||||
blend: Some(alpha_blend_state()),
|
||||
..RenderOptions::default()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
allocator.free_buffer(index_buffer_id);
|
||||
allocator.free_buffer(vertex_buffer_id);
|
||||
}
|
||||
|
||||
pub fn draw_button(&mut self, device: &D, origin: Vector2I, texture: &D::Texture) -> bool {
|
||||
pub fn draw_button(&mut self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
origin: Vector2I,
|
||||
texture: &D::Texture) -> bool {
|
||||
let button_rect = RectI::new(origin, vec2i(BUTTON_WIDTH, BUTTON_HEIGHT));
|
||||
self.draw_solid_rounded_rect(device, button_rect, WINDOW_COLOR);
|
||||
self.draw_rounded_rect_outline(device, button_rect, OUTLINE_COLOR);
|
||||
self.draw_solid_rounded_rect(device, allocator, button_rect, WINDOW_COLOR);
|
||||
self.draw_rounded_rect_outline(device, allocator, button_rect, OUTLINE_COLOR);
|
||||
self.draw_texture(device,
|
||||
allocator,
|
||||
origin + vec2i(PADDING, PADDING),
|
||||
texture,
|
||||
BUTTON_ICON_COLOR);
|
||||
|
@ -442,11 +528,13 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
|
||||
pub fn draw_text_switch(&mut self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
mut origin: Vector2I,
|
||||
segment_labels: &[&str],
|
||||
mut value: u8)
|
||||
-> u8 {
|
||||
if let Some(new_value) = self.draw_segmented_control(device,
|
||||
allocator,
|
||||
origin,
|
||||
Some(value),
|
||||
segment_labels.len() as u8) {
|
||||
|
@ -458,6 +546,7 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
let label_width = self.measure_text(segment_label);
|
||||
let offset = SEGMENT_SIZE / 2 - label_width / 2;
|
||||
self.draw_text(device,
|
||||
allocator,
|
||||
segment_label,
|
||||
origin + vec2i(offset, 0),
|
||||
segment_index as u8 == value);
|
||||
|
@ -469,12 +558,14 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
|
||||
pub fn draw_image_segmented_control(&mut self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
mut origin: Vector2I,
|
||||
segment_textures: &[&D::Texture],
|
||||
mut value: Option<u8>)
|
||||
-> Option<u8> {
|
||||
let mut clicked_segment = None;
|
||||
if let Some(segment_index) = self.draw_segmented_control(device,
|
||||
allocator,
|
||||
origin,
|
||||
value,
|
||||
segment_textures.len() as u8) {
|
||||
|
@ -493,7 +584,7 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
TEXT_COLOR
|
||||
};
|
||||
|
||||
self.draw_texture(device, origin + offset, segment_texture, color);
|
||||
self.draw_texture(device, allocator, origin + offset, segment_texture, color);
|
||||
origin += vec2i(SEGMENT_SIZE + 1, 0);
|
||||
}
|
||||
|
||||
|
@ -502,6 +593,7 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
|
||||
fn draw_segmented_control(&mut self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
origin: Vector2I,
|
||||
mut value: Option<u8>,
|
||||
segment_count: u8)
|
||||
|
@ -518,13 +610,14 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
clicked_segment = Some(segment);
|
||||
}
|
||||
|
||||
self.draw_solid_rounded_rect(device, widget_rect, WINDOW_COLOR);
|
||||
self.draw_rounded_rect_outline(device, widget_rect, OUTLINE_COLOR);
|
||||
self.draw_solid_rounded_rect(device, allocator, widget_rect, WINDOW_COLOR);
|
||||
self.draw_rounded_rect_outline(device, allocator, widget_rect, OUTLINE_COLOR);
|
||||
|
||||
if let Some(value) = value {
|
||||
let highlight_size = vec2i(SEGMENT_SIZE, BUTTON_HEIGHT);
|
||||
let x_offset = value as i32 * SEGMENT_SIZE + (value as i32 - 1);
|
||||
self.draw_solid_rounded_rect(device,
|
||||
allocator,
|
||||
RectI::new(origin + vec2i(x_offset, 0), highlight_size),
|
||||
TEXT_COLOR);
|
||||
}
|
||||
|
@ -536,6 +629,7 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
Some(value) if value == prev_segment_index || value == next_segment_index => {}
|
||||
_ => {
|
||||
self.draw_line(device,
|
||||
allocator,
|
||||
segment_origin,
|
||||
segment_origin + vec2i(0, BUTTON_HEIGHT),
|
||||
TEXT_COLOR);
|
||||
|
@ -547,7 +641,11 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
clicked_segment
|
||||
}
|
||||
|
||||
pub fn draw_tooltip(&self, device: &D, string: &str, rect: RectI) {
|
||||
pub fn draw_tooltip(&self,
|
||||
device: &D,
|
||||
allocator: &mut GPUMemoryAllocator<D>,
|
||||
string: &str,
|
||||
rect: RectI) {
|
||||
if !rect.to_f32().contains_point(self.mouse_position) {
|
||||
return;
|
||||
}
|
||||
|
@ -556,8 +654,15 @@ impl<D> UIPresenter<D> where D: Device {
|
|||
let window_size = vec2i(text_size + PADDING * 2, TOOLTIP_HEIGHT);
|
||||
let origin = rect.origin() - vec2i(0, window_size.y() + PADDING);
|
||||
|
||||
self.draw_solid_rounded_rect(device, RectI::new(origin, window_size), WINDOW_COLOR);
|
||||
self.draw_text(device, string, origin + vec2i(PADDING, PADDING + FONT_ASCENT), false);
|
||||
self.draw_solid_rounded_rect(device,
|
||||
allocator,
|
||||
RectI::new(origin, window_size),
|
||||
WINDOW_COLOR);
|
||||
self.draw_text(device,
|
||||
allocator,
|
||||
string,
|
||||
origin + vec2i(PADDING, PADDING + FONT_ASCENT),
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,7 +676,7 @@ struct DebugTextureProgram<D> where D: Device {
|
|||
|
||||
impl<D> DebugTextureProgram<D> where D: Device {
|
||||
fn new(device: &D, resources: &dyn ResourceLoader) -> DebugTextureProgram<D> {
|
||||
let program = device.create_raster_program(resources, "debug_texture");
|
||||
let program = device.create_raster_program(resources, "debug/texture");
|
||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||
let texture_size_uniform = device.get_uniform(&program, "TextureSize");
|
||||
let color_uniform = device.get_uniform(&program, "Color");
|
||||
|
@ -588,15 +693,14 @@ impl<D> DebugTextureProgram<D> where D: Device {
|
|||
|
||||
struct DebugTextureVertexArray<D> where D: Device {
|
||||
vertex_array: D::VertexArray,
|
||||
vertex_buffer: D::Buffer,
|
||||
index_buffer: D::Buffer,
|
||||
}
|
||||
|
||||
impl<D> DebugTextureVertexArray<D> where D: Device {
|
||||
fn new(device: &D, debug_texture_program: &DebugTextureProgram<D>)
|
||||
fn new(device: &D,
|
||||
debug_texture_program: &DebugTextureProgram<D>,
|
||||
vertex_buffer: &D::Buffer,
|
||||
index_buffer: &D::Buffer)
|
||||
-> DebugTextureVertexArray<D> {
|
||||
let vertex_buffer = device.create_buffer(BufferUploadMode::Dynamic);
|
||||
let index_buffer = device.create_buffer(BufferUploadMode::Dynamic);
|
||||
let vertex_array = device.create_vertex_array();
|
||||
|
||||
let position_attr = device.get_vertex_attr(&debug_texture_program.program, "Position")
|
||||
|
@ -604,8 +708,8 @@ impl<D> DebugTextureVertexArray<D> where D: Device {
|
|||
let tex_coord_attr = device.get_vertex_attr(&debug_texture_program.program, "TexCoord")
|
||||
.unwrap();
|
||||
|
||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||
device.bind_buffer(&vertex_array, &index_buffer, BufferTarget::Index);
|
||||
device.bind_buffer(&vertex_array, vertex_buffer, BufferTarget::Vertex);
|
||||
device.bind_buffer(&vertex_array, index_buffer, BufferTarget::Index);
|
||||
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
|
@ -625,20 +729,20 @@ impl<D> DebugTextureVertexArray<D> where D: Device {
|
|||
buffer_index: 0,
|
||||
});
|
||||
|
||||
DebugTextureVertexArray { vertex_array, vertex_buffer, index_buffer }
|
||||
DebugTextureVertexArray { vertex_array }
|
||||
}
|
||||
}
|
||||
|
||||
struct DebugSolidVertexArray<D> where D: Device {
|
||||
vertex_array: D::VertexArray,
|
||||
vertex_buffer: D::Buffer,
|
||||
index_buffer: D::Buffer,
|
||||
}
|
||||
|
||||
impl<D> DebugSolidVertexArray<D> where D: Device {
|
||||
fn new(device: &D, debug_solid_program: &DebugSolidProgram<D>) -> DebugSolidVertexArray<D> {
|
||||
let vertex_buffer = device.create_buffer(BufferUploadMode::Dynamic);
|
||||
let index_buffer = device.create_buffer(BufferUploadMode::Dynamic);
|
||||
fn new(device: &D,
|
||||
debug_solid_program: &DebugSolidProgram<D>,
|
||||
vertex_buffer: &D::Buffer,
|
||||
index_buffer: &D::Buffer)
|
||||
-> DebugSolidVertexArray<D> {
|
||||
let vertex_array = device.create_vertex_array();
|
||||
|
||||
let position_attr =
|
||||
|
@ -655,7 +759,7 @@ impl<D> DebugSolidVertexArray<D> where D: Device {
|
|||
buffer_index: 0,
|
||||
});
|
||||
|
||||
DebugSolidVertexArray { vertex_array, vertex_buffer, index_buffer }
|
||||
DebugSolidVertexArray { vertex_array }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -667,7 +771,7 @@ struct DebugSolidProgram<D> where D: Device {
|
|||
|
||||
impl<D> DebugSolidProgram<D> where D: Device {
|
||||
fn new(device: &D, resources: &dyn ResourceLoader) -> DebugSolidProgram<D> {
|
||||
let program = device.create_raster_program(resources, "debug_solid");
|
||||
let program = device.create_raster_program(resources, "debug/solid");
|
||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||
let color_uniform = device.get_uniform(&program, "Color");
|
||||
DebugSolidProgram { program, framebuffer_size_uniform, color_uniform }
|
||||
|
|
Loading…
Reference in New Issue