Fix pixel sizing, buffer binding entry
This commit is contained in:
@ -339,7 +339,7 @@ pub fn main_fs(
|
||||
#[spirv(frag_coord)] frag_coord: Vec4,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] viewport_constants: &ViewportConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] accum_constants: &AccumConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] _accum_image: &mut [Vec4],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] accum_image: &mut [Vec4],
|
||||
output: &mut Vec4,
|
||||
) {
|
||||
// Bootleg texture sampling; map from viewport image pixel coordinates to accumulator image
|
||||
@ -365,29 +365,19 @@ pub fn main_fs(
|
||||
let offset_x = (v_width * scale - a_width) / 2.0;
|
||||
let offset_y = (v_height * scale - a_height) / 2.0;
|
||||
|
||||
let _accum_coordinate = viewport_coordinate.as_vec2() * scale - vec2(offset_x, offset_y);
|
||||
let accum_coordinate = viewport_coordinate.as_vec2() * scale - vec2(offset_x, offset_y);
|
||||
|
||||
/*
|
||||
if accum_coordinate.x < 0.0
|
||||
|| accum_coordinate.x >= ifs_constants.accum_width as f32
|
||||
|| accum_coordinate.x >= accum_constants.width as f32
|
||||
|| accum_coordinate.y < 0.0
|
||||
|| accum_coordinate.y >= ifs_constants.accum_height as f32
|
||||
|| accum_coordinate.y >= accum_constants.height as f32
|
||||
{
|
||||
*output = ifs_constants.background_color;
|
||||
*output = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
} else {
|
||||
*output = accum_image[image_index(
|
||||
accum_coordinate.x as i32,
|
||||
accum_coordinate.y as i32,
|
||||
ifs_constants.accum_width,
|
||||
accum_constants.width,
|
||||
) as usize];
|
||||
}
|
||||
*/
|
||||
|
||||
if viewport_coordinate.x == 0
|
||||
|| viewport_coordinate.x == viewport_constants.width as u32 - 1
|
||||
|| viewport_coordinate.y == 0
|
||||
|| viewport_coordinate.y == viewport_constants.height as u32 - 1
|
||||
{
|
||||
*output = glam::Vec4::splat(1.);
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,13 @@ egui = "0.31"
|
||||
egui-wgpu = "0.31"
|
||||
env_logger.workspace = true
|
||||
flare-shader = { path = "../flare-shader" }
|
||||
futures = "0.3"
|
||||
futures-executor.workspace = true
|
||||
glam.workspace = true
|
||||
image = "0.25"
|
||||
rand = { workspace = true, default-features = true }
|
||||
rand_xoshiro.workspace = true
|
||||
wgpu.workspace = true
|
||||
winit.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
spirv-builder.workspace = true
|
||||
|
@ -1,9 +1,17 @@
|
||||
use eframe::Frame;
|
||||
use eframe::epaint::PaintCallbackInfo;
|
||||
use egui::Context;
|
||||
use egui::{Context, Rect};
|
||||
use egui_wgpu::{CallbackResources, CallbackTrait, ScreenDescriptor};
|
||||
use flare_shader::{CameraConstants, Coefs, ViewportConstants, ThreadState, Transform, Variation, VariationKind, AccumConstants};
|
||||
use flare_shader::{
|
||||
AccumConstants, CameraConstants, Coefs, ThreadState, Transform, Variation, VariationKind,
|
||||
ViewportConstants,
|
||||
};
|
||||
use futures::channel::oneshot;
|
||||
use futures_executor::block_on;
|
||||
use image::codecs::png::PngEncoder;
|
||||
use image::{ExtendedColorType, ImageEncoder};
|
||||
use rand::thread_rng;
|
||||
use std::fs::File;
|
||||
use wgpu::util::DeviceExt;
|
||||
use wgpu::{CommandBuffer, CommandEncoder, Device, Queue, RenderPass};
|
||||
|
||||
@ -74,11 +82,11 @@ impl RenderGroup {
|
||||
|
||||
fn build_image_accum_buffer(device: &wgpu::Device, width: i32, height: i32) -> wgpu::Buffer {
|
||||
let pixel_count = (width * height) as u64;
|
||||
let size = pixel_count * size_of::<f32>() as u64;
|
||||
let size = pixel_count * 4 * size_of::<f32>() as u64;
|
||||
device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("accum_image"),
|
||||
size,
|
||||
usage: wgpu::BufferUsages::STORAGE,
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC,
|
||||
mapped_at_creation: false,
|
||||
})
|
||||
}
|
||||
@ -115,12 +123,7 @@ impl RenderGroup {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Self {
|
||||
pub fn new(device: &wgpu::Device, queue: &wgpu::Queue, width: i32, height: i32) -> Self {
|
||||
let bind_group_layout = Self::bind_group_layout(device);
|
||||
|
||||
let viewport_constants_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
@ -146,8 +149,7 @@ impl RenderGroup {
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
});
|
||||
|
||||
let image_accum_buffer =
|
||||
Self::build_image_accum_buffer(device, width, height);
|
||||
let image_accum_buffer = Self::build_image_accum_buffer(device, width, height);
|
||||
|
||||
let bind_group = Self::build_bind_group(
|
||||
device,
|
||||
@ -192,8 +194,17 @@ impl RenderGroup {
|
||||
|
||||
pub fn set_viewport_dimensions(&mut self, rect: egui::Rect) {
|
||||
let offset = rect.left_top();
|
||||
let viewport_constants = ViewportConstants::new(offset.x as i32, offset.y as i32, rect.width() as i32, rect.height() as i32);
|
||||
self.queue.write_buffer(&self.viewport_constants_buffer, 0, bytemuck::cast_slice(&[viewport_constants]))
|
||||
let viewport_constants = ViewportConstants::new(
|
||||
offset.x as i32,
|
||||
offset.y as i32,
|
||||
rect.width() as i32,
|
||||
rect.height() as i32,
|
||||
);
|
||||
self.queue.write_buffer(
|
||||
&self.viewport_constants_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[viewport_constants]),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn bind_group(&self) -> &wgpu::BindGroup {
|
||||
@ -276,20 +287,24 @@ impl IfsGroup {
|
||||
}
|
||||
|
||||
pub fn set_transforms(&mut self, transforms: &[Transform]) {
|
||||
let transforms_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("transforms"),
|
||||
contents: bytemuck::cast_slice(transforms),
|
||||
usage: wgpu::BufferUsages::STORAGE,
|
||||
});
|
||||
let transforms_buffer = self
|
||||
.device
|
||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("transforms"),
|
||||
contents: bytemuck::cast_slice(transforms),
|
||||
usage: wgpu::BufferUsages::STORAGE,
|
||||
});
|
||||
let _ = self.transforms_buffer.insert(transforms_buffer);
|
||||
}
|
||||
|
||||
pub fn set_variations(&mut self, variations: &[Variation]) {
|
||||
let variations_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("variations"),
|
||||
contents: bytemuck::cast_slice(variations),
|
||||
usage: wgpu::BufferUsages::STORAGE,
|
||||
});
|
||||
let variations_buffer = self
|
||||
.device
|
||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("variations"),
|
||||
contents: bytemuck::cast_slice(variations),
|
||||
usage: wgpu::BufferUsages::STORAGE,
|
||||
});
|
||||
let _ = self.variations_buffer.insert(variations_buffer);
|
||||
}
|
||||
|
||||
@ -453,6 +468,13 @@ impl eframe::App for Flare {
|
||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||
egui::menu::bar(ui, |ui| {
|
||||
ui.menu_button("File", |ui| {
|
||||
if ui.button("Debug").clicked() {
|
||||
ui.painter().add(egui_wgpu::Callback::new_paint_callback(
|
||||
Rect::ZERO,
|
||||
DebugIfs,
|
||||
));
|
||||
ui.close_menu();
|
||||
}
|
||||
if ui.button("Quit").clicked() {
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
}
|
||||
@ -477,6 +499,85 @@ impl eframe::App for Flare {
|
||||
}
|
||||
}
|
||||
|
||||
struct DebugIfs;
|
||||
|
||||
impl CallbackTrait for DebugIfs {
|
||||
fn prepare(
|
||||
&self,
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
_screen_descriptor: &ScreenDescriptor,
|
||||
egui_encoder: &mut CommandEncoder,
|
||||
callback_resources: &mut CallbackResources,
|
||||
) -> Vec<CommandBuffer> {
|
||||
let flare_assets = callback_resources
|
||||
.get::<FlareAssets>()
|
||||
.expect("Missing assets");
|
||||
|
||||
let export_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("image_export"),
|
||||
size: flare_assets.render_group.image_accum_buffer.size(),
|
||||
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
let device_extra = device.clone();
|
||||
let width_extra = flare_assets.render_group.accum_constants.width as u32;
|
||||
let height_extra = flare_assets.render_group.accum_constants.height as u32;
|
||||
|
||||
egui_encoder.copy_buffer_to_buffer(
|
||||
&flare_assets.render_group.image_accum_buffer,
|
||||
0,
|
||||
&export_buffer,
|
||||
0,
|
||||
export_buffer.size(),
|
||||
);
|
||||
queue.on_submitted_work_done(move || {
|
||||
let slice = export_buffer.slice(..);
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
|
||||
slice.map_async(wgpu::MapMode::Read, move |result| {
|
||||
if let Ok(result) = result {
|
||||
sender.send(result).unwrap()
|
||||
}
|
||||
});
|
||||
|
||||
device_extra.poll(wgpu::Maintain::Wait);
|
||||
block_on(receiver).expect("Unable to map buffer");
|
||||
|
||||
let result: Vec<f32> = {
|
||||
let data = slice.get_mapped_range();
|
||||
bytemuck::cast_slice(&data).to_vec()
|
||||
};
|
||||
export_buffer.unmap();
|
||||
|
||||
let result_u8: Vec<u8> = result.iter().map(|v| (*v * 256.0) as u8).collect();
|
||||
|
||||
let file = File::create("accum_image.png").expect("Unable to create output image");
|
||||
let png_encoder = PngEncoder::new(file);
|
||||
|
||||
png_encoder
|
||||
.write_image(
|
||||
&result_u8,
|
||||
width_extra,
|
||||
height_extra,
|
||||
ExtendedColorType::Rgba8,
|
||||
)
|
||||
.expect("Unable to write output");
|
||||
});
|
||||
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&self,
|
||||
_info: PaintCallbackInfo,
|
||||
_render_pass: &mut RenderPass<'static>,
|
||||
_callback_resources: &CallbackResources,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
struct PaintIfs {
|
||||
run_accumulate: bool,
|
||||
viewport: egui::Rect,
|
||||
@ -491,11 +592,11 @@ impl CallbackTrait for PaintIfs {
|
||||
egui_encoder: &mut CommandEncoder,
|
||||
callback_resources: &mut CallbackResources,
|
||||
) -> Vec<CommandBuffer> {
|
||||
if self.run_accumulate {
|
||||
let flare_assets = callback_resources
|
||||
.get_mut::<FlareAssets>()
|
||||
.expect("Missing assets");
|
||||
let flare_assets = callback_resources
|
||||
.get_mut::<FlareAssets>()
|
||||
.expect("Missing assets");
|
||||
|
||||
if self.run_accumulate {
|
||||
flare_assets
|
||||
.render_group
|
||||
.set_accum_dimensions(self.viewport.width() as i32, self.viewport.height() as i32);
|
||||
@ -510,8 +611,9 @@ impl CallbackTrait for PaintIfs {
|
||||
pass.dispatch_workgroups(1, 1, 1);
|
||||
}
|
||||
|
||||
let flare_assets = callback_resources.get_mut::<FlareAssets>().expect("Missing assets");
|
||||
flare_assets.render_group.set_viewport_dimensions(self.viewport);
|
||||
flare_assets
|
||||
.render_group
|
||||
.set_viewport_dimensions(self.viewport);
|
||||
|
||||
vec![]
|
||||
}
|
||||
@ -545,6 +647,12 @@ fn main() -> eframe::Result {
|
||||
eframe::run_native(
|
||||
"flare",
|
||||
native_options,
|
||||
Box::new(|cc| Ok(Box::new(Flare::new(cc, initial_dimensions.x as i32, initial_dimensions.y as i32)))),
|
||||
Box::new(|cc| {
|
||||
Ok(Box::new(Flare::new(
|
||||
cc,
|
||||
initial_dimensions.x as i32,
|
||||
initial_dimensions.y as i32,
|
||||
)))
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user