mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
temp
This commit is contained in:
parent
c7a4b93c90
commit
205d798fae
@ -8,6 +8,7 @@ pub mod mesh;
|
|||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod pipelines;
|
pub mod pipelines;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
|
mod screenshot;
|
||||||
pub mod texture;
|
pub mod texture;
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
|
129
voxygen/src/render/pipelines/blit.rs
Normal file
129
voxygen/src/render/pipelines/blit.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
use super::{
|
||||||
|
super::{AaMode, Consts},
|
||||||
|
GlobalsLayouts,
|
||||||
|
};
|
||||||
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
pub struct BindGroup {
|
||||||
|
pub(in super::super) bind_group: wgpu::BindGroup,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BlitLayout {
|
||||||
|
pub layout: wgpu::BindGroupLayout,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlitLayout {
|
||||||
|
pub fn new(device: &wgpu::Device) -> Self {
|
||||||
|
Self {
|
||||||
|
layout: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
label: None,
|
||||||
|
entries: &[
|
||||||
|
// Color source
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
|
multisampled: false,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 1,
|
||||||
|
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Sampler {
|
||||||
|
filtering: true,
|
||||||
|
comparison: false,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind(
|
||||||
|
&self,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
src_color: &wgpu::TextureView,
|
||||||
|
sampler: &wgpu::Sampler,
|
||||||
|
) -> BindGroup {
|
||||||
|
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
label: None,
|
||||||
|
layout: &self.layout,
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: wgpu::BindingResource::TextureView(src_color),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 1,
|
||||||
|
resource: wgpu::BindingResource::Sampler(sampler),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
BindGroup { bind_group }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BlitPipeline {
|
||||||
|
pub pipeline: wgpu::RenderPipeline,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlitPipeline {
|
||||||
|
pub fn new(
|
||||||
|
device: &wgpu::Device,
|
||||||
|
vs_module: &wgpu::ShaderModule,
|
||||||
|
fs_module: &wgpu::ShaderModule,
|
||||||
|
sc_desc: &wgpu::SwapChainDescriptor,
|
||||||
|
layout: &BlitLayout,
|
||||||
|
) -> Self {
|
||||||
|
common::span!(_guard, "BlitPipeline::new");
|
||||||
|
let render_pipeline_layout =
|
||||||
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
label: Some("Blit pipeline layout"),
|
||||||
|
push_constant_ranges: &[],
|
||||||
|
bind_group_layouts: &[&layout.layout],
|
||||||
|
});
|
||||||
|
|
||||||
|
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
|
label: Some("Blit pipeline"),
|
||||||
|
layout: Some(&render_pipeline_layout),
|
||||||
|
vertex: wgpu::VertexState {
|
||||||
|
module: vs_module,
|
||||||
|
entry_point: "main",
|
||||||
|
buffers: &[],
|
||||||
|
},
|
||||||
|
primitive: wgpu::PrimitiveState {
|
||||||
|
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||||
|
strip_index_format: None,
|
||||||
|
front_face: wgpu::FrontFace::Ccw,
|
||||||
|
cull_mode: wgpu::CullMode::None,
|
||||||
|
polygon_mode: wgpu::PolygonMode::Fill,
|
||||||
|
},
|
||||||
|
depth_stencil: None,
|
||||||
|
multisample: wgpu::MultisampleState {
|
||||||
|
count: samples,
|
||||||
|
mask: !0,
|
||||||
|
alpha_to_coverage_enabled: false,
|
||||||
|
},
|
||||||
|
fragment: Some(wgpu::FragmentState {
|
||||||
|
module: fs_module,
|
||||||
|
entry_point: "main",
|
||||||
|
targets: &[wgpu::ColorTargetState {
|
||||||
|
format: sc_desc.format,
|
||||||
|
alpha_blend: wgpu::BlendState::REPLACE,
|
||||||
|
color_blend: wgpu::BlendState::REPLACE,
|
||||||
|
write_mask: wgpu::ColorWrite::ALL,
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
pipeline: render_pipeline,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
pub mod blit;
|
||||||
pub mod clouds;
|
pub mod clouds;
|
||||||
pub mod figure;
|
pub mod figure;
|
||||||
pub mod fluid;
|
pub mod fluid;
|
||||||
|
@ -1038,7 +1038,7 @@ impl Renderer {
|
|||||||
Err(wgpu::SwapChainError::Timeout) => {
|
Err(wgpu::SwapChainError::Timeout) => {
|
||||||
// This will probably be resolved on the next frame
|
// This will probably be resolved on the next frame
|
||||||
// NOTE: we don't log this because it happens very frequently with
|
// NOTE: we don't log this because it happens very frequently with
|
||||||
// PresentMode::Fifo and unlimited FPS
|
// PresentMode::Fifo and unlimited FPS on certain machines
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
},
|
},
|
||||||
Err(err @ wgpu::SwapChainError::Outdated) => {
|
Err(err @ wgpu::SwapChainError::Outdated) => {
|
||||||
|
@ -19,6 +19,8 @@ pub struct Drawer<'a> {
|
|||||||
pub renderer: &'a mut Renderer,
|
pub renderer: &'a mut Renderer,
|
||||||
tex: wgpu::SwapChainTexture,
|
tex: wgpu::SwapChainTexture,
|
||||||
globals: &'a GlobalsBindGroup,
|
globals: &'a GlobalsBindGroup,
|
||||||
|
// Texture to write in screenshot data if that was requested this frame
|
||||||
|
taking_screenshot: Option<super::screenshot::TakingScreenshot>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drawer<'a> {
|
impl<'a> Drawer<'a> {
|
||||||
@ -141,7 +143,9 @@ impl<'a> Drawer<'a> {
|
|||||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
label: Some("third pass (postprocess + ui)"),
|
label: Some("third pass (postprocess + ui)"),
|
||||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
attachment: &self.tex.view,
|
// If a screenshot was requested render to that as an intermediate texture
|
||||||
|
// instead
|
||||||
|
attachment: self.taking_screenshot.map_or(&self.tex.view, |s| &s.tex),
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
||||||
@ -295,6 +299,31 @@ impl<'a> Drawer<'a> {
|
|||||||
|
|
||||||
impl<'a> Drop for Drawer<'a> {
|
impl<'a> Drop for Drawer<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
// If taking a screenshot
|
||||||
|
if let Some(screenshot) = self.taking_screenshot {
|
||||||
|
// Image needs to be copied from the screenshot texture to the swapchain texture
|
||||||
|
let mut render_pass =
|
||||||
|
self.encoder
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: Some(&label),
|
||||||
|
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
|
attachment: &self.tex.view,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
||||||
|
store: true,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
self.render_pass.set_pipeline(&self.blit.pipeline);
|
||||||
|
self.render_pass
|
||||||
|
.set_bind_group(0, &screenshot.bind_group.bind_group, &[]);
|
||||||
|
self.render_pass.draw(0..3, 0..1);
|
||||||
|
drop(render_pass);
|
||||||
|
// TODO: Send screenshot off to another thread here
|
||||||
|
}
|
||||||
// TODO: submitting things to the queue can let the gpu start on them sooner
|
// TODO: submitting things to the queue can let the gpu start on them sooner
|
||||||
// maybe we should submit each render pass to the queue as they are produced?
|
// maybe we should submit each render pass to the queue as they are produced?
|
||||||
self.renderer
|
self.renderer
|
||||||
|
124
voxygen/src/render/renderer/screenshot.rs
Normal file
124
voxygen/src/render/renderer/screenshot.rs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
use super::super::pipelines::blit;
|
||||||
|
|
||||||
|
pub type ScreenshotFn = Box<dyn FnMut(image::DynamicImage) + Send>;
|
||||||
|
|
||||||
|
pub struct ScreenshotDownloader {
|
||||||
|
buffer: wgpu::Buffer,
|
||||||
|
screenshot_fn: ScreenshotFn,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TakeScreenshot {
|
||||||
|
bind_group: blit::BindGroup,
|
||||||
|
view: wgpu::TextureView,
|
||||||
|
texture: wgpu::Texture,
|
||||||
|
// /// Option so that we can pass ownership of the contents of this field around (and eventually to a new thread) without
|
||||||
|
// /// taking ownership of this whole struct
|
||||||
|
downloader: ScreenshotDownloader,
|
||||||
|
// Dimensions used for copying from the screenshot texture to a buffer
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
bytes_per_pixel: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
//pub struct TakingScreenshot<'a> {
|
||||||
|
// pub bind_group: &'a blit::BindGroup,
|
||||||
|
// pub tex: &'a wgpu::TextureView,
|
||||||
|
// downloader: Option<ScreenshotDownloader>
|
||||||
|
//}
|
||||||
|
|
||||||
|
impl TakeScreenshot {
|
||||||
|
pub fn new(
|
||||||
|
device: &wgpu::Device,
|
||||||
|
blit_layout: &blit::BlitLayout,
|
||||||
|
sampler: &wgpu::Sampler,
|
||||||
|
/// Used to determine the resolution and texture format
|
||||||
|
sc_desc: &wgpu::SwapChainDescriptor,
|
||||||
|
/// Function that is given the image after downloading it from the GPU
|
||||||
|
/// This is executed in a background thread
|
||||||
|
screenshot_fn: ScreenshotFn,
|
||||||
|
) -> Self {
|
||||||
|
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: Some("screenshot tex"),
|
||||||
|
size: wgpu::Extent3d {
|
||||||
|
width: sc_desc.width,
|
||||||
|
height: sc_desc.height,
|
||||||
|
depth: 1,
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: sc_desc.format,
|
||||||
|
usage: wgpu::TextureUsage::COPY_SRC
|
||||||
|
| wgpu::TextureUsage::SAMPLED
|
||||||
|
| wgpu::TextureUsage::RENDER_ATTACHEMENT,
|
||||||
|
});
|
||||||
|
|
||||||
|
let view = texture.create_view(&wgpu::TextureViewDescriptor {
|
||||||
|
label: Some("screenshot tex view"),
|
||||||
|
format: Some(sc_desc.format),
|
||||||
|
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||||
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
base_mip_level: 0,
|
||||||
|
level_count: None,
|
||||||
|
base_array_layer: 0,
|
||||||
|
array_layer_count: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let bind_group = blit_layout.bind(device, &taking_tex, sampler);
|
||||||
|
|
||||||
|
let bytes_per_pixel = sc_desc.format.describe().block_size;
|
||||||
|
|
||||||
|
let buffer = device.create_buffer(&wgpu::BufferDescriptor{
|
||||||
|
label: Some("screenshot download buffer"),
|
||||||
|
size: padded_bytes_per_row *
|
||||||
|
}
|
||||||
|
)
|
||||||
|
let downloader = ScreenshotDownloader { screenshot_fn, buffer };
|
||||||
|
|
||||||
|
Self {
|
||||||
|
bind_group,
|
||||||
|
texture,
|
||||||
|
view,
|
||||||
|
downloader: Some(Downloader),
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NOTE: spawns thread
|
||||||
|
/// Call this after rendering to the screenshot texture
|
||||||
|
pub fn download_and_handle(
|
||||||
|
self,
|
||||||
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
) {
|
||||||
|
// Calculate padded bytes per row
|
||||||
|
let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
|
||||||
|
let unpadded_bytes_per_row =
|
||||||
|
// Copy image to a buffer
|
||||||
|
encoder.copy_texture_to_buffer(
|
||||||
|
wgpu::TextureCopyView {
|
||||||
|
texture: &self.texture,
|
||||||
|
mip_level: 0,
|
||||||
|
orgin: wgpu::Origin3d::ZERO,
|
||||||
|
},
|
||||||
|
wgpu::BufferCopyView {
|
||||||
|
buffer: &self.buffer,
|
||||||
|
layout: wgpu::TextureDataLayout {
|
||||||
|
offset: 0,
|
||||||
|
bytes_per_row: padded_bytes_per_row(self.width, self.bytes_per_pixel),
|
||||||
|
rows_per_image: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// Send buffer to another thread for async mapping, downloading, and passing to the given
|
||||||
|
// handler function (which probably saves it to the disk)
|
||||||
|
std::thread::Builder::new().name("screenshot".into()).spawn(|| {
|
||||||
|
|
||||||
|
});
|
||||||
|
.expect("Failed to spawn screenshot thread");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn padded_bytes_per_row(width: u32, bytes_per_pixel: u8) -> u32 {
|
||||||
|
let unpadded_bytes_per_row = width * bytes_per_pixel;
|
||||||
|
let padding = (align - unpadded_bytes_per_row % align) % align;
|
||||||
|
unpadded_bytes_per_row + padding
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user