Make compile through various changes, update wgpu to latest git

This commit is contained in:
Imbris 2020-11-28 00:44:23 -05:00
parent 8c3995298b
commit d9c523ba0d
30 changed files with 412 additions and 293 deletions

View File

@ -98,11 +98,6 @@ incremental = true
inherits = 'release'
debug = 1
[patch.crates-io]
# macos CI fix isn't merged yet
winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" }
vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" }
[workspace.metadata.nix]
systems = ["x86_64-linux"]
@ -113,3 +108,13 @@ key = "veloren-nix.cachix.org-1:zokfKJqVsNV6kI/oJdLF6TYBdNPYGSb+diMVQPn/5Rc="
[workspace.metadata.nix.crateOverride.veloren-network]
buildInputs = ["openssl"]
nativeBuildInputs = ["pkg-config"]
[patch.crates-io]
# macos CI fix isn't merged yet
winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" }
vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" }
# see https://github.com/rustwasm/wasm-bindgen/issues/2371
wasm-bindgen = { git = "https://github.com/rustwasm/wasm-bindgen", rev = "316c5a70fdc4a052fb65ef82bf02d52107b5671b" }
wasm-bindgen-futures = { git = "https://github.com/rustwasm/wasm-bindgen", rev = "316c5a70fdc4a052fb65ef82bf02d52107b5671b" }
web-sys = { git = "https://github.com/rustwasm/wasm-bindgen", rev = "316c5a70fdc4a052fb65ef82bf02d52107b5671b" }
js-sys = { git = "https://github.com/rustwasm/wasm-bindgen", rev = "316c5a70fdc4a052fb65ef82bf02d52107b5671b" }

View File

@ -45,7 +45,7 @@ i18n = {package = "veloren-i18n", path = "i18n"}
# Graphics
winit = {version = "0.24.0", features = ["serde"]}
wgpu = { git="https://github.com/gfx-rs/wgpu-rs.git", rev= "ab8b0e3766558d541206da2790dfd63f15b13bc4" }
wgpu = { git="https://github.com/Imberflur/wgpu-rs.git" }
bytemuck = { version="1.4", features=["derive"] }
shaderc = "0.6.2"

View File

@ -3,44 +3,60 @@ use wgpu::util::DeviceExt;
pub struct Buffer<T: Copy + Pod> {
pub buf: wgpu::Buffer,
// bytes
count: usize,
// Size in number of elements
// TODO: determine if this is a good name
len: usize,
phantom_data: std::marker::PhantomData<T>,
}
impl<T: Copy + Pod> Buffer<T> {
pub fn new(device: &wgpu::Device, cap: u64, usage: wgpu::BufferUsage) -> Self {
Self {
buf: device.create_buffer(&wgpu::BufferDescriptor {
label: None,
mapped_at_creation: false,
size: cap,
usage: usage | wgpu::BufferUsage::MAP_WRITE,
}),
count: 0,
phantom_data: std::marker::PhantomData,
}
}
pub fn new_with_data(device: &wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self {
pub fn new(device: &wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self {
let contents = bytemuck::cast_slice(data);
Self {
buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None,
contents,
usage: usage | wgpu::BufferUsage::MAP_WRITE,
usage,
}),
count: data.len(),
len: data.len(),
phantom_data: std::marker::PhantomData,
}
}
pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) {
if !vals.is_empty() {
queue.write_buffer(&self.buf, offset, bytemuck::cast_slice(vals))
}
pub fn len(&self) -> usize { self.len }
}
pub struct DynamicBuffer<T: Copy + Pod>(Buffer<T>);
impl<T: Copy + Pod> DynamicBuffer<T> {
pub fn new(device: &wgpu::Device, len: usize, usage: wgpu::BufferUsage) -> Self {
let buffer = Buffer {
buf: device.create_buffer(&wgpu::BufferDescriptor {
label: None,
mapped_at_creation: false,
size: (len / std::mem::size_of::<T>()) as u64,
usage: usage | wgpu::BufferUsage::COPY_DST,
}),
len,
phantom_data: std::marker::PhantomData,
};
Self(buffer)
}
pub fn count(&self) -> usize { self.count }
pub fn update(&self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: usize) {
if !vals.is_empty() {
queue.write_buffer(
&self.buf,
(offset / std::mem::size_of::<T>()) as u64,
bytemuck::cast_slice(vals),
)
}
}
}
impl<T: Copy + Pod> std::ops::Deref for DynamicBuffer<T> {
type Target = Buffer<T>;
fn deref(&self) -> &Self::Target { &self.0 }
}

View File

@ -1,23 +1,30 @@
use super::buffer::Buffer;
use super::buffer::DynamicBuffer;
use bytemuck::Pod;
/// A handle to a series of constants sitting on the GPU. This is used to hold
/// information used in the rendering process that does not change throughout a
/// single render pass.
pub struct Consts<T: Copy + Pod> {
buf: Buffer<T>,
buf: DynamicBuffer<T>,
}
impl<T: Copy + Pod> Consts<T> {
/// Create a new `Const<T>`.
pub fn new(device: &wgpu::Device, len: u64) -> Self {
pub fn new(device: &wgpu::Device, len: usize) -> Self {
Self {
buf: Buffer::new(device, len, wgpu::BufferUsage::UNIFORM),
// TODO: examine if all our consts need to be updateable
buf: DynamicBuffer::new(device, len, wgpu::BufferUsage::UNIFORM),
}
}
/// Update the GPU-side value represented by this constant handle.
pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) {
pub fn update(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
vals: &[T],
offset: usize,
) {
self.buf.update(device, queue, vals, offset)
}

View File

@ -1,6 +1,5 @@
/// Used to represent one of many possible errors that may be omitted by the
/// rendering subsystem.
#[derive(Debug)]
pub enum RenderError {
RequestDeviceError(wgpu::RequestDeviceError),
MappingError(wgpu::BufferAsyncError),
@ -11,6 +10,23 @@ pub enum RenderError {
ShaderError(shaderc::Error),
}
use std::fmt;
impl fmt::Debug for RenderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::RequestDeviceError(err) => {
f.debug_tuple("RequestDeviceError").field(err).finish()
},
Self::MappingError(err) => f.debug_tuple("MappingError").field(err).finish(),
Self::SwapChainError(err) => f.debug_tuple("SwapChainError").field(err).finish(),
Self::CustomError(err) => f.debug_tuple("CustomError").field(err).finish(),
Self::CouldNotFindAdapter => f.debug_tuple("CouldNotFindAdapter").finish(),
Self::ErrorInitializingCompiler => f.debug_tuple("ErrorInitializingCompiler").finish(),
Self::ShaderError(err) => write!(f, "{}", err),
}
}
}
impl From<wgpu::RequestDeviceError> for RenderError {
fn from(err: wgpu::RequestDeviceError) -> Self { Self::RequestDeviceError(err) }
}

View File

@ -1,21 +1,30 @@
use super::buffer::Buffer;
use super::buffer::DynamicBuffer;
use bytemuck::Pod;
/// Represents a mesh that has been sent to the GPU.
pub struct Instances<T: Copy + Pod> {
buf: Buffer<T>,
buf: DynamicBuffer<T>,
}
impl<T: Copy + Pod> Instances<T> {
pub fn new(device: &wgpu::Device, len: u64) -> Self {
pub fn new(device: &wgpu::Device, len: usize) -> Self {
Self {
buf: Buffer::new(device, len, wgpu::BufferUsage::VERTEX),
// TODO: examine if we have Intances that are not updated and if there would be any
// gains from separating those out
buf: DynamicBuffer::new(device, len, wgpu::BufferUsage::VERTEX),
}
}
pub fn count(&self) -> usize { self.buf.count() }
// TODO: count vs len naming scheme??
pub fn count(&self) -> usize { self.buf.len() }
pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) {
pub fn update(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
vals: &[T],
offset: usize,
) {
self.buf.update(device, queue, vals, offset)
}

View File

@ -15,7 +15,7 @@ pub use self::{
error::RenderError,
instances::Instances,
mesh::{Mesh, Quad, Tri},
model::{Model, SubModel},
model::{DynamicModel, Model, SubModel},
pipelines::{
clouds::{create_mesh as create_clouds_mesh, Locals as CloudsLocals},
figure::{

View File

@ -1,4 +1,8 @@
use super::{buffer::Buffer, mesh::Mesh, Vertex};
use super::{
buffer::{Buffer, DynamicBuffer},
mesh::Mesh,
Vertex,
};
use std::ops::Range;
/// Represents a mesh that has been sent to the GPU.
@ -20,13 +24,7 @@ pub struct Model<V: Vertex> {
impl<V: Vertex> Model<V> {
pub fn new(device: &wgpu::Device, mesh: &Mesh<V>) -> Self {
Self {
vbuf: Buffer::new_with_data(device, wgpu::BufferUsage::VERTEX, mesh.vertices()),
}
}
pub fn new_dynamic(device: &wgpu::Device, size: u64) -> Self {
Self {
vbuf: Buffer::new(device, size, wgpu::BufferUsage::VERTEX),
vbuf: Buffer::new(device, wgpu::BufferUsage::VERTEX, mesh.vertices()),
}
}
@ -40,15 +38,44 @@ impl<V: Vertex> Model<V> {
}
}
pub fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf }
pub fn len(&self) -> usize { self.vbuf.len() }
}
/// Represents a mesh that has been sent to the GPU.
pub struct DynamicModel<V: Vertex> {
vbuf: DynamicBuffer<V>,
}
impl<V: Vertex> DynamicModel<V> {
pub fn new(device: &wgpu::Device, size: usize) -> Self {
Self {
vbuf: DynamicBuffer::new(device, size, wgpu::BufferUsage::VERTEX),
}
}
pub fn update(
&mut self,
&self,
device: &wgpu::Device,
queue: &wgpu::Queue,
mesh: &Mesh<V>,
offset: u64,
offset: usize,
) {
self.vbuf.update(device, queue, mesh.vertices(), offset)
}
/// Create a model with a slice of a portion of this model to send to the
/// renderer.
pub fn submodel(&self, vertex_range: Range<u32>) -> SubModel<V> {
SubModel {
vertex_range,
buf: self.buf(),
phantom_data: std::marker::PhantomData,
}
}
pub fn buf(&self) -> &wgpu::Buffer { &self.vbuf.buf }
pub fn len(&self) -> usize { self.vbuf.len() }
}

View File

@ -209,6 +209,7 @@ impl FigurePipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -33,14 +33,12 @@ impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] =
wgpu::vertex_attr_array![0 => Uint];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &[wgpu::VertexAttributeDescriptor {
offset: 0,
shader_location: 0,
format: wgpu::VertexFormat::Uint,
}],
attributes: &ATTRIBUTES,
}
}
}
@ -121,6 +119,7 @@ impl FluidPipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::None,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -17,14 +17,12 @@ impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] =
wgpu::vertex_attr_array![0 => Float2];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &[wgpu::VertexAttributeDescriptor {
offset: 0,
shader_location: 0,
format: wgpu::VertexFormat::Float2,
}],
attributes: &ATTRIBUTES,
}
}
}
@ -87,7 +85,6 @@ impl LodData {
&texture_info,
&view_info,
&sampler_info,
map_size.x * 4,
bytemuck::cast_slice(lod_base),
);
texture_info.format = wgpu::TextureFormat::Rg16Uint;
@ -96,7 +93,6 @@ impl LodData {
&texture_info,
&view_info,
&sampler_info,
map_size.x * 4,
bytemuck::cast_slice(lod_base),
);
texture_info.format = wgpu::TextureFormat::Rgba8Unorm;
@ -105,7 +101,6 @@ impl LodData {
&texture_info,
&view_info,
&sampler_info,
map_size.x * 4,
bytemuck::cast_slice(lod_base),
);
@ -198,6 +193,7 @@ impl LodTerrainPipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -33,10 +33,12 @@ impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 2] =
wgpu::vertex_attr_array![0 => Float3, 1 => Uint];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Float3, 1 => Uint],
attributes: &ATTRIBUTES,
}
}
}
@ -150,10 +152,12 @@ impl Instance {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 5] =
wgpu::vertex_attr_array![0 => Float, 1 => Float, 2 => Float, 3 => Int, 4 => Float3];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Instance,
attributes: &wgpu::vertex_attr_array![0 => Float, 1 => Float, 2 => Float, 3 => Int, 4 => Float3],
attributes: &ATTRIBUTES,
}
}
}
@ -205,6 +209,7 @@ impl ParticlePipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -31,14 +31,12 @@ pub struct Vertex {
impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] =
wgpu::vertex_attr_array![0 => Float2];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &[wgpu::VertexAttributeDescriptor {
offset: 0,
shader_location: 0,
format: wgpu::VertexFormat::Float2,
}],
attributes: &ATTRIBUTES,
}
}
}
@ -139,6 +137,7 @@ impl PostProcessPipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -95,7 +95,6 @@ pub fn create_col_lights(
&texture_info,
&view_info,
&sampler_info,
col_lights_size.x * 4,
bytemuck::cast_slice(&col_lights),
)
}
@ -149,6 +148,7 @@ impl ShadowFigurePipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
@ -231,6 +231,7 @@ impl ShadowPipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -65,6 +65,7 @@ impl SkyboxPipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
@ -103,6 +104,7 @@ impl SkyboxPipeline {
}
}
// TODO: generate mesh in vertex shader
pub fn create_mesh() -> Mesh<Vertex> {
let mut mesh = Mesh::new();

View File

@ -61,10 +61,12 @@ impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 3] =
wgpu::vertex_attr_array![0 => Float3, 1 => Uint, 2 => Uint];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Float3, 1 => Uint, 2 => Uint],
attributes: &ATTRIBUTES,
}
}
}
@ -109,10 +111,11 @@ impl Instance {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 6] = wgpu::vertex_attr_array![0 => Uint, 1 => Float4,2 => Float4, 3 => Float4,4 => Float4, 5 => Float];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Instance,
attributes: &wgpu::vertex_attr_array![0 => Uint, 1 => Float4,2 => Float4, 3 => Float4,4 => Float4,5 => Float],
attributes: &ATTRIBUTES,
}
}
}
@ -253,6 +256,7 @@ impl SpritePipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -120,20 +120,23 @@ impl Vertex {
pub fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 2] =
wgpu::vertex_attr_array![0 => Uint,1 => Uint];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Uint,1 => Uint],
attributes: &ATTRIBUTES,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
// TODO: new function and private fields??
pub struct Locals {
model_offs: [f32; 3],
load_time: f32,
atlas_offs: [i32; 4],
pub model_offs: [f32; 3],
pub load_time: f32,
pub atlas_offs: [i32; 4],
}
impl Locals {
@ -233,6 +236,7 @@ impl TerrainPipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -15,10 +15,12 @@ pub struct Vertex {
impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 5] =
wgpu::vertex_attr_array![0 => Float2, 1 => Float2, 2 => Float4, 3 => Float2, 4 => Uint];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Float2, 1 => Float2, 2 => Float4, 3 => Float2, 4 => Uint],
attributes: &ATTRIBUTES,
}
}
}
@ -165,6 +167,7 @@ impl UIPipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,

View File

@ -2,7 +2,7 @@ use super::{
consts::Consts,
instances::Instances,
mesh::Mesh,
model::Model,
model::{DynamicModel, Model},
pipelines::{
clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain,
ui, GlobalsLayouts,
@ -177,9 +177,9 @@ pub struct Layouts {
/// rendering subsystem and contains any state necessary to interact with the
/// GPU, along with pipeline state objects (PSOs) needed to renderer different
/// kinds of models to the screen.
pub struct Renderer<'a> {
window: &'a winit::window::Window,
pub struct Renderer {
// TODO: why????
//window: &'a winit::window::Window,
device: wgpu::Device,
queue: wgpu::Queue,
swap_chain: wgpu::SwapChain,
@ -216,12 +216,14 @@ pub struct Renderer<'a> {
noise_tex: Texture,
mode: RenderMode,
resolution: Vec2<u32>,
}
impl<'a> Renderer<'a> {
impl Renderer {
/// Create a new `Renderer` from a variety of backend-specific components
/// and the window targets.
pub fn new(window: &'a winit::window::Window, mode: RenderMode) -> Result<Self, RenderError> {
pub fn new(window: &winit::window::Window, mode: RenderMode) -> Result<Self, RenderError> {
// Enable seamless cubemaps globally, where available--they are essentially a
// strict improvement on regular cube maps.
//
@ -231,7 +233,9 @@ impl<'a> Renderer<'a> {
let dims = window.inner_size();
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY | wgpu::BackendBit::SECONDARY);
let instance = wgpu::Instance::new(
wgpu::BackendBit::PRIMARY, /* | wgpu::BackendBit::SECONDARY */
);
// This is unsafe because the window handle must be valid, if you find a way to
// have an invalid winit::Window then you have bigger issues
@ -251,6 +255,7 @@ impl<'a> Renderer<'a> {
let (device, queue) = futures::executor::block_on(adapter.request_device(
&wgpu::DeviceDescriptor {
// TODO
label: None,
features: Features::DEPTH_CLAMPING | Features::ADDRESS_MODE_CLAMP_TO_BORDER,
limits: Limits::default(),
shader_validation: true,
@ -269,7 +274,7 @@ impl<'a> Renderer<'a> {
);
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
width: dims.width,
height: dims.height,
@ -387,8 +392,6 @@ impl<'a> Renderer<'a> {
)?;
Ok(Self {
window,
device,
queue,
swap_chain,
@ -423,6 +426,8 @@ impl<'a> Renderer<'a> {
noise_tex,
mode,
resolution: Vec2::new(dims.width, dims.height),
})
}
@ -443,7 +448,7 @@ impl<'a> Renderer<'a> {
self.mode = mode;
// Recreate render target
self.on_resize()?;
self.on_resize(self.resolution)?;
// Recreate pipelines with the new AA mode
self.recreate_pipelines();
@ -455,13 +460,11 @@ impl<'a> Renderer<'a> {
pub fn render_mode(&self) -> &RenderMode { &self.mode }
/// Resize internal render targets to match window render target dimensions.
pub fn on_resize(&mut self) -> Result<(), RenderError> {
let dims = self.window.inner_size();
pub fn on_resize(&mut self, dims: Vec2<u32>) -> Result<(), RenderError> {
// Avoid panics when creating texture with w,h of 0,0.
if dims.width != 0 && dims.height != 0 {
if dims.x != 0 && dims.y != 0 {
let (tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view) =
Self::create_rt_views(&mut self.device, (dims.width, dims.height), &self.mode)?;
Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?;
self.win_depth_view = win_depth_view;
self.tgt_color_view = tgt_color_view;
self.tgt_depth_stencil_view = tgt_depth_stencil_view;
@ -469,8 +472,7 @@ impl<'a> Renderer<'a> {
if let (Some(shadow_map), ShadowMode::Map(mode)) =
(self.shadow_map.as_mut(), self.mode.shadow)
{
match Self::create_shadow_views(&mut self.device, (dims.width, dims.height), &mode)
{
match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) {
Ok((point_depth_stencil, directed_depth_stencil)) => {
shadow_map.point_depth_stencil = point_depth_stencil;
shadow_map.directed_depth_stencil = directed_depth_stencil;
@ -480,6 +482,8 @@ impl<'a> Renderer<'a> {
},
}
}
self.resolution = dims;
}
Ok(())
@ -523,7 +527,7 @@ impl<'a> Renderer<'a> {
sample_count,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT,
});
tex.create_view(&wgpu::TextureViewDescriptor {
@ -553,7 +557,7 @@ impl<'a> Renderer<'a> {
sample_count,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Depth24Plus,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT,
});
let tgt_depth_stencil_view =
tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor {
@ -578,7 +582,7 @@ impl<'a> Renderer<'a> {
sample_count,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Depth24Plus,
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
});
let win_depth_view = tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor {
label: None,
@ -667,7 +671,19 @@ impl<'a> Renderer<'a> {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Depth24Plus,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT,
};
//TODO: (0, levels - 1), ?? from master
let mut point_shadow_view = wgpu::TextureViewDescriptor {
label: None,
format: Some(wgpu::TextureFormat::Depth24Plus),
dimension: Some(wgpu::TextureViewDimension::Cube),
aspect: wgpu::TextureAspect::DepthOnly,
base_mip_level: 0,
level_count: None,
base_array_layer: 0,
array_layer_count: None,
};
let directed_shadow_tex = wgpu::TextureDescriptor {
@ -681,10 +697,10 @@ impl<'a> Renderer<'a> {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Depth24Plus,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT,
};
let mut view_info = wgpu::TextureViewDescriptor {
let directed_shadow_view = wgpu::TextureViewDescriptor {
label: None,
format: Some(wgpu::TextureFormat::Depth24Plus),
dimension: Some(wgpu::TextureViewDimension::D2),
@ -707,30 +723,27 @@ impl<'a> Renderer<'a> {
..Default::default()
};
let point_tgt_shadow =
Texture::new_raw(device, &point_shadow_tex, &view_info, &sampler_info);
view_info.dimension = Some(wgpu::TextureViewDimension::Cube);
let directed_shadow_tex =
Texture::new_raw(device, &directed_shadow_tex, &view_info, &sampler_info);
let point_shadow_tex =
Texture::new_raw(device, &point_shadow_tex, &point_shadow_view, &sampler_info);
let directed_shadow_tex = Texture::new_raw(
device,
&directed_shadow_tex,
&directed_shadow_view,
&sampler_info,
);
Ok((point_tgt_shadow, directed_shadow_tex))
Ok((point_shadow_tex, directed_shadow_tex))
}
/// Get the resolution of the render target.
pub fn get_resolution(&self) -> Vec2<u32> {
let dims = self.window.inner_size();
Vec2::new(dims.width, dims.height)
}
pub fn resolution(&self) -> Vec2<u32> { self.resolution }
/// Get the resolution of the shadow render target.
pub fn get_shadow_resolution(&self) -> (Vec2<u32>, Vec2<u32>) {
if let Some(shadow_map) = &self.shadow_map {
let point_dims = shadow_map.point_depth_stencil.get_dimensions();
let directed_dims = shadow_map.directed_depth_stencil.get_dimensions();
(
Vec2::new(point_dims.width, point_dims.height),
Vec2::new(directed_dims.width, directed_dims.height),
shadow_map.point_depth_stencil.get_dimensions().xy(),
shadow_map.directed_depth_stencil.get_dimensions().xy(),
)
} else {
(Vec2::new(1, 1), Vec2::new(1, 1))
@ -882,7 +895,7 @@ impl<'a> Renderer<'a> {
&mut self,
vals: &[T],
) -> Result<Consts<T>, RenderError> {
let mut consts = Consts::new(&self.device, vals.len() as u64);
let mut consts = Consts::new(&self.device, vals.len());
consts.update(&self.device, &self.queue, vals, 0);
Ok(consts)
}
@ -897,7 +910,7 @@ impl<'a> Renderer<'a> {
&mut self,
vals: &[T],
) -> Result<Instances<T>, RenderError> {
let mut instances = Instances::new(&self.device, vals.len() as u64);
let mut instances = Instances::new(&self.device, vals.len());
instances.update(&self.device, &self.queue, vals, 0);
Ok(instances)
}
@ -908,12 +921,12 @@ impl<'a> Renderer<'a> {
}
/// Create a new dynamic model with the specified size.
pub fn create_dynamic_model<V: Vertex>(&mut self, size: u64) -> Model<V> {
Model::new_dynamic(&self.device, size)
pub fn create_dynamic_model<V: Vertex>(&mut self, size: usize) -> DynamicModel<V> {
DynamicModel::new(&self.device, size)
}
/// Update a dynamic model with a mesh and a offset.
pub fn update_model<V: Vertex>(&mut self, model: &Model<V>, mesh: &Mesh<V>, offset: u64) {
pub fn update_model<V: Vertex>(&self, model: &DynamicModel<V>, mesh: &Mesh<V>, offset: usize) {
model.update(&self.device, &self.queue, mesh, offset)
}
@ -933,7 +946,6 @@ impl<'a> Renderer<'a> {
texture_info: &wgpu::TextureDescriptor,
view_info: &wgpu::TextureViewDescriptor,
sampler_info: &wgpu::SamplerDescriptor,
bytes_per_row: u32,
data: &[u8],
) -> Texture {
let tex = Texture::new_raw(&self.device, &texture_info, &view_info, &sampler_info);
@ -944,7 +956,6 @@ impl<'a> Renderer<'a> {
[0; 2],
[texture_info.size.width, texture_info.size.height],
data,
bytes_per_row,
);
tex
@ -1004,7 +1015,6 @@ impl<'a> Renderer<'a> {
// Copy, {
// texture.update(&mut self.encoder, offset, size, data)
data: &[[u8; 4]],
bytes_per_row: u32,
) {
texture.update(
&self.device,
@ -1012,7 +1022,6 @@ impl<'a> Renderer<'a> {
offset,
size,
bytemuck::cast_slice(data),
bytes_per_row,
)
}
@ -1882,16 +1891,16 @@ fn create_pipelines(
Ok(ResolvedInclude {
resolved_name: name.to_string(),
content: match name {
"constants.glsl" => constants,
"globals.glsl" => *globals,
"shadows.glsl" => *shadows,
"sky.glsl" => *sky,
"light.glsl" => *light,
"srgb.glsl" => *srgb,
"random.glsl" => *random,
"lod.glsl" => *lod,
"anti-aliasing.glsl" => *anti_alias,
"cloud.glsl" => *cloud,
"constants.glsl" => constants.clone(),
"globals.glsl" => globals.as_ref().clone(),
"shadows.glsl" => shadows.as_ref().clone(),
"sky.glsl" => sky.as_ref().clone(),
"light.glsl" => light.as_ref().clone(),
"srgb.glsl" => srgb.as_ref().clone(),
"random.glsl" => random.as_ref().clone(),
"lod.glsl" => lod.as_ref().clone(),
"anti-aliasing.glsl" => anti_alias.as_ref().clone(),
"cloud.glsl" => cloud.as_ref().clone(),
other => return Err(format!("Include {} is not defined", other)),
},
})
@ -2298,7 +2307,7 @@ fn create_pipelines(
))
}
pub fn create_shader_module(
fn create_shader_module(
device: &wgpu::Device,
compiler: &mut shaderc::Compiler,
source: &str,

View File

@ -18,7 +18,7 @@ impl Texture {
filter_method: Option<wgpu::FilterMode>,
address_mode: Option<wgpu::AddressMode>,
) -> Result<Self, RenderError> {
// TODO: Actualy handle images that aren't in rgba format properly.
// TODO: Actually handle images that aren't in rgba format properly.
let buffer = image.as_flat_samples_u8().ok_or_else(|| {
RenderError::CustomError(
"We currently do not support color formats using more than 4 bytes / pixel.".into(),
@ -38,7 +38,7 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
});
let mut command_encoder =
@ -107,7 +107,8 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED,
// TODO: nondynamic version doesn't seeem to have different usage, unify code?
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
};
let sampler_info = wgpu::SamplerDescriptor {
@ -161,8 +162,10 @@ impl Texture {
offset: [u32; 2],
size: [u32; 2],
data: &[u8],
bytes_per_row: u32,
) {
// Note: we only accept 4 bytes per pixel
// (enforce this is API?)
debug_assert_eq!(data.len(), size[0] as usize * size[1] as usize * 4);
// TODO: Only works for 2D images
queue.write_texture(
wgpu::TextureCopyViewBase {
@ -177,8 +180,8 @@ impl Texture {
data,
wgpu::TextureDataLayout {
offset: 0,
bytes_per_row,
rows_per_image: self.size.height,
bytes_per_row: size[0] * 4,
rows_per_image: size[1],
},
wgpu::Extent3d {
width: size[0],
@ -189,5 +192,7 @@ impl Texture {
}
/// Get dimensions of the represented image.
pub fn get_dimensions(&self) -> Extent3d { self.size }
pub fn get_dimensions(&self) -> vek::Vec3<u32> {
vek::Vec3::new(self.size.width, self.size.height, self.size.depth)
}
}

View File

@ -8,7 +8,7 @@ use crate::{
ecs::comp::Interpolated,
render::{
pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel,
Mesh, RenderError, Renderer, TerrainVertex, Texture,
Mesh, RenderError, Renderer, SubModel, TerrainVertex, Texture,
},
scene::{
camera::{Camera, CameraMode, Dependents},
@ -63,7 +63,7 @@ pub type CameraData<'a> = (&'a Camera, f32);
pub type FigureModelRef<'a> = (
&'a Consts<FigureLocals>,
&'a Consts<FigureBoneData>,
&'a FigureModel,
SubModel<'a, TerrainVertex>,
&'a Texture, /* <ColLightFmt> */
);
@ -81,9 +81,19 @@ pub struct FigureModelEntry<const N: usize> {
/* TODO: Consider using mipmaps instead of storing multiple texture atlases for different
* LOD levels. */
col_lights: Texture, /* <ColLightFmt> */
/// Models stored in this figure entry; there may be several for one figure,
/// because of LOD models.
pub models: [FigureModel; N],
/// Vertex ranges stored in this figure entry; there may be several for one
/// figure, because of LOD models.
lod_vertex_ranges: [Range<u32>; N],
model: FigureModel,
}
impl<const N: usize> FigureModelEntry<N> {
pub fn lod_model(&self, lod: usize) -> SubModel<TerrainVertex> {
// Note: Range doesn't impl Copy even for trivially Cloneable things
self.model
.opaque
.submodel(self.lod_vertex_ranges[lod].clone())
}
}
struct FigureMgrStates {
@ -4734,13 +4744,14 @@ impl FigureMgr {
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|state| state.can_shadow_sun(),
) {
renderer.render_figure_shadow_directed(
model,
global,
locals,
bone_consts,
&global.shadow_mats,
);
// TODO
//renderer.render_figure_shadow_directed(
// model,
// global,
// locals,
// bone_consts,
// &global.shadow_mats,
//);
}
});
}
@ -4791,7 +4802,8 @@ impl FigureMgr {
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|state| state.visible(),
) {
renderer.render_figure(model, &col_lights, global, locals, bone_consts, lod);
// renderer.render_figure(model, &col_lights, global,
// locals, bone_consts, lod);
}
}
}
@ -4839,15 +4851,16 @@ impl FigureMgr {
figure_lod_render_distance,
|state| state.visible(),
) {
renderer.render_player(model, &col_lights, global, locals, bone_consts, lod);
renderer.render_player_shadow(
//renderer.render_player(model, &col_lights, global, locals,
// bone_consts, lod);
/*renderer.render_player_shadow(
model,
&col_lights,
global,
bone_consts,
lod,
&global.shadow_mats,
);
);*/
}
}
}
@ -5175,11 +5188,11 @@ impl FigureMgr {
let figure_mid_detail_distance = figure_lod_render_distance * 0.5;
let model = if pos.distance_squared(cam_pos) > figure_low_detail_distance.powi(2) {
&model_entry.models[2]
model_entry.lod_model(2)
} else if pos.distance_squared(cam_pos) > figure_mid_detail_distance.powi(2) {
&model_entry.models[1]
model_entry.lod_model(1)
} else {
&model_entry.models[0]
model_entry.lod_model(0)
};
Some((locals, bone_consts, model, col_lights_.texture(model_entry)))
@ -5225,7 +5238,7 @@ impl FigureColLights {
renderer: &mut Renderer,
(tex, tex_size): ColLightInfo,
(opaque, bounds): (Mesh<TerrainVertex>, math::Aabb<f32>),
vertex_range: [Range<u32>; N],
vertex_ranges: [Range<u32>; N],
) -> Result<FigureModelEntry<N>, RenderError> {
span!(_guard, "create_figure", "FigureColLights::create_figure");
let atlas = &mut self.atlas;
@ -5237,22 +5250,22 @@ impl FigureColLights {
.expect("The model size for this figure does not fit in a u32!");
let model = renderer.create_model(&opaque)?;
vertex_ranges.iter().for_each(|range| {
assert!(
range.start <= range.end && range.end <= model_len,
"The provided vertex range for figure mesh {:?} does not fit in the model, which \
is of size {:?}!",
range,
model_len
);
});
Ok(FigureModelEntry {
_bounds: bounds,
models: vertex_range.map(|range| {
assert!(
range.start <= range.end && range.end <= model_len,
"The provided vertex range for figure mesh {:?} does not fit in the model, \
which is of size {:?}!",
range,
model_len
);
FigureModel {
opaque: model.submodel(range),
}
}),
col_lights,
allocation,
col_lights,
lod_vertex_ranges: vertex_ranges,
model: FigureModel { opaque: model },
})
}

View File

@ -61,7 +61,8 @@ impl Lod {
pub fn render(&self, renderer: &mut Renderer, global: &GlobalModel) {
if let Some((_, model)) = self.model.as_ref() {
renderer.render_lod_terrain(&model, global, &self.locals, &self.data);
//renderer.render_lod_terrain(&model, global, &self.locals,
// &self.data);
}
}
}

View File

@ -271,7 +271,7 @@ impl Scene {
client: &Client,
settings: &Settings,
) -> Self {
let resolution = renderer.get_resolution().map(|e| e as f32);
let resolution = renderer.resolution().map(|e| e as f32);
let sprite_render_context = lazy_init(renderer);
Self {
@ -642,7 +642,7 @@ impl Scene {
self.map_bounds,
time_of_day,
scene_data.state.get_time(),
renderer.get_resolution().as_(),
renderer.resolution().as_(),
Vec2::new(SHADOW_NEAR, SHADOW_FAR),
lights.len(),
shadows.len(),
@ -1061,7 +1061,7 @@ impl Scene {
self.lod.render(renderer, global);
// Render the skybox.
renderer.render_skybox(&self.skybox.model, global, &self.skybox.locals, lod);
// TODO: renderer.render_skybox(&self.skybox.model, global, lod);
self.terrain.render_translucent(
renderer,
@ -1075,19 +1075,20 @@ impl Scene {
// Render particle effects.
self.particle_mgr.render(renderer, scene_data, global, lod);
// Render clouds (a post-processing effect)
renderer.render_clouds(
&self.clouds.model,
&global.globals,
&self.clouds.locals,
self.lod.get_data(),
);
// TODO:
// // Render clouds (a post-processing effect)
// renderer.render_clouds(
// &self.clouds.model,
// &global.globals,
// &self.clouds.locals,
// self.lod.get_data(),
// );
renderer.render_post_process(
&self.postprocess.model,
&global.globals,
&self.postprocess.locals,
self.lod.get_data(),
);
// renderer.render_post_process(
// &self.postprocess.model,
// &global.globals,
// &self.postprocess.locals,
// self.lod.get_data(),
// );
}
}

View File

@ -1192,7 +1192,8 @@ impl ParticleMgr {
.get(DEFAULT_MODEL_KEY)
.expect("Expected particle model in cache");
renderer.render_particles(model, global, &self.instances, lod);
/* renderer.render_particles(model, global, &self.instances,
* lod); */
}
}

View File

@ -30,7 +30,6 @@ use common::{
terrain::BlockKind,
vol::{BaseVol, ReadVol},
};
use tracing::error;
use vek::*;
use winit::event::MouseButton;
@ -104,7 +103,7 @@ pub struct SceneData<'a> {
impl Scene {
pub fn new(renderer: &mut Renderer, backdrop: Option<&str>, client: &Client) -> Self {
let start_angle = 90.0f32.to_radians();
let resolution = renderer.get_resolution().map(|e| e as f32);
let resolution = renderer.resolution().map(|e| e as f32);
let map_bounds = Vec2::new(
client.world_data().min_chunk_alt(),
@ -278,7 +277,7 @@ impl Scene {
self.map_bounds,
TIME,
scene_data.time,
renderer.get_resolution().as_(),
renderer.resolution().as_(),
Vec2::new(SHADOW_NEAR, SHADOW_FAR),
0,
0,
@ -380,12 +379,12 @@ impl Scene {
body: Option<humanoid::Body>,
inventory: Option<&Inventory>,
) {
renderer.render_skybox(
/*renderer.render_skybox(
&self.skybox.model,
&self.data,
&self.skybox.locals,
&self.lod,
);
);*/
if let Some(body) = body {
let model = &self.figure_model_cache.get_model(
@ -398,40 +397,40 @@ impl Scene {
);
if let Some(model) = model {
renderer.render_figure(
&model.models[0],
&self.col_lights.texture(model),
&self.data,
self.figure_state.locals(),
self.figure_state.bone_consts(),
&self.lod,
);
// renderer.render_figure(
// &model.models[0],
// &self.col_lights.texture(model),
// &self.data,
// self.figure_state.locals(),
// self.figure_state.bone_consts(),
// &self.lod,
// );
}
}
if let Some((model, state)) = &self.backdrop {
renderer.render_figure(
/*renderer.render_figure(
&model.models[0],
&self.col_lights.texture(model),
&self.data,
state.locals(),
state.bone_consts(),
&self.lod,
);
);*/
}
renderer.render_clouds(
&self.clouds.model,
&self.data.globals,
&self.clouds.locals,
&self.lod,
);
// renderer.render_clouds(
// &self.clouds.model,
// &self.data.globals,
// &self.clouds.locals,
// &self.lod,
// );
renderer.render_post_process(
&self.postprocess.model,
&self.data.globals,
&self.postprocess.locals,
&self.lod,
);
// renderer.render_post_process(
// &self.postprocess.model,
// &self.data.globals,
// &self.postprocess.locals,
// &self.lod,
// );
}
}

View File

@ -1429,12 +1429,12 @@ impl<V: RectRasterableVol> Terrain<V> {
.chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk))
.for_each(|chunk| {
// Directed light shadows.
renderer.render_terrain_shadow_directed(
/*renderer.render_terrain_shadow_directed(
&chunk.opaque_model,
global,
&chunk.locals,
&global.shadow_mats,
);
);*/
});
}
@ -1445,12 +1445,12 @@ impl<V: RectRasterableVol> Terrain<V> {
light_data.iter().take(1).for_each(|_light| {
chunk_iter.clone().for_each(|chunk| {
if chunk.can_shadow_point {
renderer.render_shadow_point(
/*renderer.render_shadow_point(
&chunk.opaque_model,
global,
&chunk.locals,
&global.shadow_mats,
);
);*/
}
});
});
@ -1477,13 +1477,13 @@ impl<V: RectRasterableVol> Terrain<V> {
for (_, chunk) in chunk_iter {
if chunk.visible.is_visible() {
renderer.render_terrain_chunk(
/* renderer.render_terrain_chunk(
&chunk.opaque_model,
&chunk.texture,
global,
&chunk.locals,
lod,
);
);*/
}
}
}
@ -1558,7 +1558,7 @@ impl<V: RectRasterableVol> Terrain<V> {
} else {
&self.sprite_data[&kind][4]
};
renderer.render_sprites(
/*renderer.render_sprites(
model,
&self.sprite_col_lights,
global,
@ -1566,7 +1566,7 @@ impl<V: RectRasterableVol> Terrain<V> {
locals,
&instances,
lod,
);
);*/
}
}
}
@ -1587,13 +1587,13 @@ impl<V: RectRasterableVol> Terrain<V> {
.into_iter()
.rev() // Render back-to-front
.for_each(|(model, locals)| {
renderer.render_fluid_chunk(
/*renderer.render_fluid_chunk(
model,
global,
locals,
lod,
&self.waves,
)
)*/
});
}
}

View File

@ -8,7 +8,7 @@ use hashbrown::HashMap;
use vek::*;
// Multiplied by current window size
const GLYPH_CACHE_SIZE: u16 = 1;
const GLYPH_CACHE_SIZE: u32 = 1;
// Glyph cache tolerances
const SCALE_TOLERANCE: f32 = 0.5;
const POSITION_TOLERANCE: f32 = 0.5;
@ -26,7 +26,7 @@ pub struct Cache {
// TODO: Should functions be returning UiError instead of Error?
impl Cache {
pub fn new(renderer: &mut Renderer) -> Result<Self, Error> {
let (w, h) = renderer.get_resolution().into_tuple();
let (w, h) = renderer.resolution().into_tuple();
let max_texture_size = renderer.max_texture_size();
@ -36,11 +36,11 @@ impl Cache {
Ok(Self {
text_cache: Default::default(),
glyph_cache: GlyphCache::builder()
.dimensions(glyph_cache_dims.x as u32, glyph_cache_dims.y as u32)
.dimensions(glyph_cache_dims.x, glyph_cache_dims.y)
.scale_tolerance(SCALE_TOLERANCE)
.position_tolerance(POSITION_TOLERANCE)
.build(),
glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims.map(|e| e as u16))?,
glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims),
graphic_cache: GraphicCache::new(renderer),
})
}
@ -82,14 +82,14 @@ impl Cache {
self.text_cache.clear();
let max_texture_size = renderer.max_texture_size();
let cache_dims = renderer
.get_resolution()
.resolution()
.map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512));
self.glyph_cache = GlyphCache::builder()
.dimensions(cache_dims.x as u32, cache_dims.y as u32)
.dimensions(cache_dims.x, cache_dims.y)
.scale_tolerance(SCALE_TOLERANCE)
.position_tolerance(POSITION_TOLERANCE)
.build();
self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims.map(|e| e as u16))?;
self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims);
Ok(())
}
}

View File

@ -51,7 +51,7 @@ pub enum Rotation {
/// Fraction of the total graphic cache size
const ATLAS_CUTOFF_FRAC: f32 = 0.2;
/// Multiplied by current window size
const GRAPHIC_CACHE_RELATIVE_SIZE: u16 = 1;
const GRAPHIC_CACHE_RELATIVE_SIZE: u32 = 1;
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub struct Id(u32);
@ -314,7 +314,7 @@ impl GraphicCache {
// Graphics over a particular size are sent to their own textures
let location = if let Some(border_color) = border_color {
// Create a new immutable texture.
let texture = create_image(renderer, image, border_color).unwrap();
let texture = create_image(renderer, image, border_color);
// NOTE: All mutations happen only after the upload succeeds!
let index = textures.len();
textures.push(texture);
@ -365,7 +365,7 @@ impl GraphicCache {
}
} else {
// Create a texture just for this
let texture = renderer.create_dynamic_texture(dims).unwrap();
let texture = renderer.create_dynamic_texture(dims.map(|e| e as u32));
// NOTE: All mutations happen only after the texture creation succeeds!
let index = textures.len();
textures.push(texture);
@ -440,10 +440,10 @@ fn draw_graphic(
}
}
fn atlas_size(renderer: &Renderer) -> Vec2<u16> {
fn atlas_size(renderer: &Renderer) -> Vec2<u32> {
let max_texture_size = renderer.max_texture_size();
renderer.get_resolution().map(|e| {
renderer.resolution().map(|e| {
(e * GRAPHIC_CACHE_RELATIVE_SIZE)
.max(512)
.min(max_texture_size)
@ -452,8 +452,9 @@ fn atlas_size(renderer: &Renderer) -> Vec2<u16> {
fn create_atlas_texture(renderer: &mut Renderer) -> (SimpleAtlasAllocator, Texture) {
let size = atlas_size(renderer);
let atlas = SimpleAtlasAllocator::new(size2(i32::from(size.x), i32::from(size.y)));
let texture = renderer.create_dynamic_texture(size).unwrap();
// Note: here we assume the atlas size is under i32::MAX
let atlas = SimpleAtlasAllocator::new(size2(size.x as i32, size.y as i32));
let texture = renderer.create_dynamic_texture(size);
(atlas, texture)
}
@ -466,25 +467,27 @@ fn aabr_from_alloc_rect(rect: guillotiere::Rectangle) -> Aabr<u16> {
}
fn upload_image(renderer: &mut Renderer, aabr: Aabr<u16>, tex: &Texture, image: &RgbaImage) {
let aabr = aabr.map(|e| e as u32);
let offset = aabr.min.into_array();
let size = aabr.size().into_array();
if let Err(e) = renderer.update_texture(
renderer.update_texture(
tex,
offset,
size,
// NOTE: Rgba texture, so each pixel is 4 bytes, ergo this cannot fail.
// We make the cast parameters explicit for clarity.
bytemuck::cast_slice::<u8, [u8; 4]>(&image),
) {
warn!(?e, "Failed to update texture");
}
);
}
fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba<f32>) {
renderer.create_texture(
&DynamicImage::ImageRgba8(image),
None,
Some(wgpu::AddressMode::ClampToBorder),
Some(border_color.into_array().into()),
)
fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba<f32>) -> Texture {
renderer
.create_texture(
&DynamicImage::ImageRgba8(image),
None,
//TODO: either use the desktop only border color or just emulate this
// Some(border_color.into_array().into()),
Some(wgpu::AddressMode::ClampToBorder),
)
.expect("create_texture only panics is non ImageRbga8 is passed")
}

View File

@ -27,7 +27,7 @@ pub use widgets::{
use crate::{
render::{
create_ui_quad, create_ui_tri, Consts, Globals, Mesh, Model, RenderError, Renderer,
create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer,
UIVertex, UiLocals, UiMode,
},
window::Window,
@ -111,7 +111,7 @@ pub struct Ui {
// during redrawing.
mesh: Mesh<UIVertex>,
// Model for drawing the ui
model: Model<UIVertex>,
model: DynamicModel<UIVertex>,
// Consts for default ui drawing position (ie the interface)
interface_locals: Consts<UiLocals>,
default_globals: Consts<Globals>,
@ -164,7 +164,7 @@ impl Ui {
cache: Cache::new(renderer)?,
draw_commands: Vec::new(),
mesh: Mesh::new(),
model: renderer.create_dynamic_model(100)?,
model: renderer.create_dynamic_model(100),
interface_locals: renderer.create_consts(&[UiLocals::default()])?,
default_globals: renderer.create_consts(&[Globals::default()])?,
ingame_locals: Vec::new(),
@ -341,7 +341,7 @@ impl Ui {
// Avoid resetting cache if window size didn't change
// Somewhat inefficient for elements that won't change size after a window
// resize
let res = renderer.get_resolution();
let res = renderer.resolution();
res.x > 0 && res.y > 0 && !(old_w == w && old_h == h)
} else {
false
@ -389,7 +389,7 @@ impl Ui {
};
let (half_res, x_align, y_align) = {
let res = renderer.get_resolution();
let res = renderer.resolution();
(
res.map(|e| e as f32 / 2.0),
(res.x & 1) as f32 * 0.5,
@ -569,23 +569,15 @@ impl Ui {
tracing::debug!("Updating glyphs and clearing text cache.");
if let Err(err) = glyph_cache.cache_queued(|rect, data| {
let offset = [rect.min.x as u16, rect.min.y as u16];
let size = [rect.width() as u16, rect.height() as u16];
let offset = [rect.min.x as u32, rect.min.y as u32];
let size = [rect.width() as u32, rect.height() as u32];
let new_data = data
.iter()
.map(|x| [255, 255, 255, *x])
.collect::<Vec<[u8; 4]>>();
if let Err(err) = renderer.update_texture(
cache_tex,
offset,
size,
&new_data,
rect.width() * 4,
) {
warn!("Failed to update texture: {:?}", err);
}
renderer.update_texture(cache_tex, offset, size, &new_data);
}) {
// FIXME: If we actually hit this error, it's still possible we could salvage
// things in various ways (for instance, the current queue might have extra
@ -831,6 +823,7 @@ impl Ui {
let cache_dims = graphic_cache
.get_tex(tex_id)
.get_dimensions()
.xy()
.map(|e| e as f32);
let min = Vec2::new(aabr.min.x as f32, aabr.max.y as f32) / cache_dims;
let max = Vec2::new(aabr.max.x as f32, aabr.min.y as f32) / cache_dims;
@ -964,12 +957,10 @@ impl Ui {
// Push new position command
let world_pos = Vec4::from_point(parameters.pos);
if self.ingame_locals.len() > ingame_local_index {
renderer
.update_consts(
&mut self.ingame_locals[ingame_local_index],
&[world_pos.into()],
)
.unwrap();
renderer.update_consts(
&mut self.ingame_locals[ingame_local_index],
&[world_pos.into()],
)
} else {
self.ingame_locals
.push(renderer.create_consts(&[world_pos.into()]).unwrap());
@ -1017,13 +1008,11 @@ impl Ui {
// Create a larger dynamic model if the mesh is larger than the current model
// size.
if self.model.vbuf.len() < self.mesh.vertices().len() {
self.model = renderer
.create_dynamic_model(self.mesh.vertices().len() * 4 / 3)
.unwrap();
if self.model.len() < self.mesh.vertices().len() {
self.model = renderer.create_dynamic_model(self.mesh.vertices().len() * 4 / 3);
}
// Update model with new mesh.
renderer.update_model(&self.model, &self.mesh, 0).unwrap();
renderer.update_model(&self.model, &self.mesh, 0);
}
pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts<Globals>>) {
@ -1045,7 +1034,9 @@ impl Ui {
DrawKind::Plain => self.cache.glyph_cache_tex(),
};
let model = self.model.submodel(verts.clone());
renderer.render_ui_element(model, tex, scissor, globals, locals);
// TODO
//renderer.render_ui_element(model, tex, scissor, globals,
// locals);
},
}
}
@ -1053,12 +1044,12 @@ impl Ui {
}
fn default_scissor(renderer: &Renderer) -> Aabr<u16> {
let (screen_w, screen_h) = renderer.get_resolution().into_tuple();
let (screen_w, screen_h) = renderer.resolution().into_tuple();
Aabr {
min: Vec2 { x: 0, y: 0 },
max: Vec2 {
x: screen_w,
y: screen_h,
x: screen_w as u16,
y: screen_h as u16,
},
}
}

View File

@ -518,7 +518,7 @@ impl KeyMouse {
}
pub struct Window {
renderer: Renderer<'static>,
renderer: Renderer,
window: winit::window::Window,
cursor_grabbed: bool,
pub pan_sensitivity: u32,
@ -658,7 +658,7 @@ impl Window {
pub fn renderer(&self) -> &Renderer { &self.renderer }
pub fn renderer_mut(&mut self) -> &mut Renderer<'static> { &mut self.renderer }
pub fn renderer_mut(&mut self) -> &mut Renderer { &mut self.renderer }
pub fn resolve_deduplicated_events(&mut self, settings: &mut Settings) {
// Handle screenshots and toggling fullscreen
@ -941,7 +941,9 @@ impl Window {
// let (mut color_view, mut depth_view) = self.renderer.win_views_mut();
// self.window.resize(physical);
// self.window.update_gfx(&mut color_view, &mut depth_view);
self.renderer.on_resize().unwrap();
self.renderer
.on_resize(Vec2::new(physical.width, physical.height))
.unwrap();
// TODO: update users of this event with the fact that it is now the physical
// size
let winit::dpi::PhysicalSize { width, height } = physical;