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' inherits = 'release'
debug = 1 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] [workspace.metadata.nix]
systems = ["x86_64-linux"] systems = ["x86_64-linux"]
@ -113,3 +108,13 @@ key = "veloren-nix.cachix.org-1:zokfKJqVsNV6kI/oJdLF6TYBdNPYGSb+diMVQPn/5Rc="
[workspace.metadata.nix.crateOverride.veloren-network] [workspace.metadata.nix.crateOverride.veloren-network]
buildInputs = ["openssl"] buildInputs = ["openssl"]
nativeBuildInputs = ["pkg-config"] 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 # Graphics
winit = {version = "0.24.0", features = ["serde"]} 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"] } bytemuck = { version="1.4", features=["derive"] }
shaderc = "0.6.2" shaderc = "0.6.2"

View File

@ -3,44 +3,60 @@ use wgpu::util::DeviceExt;
pub struct Buffer<T: Copy + Pod> { pub struct Buffer<T: Copy + Pod> {
pub buf: wgpu::Buffer, pub buf: wgpu::Buffer,
// bytes // Size in number of elements
count: usize, // TODO: determine if this is a good name
len: usize,
phantom_data: std::marker::PhantomData<T>, phantom_data: std::marker::PhantomData<T>,
} }
impl<T: Copy + Pod> Buffer<T> { impl<T: Copy + Pod> Buffer<T> {
pub fn new(device: &wgpu::Device, cap: u64, usage: wgpu::BufferUsage) -> Self { pub fn new(device: &wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> 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 {
let contents = bytemuck::cast_slice(data); let contents = bytemuck::cast_slice(data);
Self { Self {
buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor { buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: None, label: None,
contents, contents,
usage: usage | wgpu::BufferUsage::MAP_WRITE, usage,
}), }),
count: data.len(), len: data.len(),
phantom_data: std::marker::PhantomData, phantom_data: std::marker::PhantomData,
} }
} }
pub fn update(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, vals: &[T], offset: u64) { pub fn len(&self) -> usize { self.len }
if !vals.is_empty() { }
queue.write_buffer(&self.buf, offset, bytemuck::cast_slice(vals))
} 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; use bytemuck::Pod;
/// A handle to a series of constants sitting on the GPU. This is used to hold /// 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 /// information used in the rendering process that does not change throughout a
/// single render pass. /// single render pass.
pub struct Consts<T: Copy + Pod> { pub struct Consts<T: Copy + Pod> {
buf: Buffer<T>, buf: DynamicBuffer<T>,
} }
impl<T: Copy + Pod> Consts<T> { impl<T: Copy + Pod> Consts<T> {
/// Create a new `Const<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 { 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. /// 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) 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 /// Used to represent one of many possible errors that may be omitted by the
/// rendering subsystem. /// rendering subsystem.
#[derive(Debug)]
pub enum RenderError { pub enum RenderError {
RequestDeviceError(wgpu::RequestDeviceError), RequestDeviceError(wgpu::RequestDeviceError),
MappingError(wgpu::BufferAsyncError), MappingError(wgpu::BufferAsyncError),
@ -11,6 +10,23 @@ pub enum RenderError {
ShaderError(shaderc::Error), 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 { impl From<wgpu::RequestDeviceError> for RenderError {
fn from(err: wgpu::RequestDeviceError) -> Self { Self::RequestDeviceError(err) } 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; use bytemuck::Pod;
/// Represents a mesh that has been sent to the GPU. /// Represents a mesh that has been sent to the GPU.
pub struct Instances<T: Copy + Pod> { pub struct Instances<T: Copy + Pod> {
buf: Buffer<T>, buf: DynamicBuffer<T>,
} }
impl<T: Copy + Pod> Instances<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 { 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) self.buf.update(device, queue, vals, offset)
} }

View File

@ -15,7 +15,7 @@ pub use self::{
error::RenderError, error::RenderError,
instances::Instances, instances::Instances,
mesh::{Mesh, Quad, Tri}, mesh::{Mesh, Quad, Tri},
model::{Model, SubModel}, model::{DynamicModel, Model, SubModel},
pipelines::{ pipelines::{
clouds::{create_mesh as create_clouds_mesh, Locals as CloudsLocals}, clouds::{create_mesh as create_clouds_mesh, Locals as CloudsLocals},
figure::{ 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; use std::ops::Range;
/// Represents a mesh that has been sent to the GPU. /// Represents a mesh that has been sent to the GPU.
@ -20,13 +24,7 @@ pub struct Model<V: Vertex> {
impl<V: Vertex> Model<V> { impl<V: Vertex> Model<V> {
pub fn new(device: &wgpu::Device, mesh: &Mesh<V>) -> Self { pub fn new(device: &wgpu::Device, mesh: &Mesh<V>) -> Self {
Self { Self {
vbuf: Buffer::new_with_data(device, wgpu::BufferUsage::VERTEX, mesh.vertices()), vbuf: Buffer::new(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),
} }
} }
@ -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( pub fn update(
&mut self, &self,
device: &wgpu::Device, device: &wgpu::Device,
queue: &wgpu::Queue, queue: &wgpu::Queue,
mesh: &Mesh<V>, mesh: &Mesh<V>,
offset: u64, offset: usize,
) { ) {
self.vbuf.update(device, queue, mesh.vertices(), offset) 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 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 { rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw, front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back, cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false, clamp_depth: false,
depth_bias: 0, depth_bias: 0,
depth_bias_slope_scale: 0.0, depth_bias_slope_scale: 0.0,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -65,6 +65,7 @@ impl SkyboxPipeline {
rasterization_state: Some(wgpu::RasterizationStateDescriptor { rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw, front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back, cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false, clamp_depth: false,
depth_bias: 0, depth_bias: 0,
depth_bias_slope_scale: 0.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> { pub fn create_mesh() -> Mesh<Vertex> {
let mut mesh = Mesh::new(); let mut mesh = Mesh::new();

View File

@ -61,10 +61,12 @@ impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem; use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 3] =
wgpu::vertex_attr_array![0 => Float3, 1 => Uint, 2 => Uint];
wgpu::VertexBufferDescriptor { wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress, stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex, 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> { fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem; 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 { wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress, stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Instance, 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 { rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw, front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back, cull_mode: wgpu::CullMode::Back,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: false, clamp_depth: false,
depth_bias: 0, depth_bias: 0,
depth_bias_slope_scale: 0.0, depth_bias_slope_scale: 0.0,

View File

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

View File

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

View File

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

View File

@ -18,7 +18,7 @@ impl Texture {
filter_method: Option<wgpu::FilterMode>, filter_method: Option<wgpu::FilterMode>,
address_mode: Option<wgpu::AddressMode>, address_mode: Option<wgpu::AddressMode>,
) -> Result<Self, RenderError> { ) -> 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(|| { let buffer = image.as_flat_samples_u8().ok_or_else(|| {
RenderError::CustomError( RenderError::CustomError(
"We currently do not support color formats using more than 4 bytes / pixel.".into(), "We currently do not support color formats using more than 4 bytes / pixel.".into(),
@ -38,7 +38,7 @@ impl Texture {
sample_count: 1, sample_count: 1,
dimension: wgpu::TextureDimension::D2, dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb, format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
}); });
let mut command_encoder = let mut command_encoder =
@ -107,7 +107,8 @@ impl Texture {
sample_count: 1, sample_count: 1,
dimension: wgpu::TextureDimension::D2, dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb, 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 { let sampler_info = wgpu::SamplerDescriptor {
@ -161,8 +162,10 @@ impl Texture {
offset: [u32; 2], offset: [u32; 2],
size: [u32; 2], size: [u32; 2],
data: &[u8], 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 // TODO: Only works for 2D images
queue.write_texture( queue.write_texture(
wgpu::TextureCopyViewBase { wgpu::TextureCopyViewBase {
@ -177,8 +180,8 @@ impl Texture {
data, data,
wgpu::TextureDataLayout { wgpu::TextureDataLayout {
offset: 0, offset: 0,
bytes_per_row, bytes_per_row: size[0] * 4,
rows_per_image: self.size.height, rows_per_image: size[1],
}, },
wgpu::Extent3d { wgpu::Extent3d {
width: size[0], width: size[0],
@ -189,5 +192,7 @@ impl Texture {
} }
/// Get dimensions of the represented image. /// 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, ecs::comp::Interpolated,
render::{ render::{
pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel, pipelines, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel,
Mesh, RenderError, Renderer, TerrainVertex, Texture, Mesh, RenderError, Renderer, SubModel, TerrainVertex, Texture,
}, },
scene::{ scene::{
camera::{Camera, CameraMode, Dependents}, camera::{Camera, CameraMode, Dependents},
@ -63,7 +63,7 @@ pub type CameraData<'a> = (&'a Camera, f32);
pub type FigureModelRef<'a> = ( pub type FigureModelRef<'a> = (
&'a Consts<FigureLocals>, &'a Consts<FigureLocals>,
&'a Consts<FigureBoneData>, &'a Consts<FigureBoneData>,
&'a FigureModel, SubModel<'a, TerrainVertex>,
&'a Texture, /* <ColLightFmt> */ &'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 /* TODO: Consider using mipmaps instead of storing multiple texture atlases for different
* LOD levels. */ * LOD levels. */
col_lights: Texture, /* <ColLightFmt> */ col_lights: Texture, /* <ColLightFmt> */
/// Models stored in this figure entry; there may be several for one figure, /// Vertex ranges stored in this figure entry; there may be several for one
/// because of LOD models. /// figure, because of LOD models.
pub models: [FigureModel; N], 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 { struct FigureMgrStates {
@ -4734,13 +4744,14 @@ impl FigureMgr {
figure_lod_render_distance * scale.map_or(1.0, |s| s.0), figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|state| state.can_shadow_sun(), |state| state.can_shadow_sun(),
) { ) {
renderer.render_figure_shadow_directed( // TODO
model, //renderer.render_figure_shadow_directed(
global, // model,
locals, // global,
bone_consts, // locals,
&global.shadow_mats, // bone_consts,
); // &global.shadow_mats,
//);
} }
}); });
} }
@ -4791,7 +4802,8 @@ impl FigureMgr {
figure_lod_render_distance * scale.map_or(1.0, |s| s.0), figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|state| state.visible(), |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, figure_lod_render_distance,
|state| state.visible(), |state| state.visible(),
) { ) {
renderer.render_player(model, &col_lights, global, locals, bone_consts, lod); //renderer.render_player(model, &col_lights, global, locals,
renderer.render_player_shadow( // bone_consts, lod);
/*renderer.render_player_shadow(
model, model,
&col_lights, &col_lights,
global, global,
bone_consts, bone_consts,
lod, lod,
&global.shadow_mats, &global.shadow_mats,
); );*/
} }
} }
} }
@ -5175,11 +5188,11 @@ impl FigureMgr {
let figure_mid_detail_distance = figure_lod_render_distance * 0.5; 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) { 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) { } else if pos.distance_squared(cam_pos) > figure_mid_detail_distance.powi(2) {
&model_entry.models[1] model_entry.lod_model(1)
} else { } else {
&model_entry.models[0] model_entry.lod_model(0)
}; };
Some((locals, bone_consts, model, col_lights_.texture(model_entry))) Some((locals, bone_consts, model, col_lights_.texture(model_entry)))
@ -5225,7 +5238,7 @@ impl FigureColLights {
renderer: &mut Renderer, renderer: &mut Renderer,
(tex, tex_size): ColLightInfo, (tex, tex_size): ColLightInfo,
(opaque, bounds): (Mesh<TerrainVertex>, math::Aabb<f32>), (opaque, bounds): (Mesh<TerrainVertex>, math::Aabb<f32>),
vertex_range: [Range<u32>; N], vertex_ranges: [Range<u32>; N],
) -> Result<FigureModelEntry<N>, RenderError> { ) -> Result<FigureModelEntry<N>, RenderError> {
span!(_guard, "create_figure", "FigureColLights::create_figure"); span!(_guard, "create_figure", "FigureColLights::create_figure");
let atlas = &mut self.atlas; let atlas = &mut self.atlas;
@ -5237,22 +5250,22 @@ impl FigureColLights {
.expect("The model size for this figure does not fit in a u32!"); .expect("The model size for this figure does not fit in a u32!");
let model = renderer.create_model(&opaque)?; 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 { Ok(FigureModelEntry {
_bounds: bounds, _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, 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) { pub fn render(&self, renderer: &mut Renderer, global: &GlobalModel) {
if let Some((_, model)) = self.model.as_ref() { 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, client: &Client,
settings: &Settings, settings: &Settings,
) -> Self { ) -> 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); let sprite_render_context = lazy_init(renderer);
Self { Self {
@ -642,7 +642,7 @@ impl Scene {
self.map_bounds, self.map_bounds,
time_of_day, time_of_day,
scene_data.state.get_time(), scene_data.state.get_time(),
renderer.get_resolution().as_(), renderer.resolution().as_(),
Vec2::new(SHADOW_NEAR, SHADOW_FAR), Vec2::new(SHADOW_NEAR, SHADOW_FAR),
lights.len(), lights.len(),
shadows.len(), shadows.len(),
@ -1061,7 +1061,7 @@ impl Scene {
self.lod.render(renderer, global); self.lod.render(renderer, global);
// Render the skybox. // 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( self.terrain.render_translucent(
renderer, renderer,
@ -1075,19 +1075,20 @@ impl Scene {
// Render particle effects. // Render particle effects.
self.particle_mgr.render(renderer, scene_data, global, lod); self.particle_mgr.render(renderer, scene_data, global, lod);
// Render clouds (a post-processing effect) // TODO:
renderer.render_clouds( // // Render clouds (a post-processing effect)
&self.clouds.model, // renderer.render_clouds(
&global.globals, // &self.clouds.model,
&self.clouds.locals, // &global.globals,
self.lod.get_data(), // &self.clouds.locals,
); // self.lod.get_data(),
// );
renderer.render_post_process( // renderer.render_post_process(
&self.postprocess.model, // &self.postprocess.model,
&global.globals, // &global.globals,
&self.postprocess.locals, // &self.postprocess.locals,
self.lod.get_data(), // self.lod.get_data(),
); // );
} }
} }

View File

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

View File

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

View File

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

View File

@ -51,7 +51,7 @@ pub enum Rotation {
/// Fraction of the total graphic cache size /// Fraction of the total graphic cache size
const ATLAS_CUTOFF_FRAC: f32 = 0.2; const ATLAS_CUTOFF_FRAC: f32 = 0.2;
/// Multiplied by current window size /// 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)] #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub struct Id(u32); pub struct Id(u32);
@ -314,7 +314,7 @@ impl GraphicCache {
// Graphics over a particular size are sent to their own textures // Graphics over a particular size are sent to their own textures
let location = if let Some(border_color) = border_color { let location = if let Some(border_color) = border_color {
// Create a new immutable texture. // 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! // NOTE: All mutations happen only after the upload succeeds!
let index = textures.len(); let index = textures.len();
textures.push(texture); textures.push(texture);
@ -365,7 +365,7 @@ impl GraphicCache {
} }
} else { } else {
// Create a texture just for this // 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! // NOTE: All mutations happen only after the texture creation succeeds!
let index = textures.len(); let index = textures.len();
textures.push(texture); 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(); let max_texture_size = renderer.max_texture_size();
renderer.get_resolution().map(|e| { renderer.resolution().map(|e| {
(e * GRAPHIC_CACHE_RELATIVE_SIZE) (e * GRAPHIC_CACHE_RELATIVE_SIZE)
.max(512) .max(512)
.min(max_texture_size) .min(max_texture_size)
@ -452,8 +452,9 @@ fn atlas_size(renderer: &Renderer) -> Vec2<u16> {
fn create_atlas_texture(renderer: &mut Renderer) -> (SimpleAtlasAllocator, Texture) { fn create_atlas_texture(renderer: &mut Renderer) -> (SimpleAtlasAllocator, Texture) {
let size = atlas_size(renderer); let size = atlas_size(renderer);
let atlas = SimpleAtlasAllocator::new(size2(i32::from(size.x), i32::from(size.y))); // Note: here we assume the atlas size is under i32::MAX
let texture = renderer.create_dynamic_texture(size).unwrap(); let atlas = SimpleAtlasAllocator::new(size2(size.x as i32, size.y as i32));
let texture = renderer.create_dynamic_texture(size);
(atlas, texture) (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) { 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 offset = aabr.min.into_array();
let size = aabr.size().into_array(); let size = aabr.size().into_array();
if let Err(e) = renderer.update_texture( renderer.update_texture(
tex, tex,
offset, offset,
size, size,
// NOTE: Rgba texture, so each pixel is 4 bytes, ergo this cannot fail. // NOTE: Rgba texture, so each pixel is 4 bytes, ergo this cannot fail.
// We make the cast parameters explicit for clarity. // We make the cast parameters explicit for clarity.
bytemuck::cast_slice::<u8, [u8; 4]>(&image), 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>) { fn create_image(renderer: &mut Renderer, image: RgbaImage, border_color: Rgba<f32>) -> Texture {
renderer.create_texture( renderer
&DynamicImage::ImageRgba8(image), .create_texture(
None, &DynamicImage::ImageRgba8(image),
Some(wgpu::AddressMode::ClampToBorder), None,
Some(border_color.into_array().into()), //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::{ use crate::{
render::{ 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, UIVertex, UiLocals, UiMode,
}, },
window::Window, window::Window,
@ -111,7 +111,7 @@ pub struct Ui {
// during redrawing. // during redrawing.
mesh: Mesh<UIVertex>, mesh: Mesh<UIVertex>,
// Model for drawing the ui // Model for drawing the ui
model: Model<UIVertex>, model: DynamicModel<UIVertex>,
// Consts for default ui drawing position (ie the interface) // Consts for default ui drawing position (ie the interface)
interface_locals: Consts<UiLocals>, interface_locals: Consts<UiLocals>,
default_globals: Consts<Globals>, default_globals: Consts<Globals>,
@ -164,7 +164,7 @@ impl Ui {
cache: Cache::new(renderer)?, cache: Cache::new(renderer)?,
draw_commands: Vec::new(), draw_commands: Vec::new(),
mesh: Mesh::new(), mesh: Mesh::new(),
model: renderer.create_dynamic_model(100)?, model: renderer.create_dynamic_model(100),
interface_locals: renderer.create_consts(&[UiLocals::default()])?, interface_locals: renderer.create_consts(&[UiLocals::default()])?,
default_globals: renderer.create_consts(&[Globals::default()])?, default_globals: renderer.create_consts(&[Globals::default()])?,
ingame_locals: Vec::new(), ingame_locals: Vec::new(),
@ -341,7 +341,7 @@ impl Ui {
// Avoid resetting cache if window size didn't change // Avoid resetting cache if window size didn't change
// Somewhat inefficient for elements that won't change size after a window // Somewhat inefficient for elements that won't change size after a window
// resize // resize
let res = renderer.get_resolution(); let res = renderer.resolution();
res.x > 0 && res.y > 0 && !(old_w == w && old_h == h) res.x > 0 && res.y > 0 && !(old_w == w && old_h == h)
} else { } else {
false false
@ -389,7 +389,7 @@ impl Ui {
}; };
let (half_res, x_align, y_align) = { 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.map(|e| e as f32 / 2.0),
(res.x & 1) as f32 * 0.5, (res.x & 1) as f32 * 0.5,
@ -569,23 +569,15 @@ impl Ui {
tracing::debug!("Updating glyphs and clearing text cache."); tracing::debug!("Updating glyphs and clearing text cache.");
if let Err(err) = glyph_cache.cache_queued(|rect, data| { if let Err(err) = glyph_cache.cache_queued(|rect, data| {
let offset = [rect.min.x as u16, rect.min.y as u16]; let offset = [rect.min.x as u32, rect.min.y as u32];
let size = [rect.width() as u16, rect.height() as u16]; let size = [rect.width() as u32, rect.height() as u32];
let new_data = data let new_data = data
.iter() .iter()
.map(|x| [255, 255, 255, *x]) .map(|x| [255, 255, 255, *x])
.collect::<Vec<[u8; 4]>>(); .collect::<Vec<[u8; 4]>>();
if let Err(err) = renderer.update_texture( renderer.update_texture(cache_tex, offset, size, &new_data);
cache_tex,
offset,
size,
&new_data,
rect.width() * 4,
) {
warn!("Failed to update texture: {:?}", err);
}
}) { }) {
// FIXME: If we actually hit this error, it's still possible we could salvage // 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 // things in various ways (for instance, the current queue might have extra
@ -831,6 +823,7 @@ impl Ui {
let cache_dims = graphic_cache let cache_dims = graphic_cache
.get_tex(tex_id) .get_tex(tex_id)
.get_dimensions() .get_dimensions()
.xy()
.map(|e| e as f32); .map(|e| e as f32);
let min = Vec2::new(aabr.min.x as f32, aabr.max.y as f32) / cache_dims; 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; 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 // Push new position command
let world_pos = Vec4::from_point(parameters.pos); let world_pos = Vec4::from_point(parameters.pos);
if self.ingame_locals.len() > ingame_local_index { if self.ingame_locals.len() > ingame_local_index {
renderer renderer.update_consts(
.update_consts( &mut self.ingame_locals[ingame_local_index],
&mut self.ingame_locals[ingame_local_index], &[world_pos.into()],
&[world_pos.into()], )
)
.unwrap();
} else { } else {
self.ingame_locals self.ingame_locals
.push(renderer.create_consts(&[world_pos.into()]).unwrap()); .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 // Create a larger dynamic model if the mesh is larger than the current model
// size. // size.
if self.model.vbuf.len() < self.mesh.vertices().len() { if self.model.len() < self.mesh.vertices().len() {
self.model = renderer self.model = renderer.create_dynamic_model(self.mesh.vertices().len() * 4 / 3);
.create_dynamic_model(self.mesh.vertices().len() * 4 / 3)
.unwrap();
} }
// Update model with new mesh. // 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>>) { 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(), DrawKind::Plain => self.cache.glyph_cache_tex(),
}; };
let model = self.model.submodel(verts.clone()); 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> { 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 { Aabr {
min: Vec2 { x: 0, y: 0 }, min: Vec2 { x: 0, y: 0 },
max: Vec2 { max: Vec2 {
x: screen_w, x: screen_w as u16,
y: screen_h, y: screen_h as u16,
}, },
} }
} }

View File

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