Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions libs/render/buffer/global_layout/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
// along with OpenFA. If not, see <http://www.gnu.org/licenses/>.

pub enum GlobalSets {
Global = 0,
Atmosphere = 1,
Stars = 2,
ShapeTextures = 3,
ShapeBuffers = 4,
ShapeBuffers = 3,
ShapeTextures = 4,
ShapeArt = 5,
}

impl From<GlobalSets> for usize {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ use camera::{ArcBallCamera, CameraAbstract};
use failure::Fallible;
use global_layout::GlobalSets;
use input::{InputBindings, InputSystem};
use log::trace;
use nalgebra::Matrix4;
use omnilib::OmniLib;
use pal::Palette;
use shape_chunk::{ClosedChunk, DrawSelection, DrawState, OpenChunk, Vertex};
use shape_chunk::{DrawSelection, DrawState, ShapeChunkManager, Vertex};
use std::{sync::Arc, time::Instant};
use vulkano::{
buffer::{BufferUsage, CpuAccessibleBuffer},
Expand All @@ -43,6 +42,30 @@ mod vs {
include: ["./libs/render"],
src: "
#version 450
#include <common/include/include_global.glsl>
#include <buffer/shape_chunk/src/include_shape.glsl>

// Scene info
layout(push_constant) uniform PushConstantData {
mat4 view;
mat4 projection;
} pc;

const uint MAX_XFORM_ID = 32;

// Per shape input
layout(set = 3, binding = 0) buffer ChunkTransforms {
float data[];
} shape_transforms;
layout(set = 3, binding = 1) buffer ChunkFlags {
uint data[];
} shape_flags;
layout(set = 3, binding = 2) buffer ChunkXforms {
float data[];
} shape_xforms;
layout(set = 3, binding = 3) buffer ChunkXformOffsets {
uint data[];
} shape_xform_offsets;

// Per Vertex input
layout(location = 0) in vec3 position;
Expand All @@ -52,51 +75,40 @@ mod vs {
layout(location = 4) in uint flags1;
layout(location = 5) in uint xform_id;

// Per shape input
layout(set = 4, binding = 0) buffer ChunkFlags {
uint flag_data[];
} flags;
layout(set = 4, binding = 1) buffer ChunkTransforms {
float xform_data[];
} xforms;

layout(push_constant) uniform PushConstantData {
mat4 view;
mat4 projection;
} pc;

#include <common/include/include_global.glsl>
#include <buffer/shape_chunk/src/include_shape.glsl>

layout(location = 0) smooth out vec4 v_color;
layout(location = 1) smooth out vec2 v_tex_coord;
layout(location = 2) flat out uint f_flags0;
layout(location = 3) flat out uint f_flags1;

void main() {
uint shape_base_flag = 0;
uint shape_base_xform = 0;
if (gl_InstanceIndex >= 10) {
shape_base_flag = 2;
shape_base_xform = 24;
}

float xform[6] = {
xforms.xform_data[shape_base_xform + 6 * xform_id + 0],
xforms.xform_data[shape_base_xform + 6 * xform_id + 1],
xforms.xform_data[shape_base_xform + 6 * xform_id + 2],
xforms.xform_data[shape_base_xform + 6 * xform_id + 3],
xforms.xform_data[shape_base_xform + 6 * xform_id + 4],
xforms.xform_data[shape_base_xform + 6 * xform_id + 5],
uint base_transform = gl_InstanceIndex * 6;
uint base_flag = gl_InstanceIndex * 2;
uint base_xform = shape_xform_offsets.data[gl_InstanceIndex];

float transform[6] = {
shape_transforms.data[base_transform + 0],
shape_transforms.data[base_transform + 1],
shape_transforms.data[base_transform + 2],
shape_transforms.data[base_transform + 3],
shape_transforms.data[base_transform + 4],
shape_transforms.data[base_transform + 5]
};
float xform[6] = {0, 0, 0, 0, 0, 0};
if (xform_id < MAX_XFORM_ID) {
xform[0] = shape_xforms.data[base_xform + 6 * xform_id + 0];
xform[1] = shape_xforms.data[base_xform + 6 * xform_id + 1];
xform[2] = shape_xforms.data[base_xform + 6 * xform_id + 2];
xform[3] = shape_xforms.data[base_xform + 6 * xform_id + 3];
xform[4] = shape_xforms.data[base_xform + 6 * xform_id + 4];
xform[5] = shape_xforms.data[base_xform + 6 * xform_id + 5];
}

gl_Position = pc.projection * pc.view * matrix_for_xform(xform) * vec4(position, 1.0);
gl_Position.x += float(gl_InstanceIndex) * 10.0;
gl_Position = pc.projection * pc.view * matrix_for_xform(transform) * matrix_for_xform(xform) * vec4(position, 1.0);
v_color = color;
v_tex_coord = tex_coord;

f_flags0 = flags0 & flags.flag_data[shape_base_flag + 0];
f_flags1 = flags1 & flags.flag_data[shape_base_flag + 1];
f_flags0 = flags0 & shape_flags.data[base_flag + 0];
f_flags1 = flags1 & shape_flags.data[base_flag + 1];
}"
}
}
Expand All @@ -117,7 +129,11 @@ mod fs {

layout(location = 0) out vec4 f_color;

layout(set = 3, binding = 0) uniform sampler2DArray mega_atlas;
layout(set = 4, binding = 0) uniform sampler2DArray mega_atlas;
//layout(set = 5, binding = 1) uniform sampler2DArray nose_art; NOSE\\d\\d.PIC
//layout(set = 5, binding = 2) uniform sampler2DArray left_tail_art; LEFT\\d\\d.PIC
//layout(set = 5, binding = 3) uniform sampler2DArray right_tail_art; RIGHT\\d\\d.PIC
//layout(set = 5, binding = 4) uniform sampler2DArray round_art; ROUND\\d\\d.PIC

void main() {
if ((f_flags0 & 0xFFFFFFFE) == 0 && f_flags1 == 0) {
Expand Down Expand Up @@ -199,7 +215,6 @@ impl vs::ty::PushConstantData {

fn main() -> Fallible<()> {
let mut window = GraphicsWindow::new(&GraphicsConfigBuilder::new().build())?;
window.hide_cursor()?;
let bindings = InputBindings::new("base")
.bind("exit", "Escape")?
.bind("exit", "q")?;
Expand Down Expand Up @@ -235,19 +250,30 @@ fn main() -> Fallible<()> {
let lib = omni.library("FA");
let palette = Palette::from_bytes(&lib.load("PALETTE.PAL")?)?;

let mut open_chunk = OpenChunk::new(&window)?;
open_chunk.upload_shape("F8.SH", DrawSelection::NormalModel, &palette, &lib, &window)?;
open_chunk.upload_shape(
let mut chunk_man = ShapeChunkManager::new(pipeline.clone(), &window)?;
let (_f8_id, _) =
chunk_man.upload_shape("F8.SH", DrawSelection::NormalModel, &palette, &lib, &window)?;
let (f18_id, _) = chunk_man.upload_shape(
"F18.SH",
DrawSelection::NormalModel,
&palette,
&lib,
&window,
)?;
let (chunk, future) = ClosedChunk::new(open_chunk, pipeline.clone(), &window)?;
let future = chunk_man.finish(&window)?;
future.then_signal_fence_and_flush()?.wait(None)?;

let f18_part = chunk.part_for("F18.SH")?;
let chunk = chunk_man.chunk(f18_id)?;
let f18_part = chunk_man.part(f18_id)?;
let _f18_widgets = f18_part.widgets().read().unwrap().clone();

// Upload transforms
let transforms = vec![0f32, 0f32, 0f32, 0f32, 0f32, 0f32];
let transforms_buffer: Arc<CpuAccessibleBuffer<[f32]>> = CpuAccessibleBuffer::from_iter(
window.device(),
BufferUsage::all(),
transforms.iter().cloned(),
)?;

// Upload flags
let mut draw_state: DrawState = Default::default();
Expand All @@ -264,7 +290,7 @@ fn main() -> Fallible<()> {
flags_arr.iter().cloned(),
)?;

// Upload transforms
// Upload xforms
let now = Instant::now();
let xforms_len = f18_part.widgets().read().unwrap().num_transformer_floats();
let mut xforms = Vec::with_capacity(xforms_len);
Expand All @@ -273,18 +299,28 @@ fn main() -> Fallible<()> {
&draw_state,
draw_state.time_origin(),
&now,
&mut xforms[0..],
&mut xforms,
)?;
let xforms_buffer = CpuAccessibleBuffer::from_iter(
window.device(),
BufferUsage::all(),
xforms.iter().cloned(),
)?;

// Upload xform buffer offsets
let xform_offsets = vec![0];
let xform_offsets_buffer = CpuAccessibleBuffer::from_iter(
window.device(),
BufferUsage::all(),
xform_offsets.iter().cloned(),
)?;

let shape_descriptor_set = Arc::new(
PersistentDescriptorSet::start(pipeline.clone(), GlobalSets::ShapeBuffers.into())
.add_buffer(transforms_buffer)?
.add_buffer(flags_buffer)?
.add_buffer(xforms_buffer)?
.add_buffer(xform_offsets_buffer)?
.build()?,
);

Expand All @@ -301,6 +337,7 @@ fn main() -> Fallible<()> {
let empty0 = GraphicsWindow::empty_descriptor_set(pipeline.clone(), 0)?;
let empty1 = GraphicsWindow::empty_descriptor_set(pipeline.clone(), 1)?;
let empty2 = GraphicsWindow::empty_descriptor_set(pipeline.clone(), 2)?;
window.hide_cursor()?;
loop {
for command in input.poll(&mut window.events_loop) {
match command.name.as_str() {
Expand All @@ -314,7 +351,7 @@ fn main() -> Fallible<()> {
command.displacement()?.1 / 4.0,
),
"window-cursor-move" => {}
_ => trace!("unhandled command: {}", command.name),
_ => println!("unhandled command: {}", command.name),
}
}
window.center_cursor()?;
Expand Down Expand Up @@ -348,8 +385,8 @@ fn main() -> Fallible<()> {
empty0.clone(),
empty1.clone(),
empty2.clone(),
chunk.atlas_descriptor_set_ref(),
shape_descriptor_set.clone(),
chunk.atlas_descriptor_set_ref(),
),
push_constants,
)?;
Expand Down
16 changes: 16 additions & 0 deletions libs/render/buffer/shape_chunk/src/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ pub enum Chunk {
Closed(ClosedChunk),
}

impl Chunk {
pub fn is_open(&self) -> bool {
match self {
Self::Open(_) => true,
_ => false,
}
}

pub fn as_open_chunk_mut(&mut self) -> &mut OpenChunk {
match self {
Self::Open(chunk) => chunk,
_ => panic!("not an open chunk"),
}
}
}

// Where a shape lives in a chunk.
pub struct ChunkPart {
vertex_start: usize,
Expand Down
8 changes: 8 additions & 0 deletions libs/render/buffer/shape_chunk/src/chunk_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,12 @@ impl ShapeChunkManager {
.ok_or_else(|| err_msg("no chunk for associated shape id"))?;
self.closed_chunks[chunk_id].part(shape_id)
}

pub fn chunk(&self, shape_id: ShapeId) -> Fallible<&ClosedChunk> {
let chunk_id = self
.shape_to_chunk_map
.get(&shape_id)
.ok_or_else(|| err_msg("no chunk for associated shape id"))?;
Ok(&self.closed_chunks[chunk_id])
}
}
22 changes: 12 additions & 10 deletions libs/render/buffer/shape_chunk/src/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ pub struct ShapeWidgets {

// Self contained vm/instructions for how to set up each required transform
// to draw this shape buffer.
num_transformer_floats: usize,
transformers: Vec<Transformer>,

// Draw properties based on what's in the shape file.
Expand All @@ -518,6 +519,7 @@ pub struct ShapeWidgets {
impl ShapeWidgets {
pub fn new(name: &str, transformers: Vec<Transformer>, errata: ShapeErrata) -> Self {
Self {
num_transformer_floats: transformers.len() * 6,
shape_name: name.to_owned(),
transformers,
errata,
Expand Down Expand Up @@ -554,7 +556,7 @@ impl ShapeWidgets {
}

pub fn num_transformer_floats(&self) -> usize {
self.transformers.len() * 6
self.num_transformer_floats
}
}

Expand Down Expand Up @@ -584,7 +586,7 @@ impl ShapeUploader {
.unwrap_or_else(|| BufferProps {
context: "Static".to_owned(),
flags: VertexFlags::STATIC,
xform_id: 0,
xform_id: std::u32::MAX,
});
for v in vert_buf.vertices() {
let v0 = Vector3::new(f32::from(v[0]), f32::from(-v[2]), -f32::from(v[1]));
Expand Down Expand Up @@ -617,15 +619,15 @@ impl ShapeUploader {
override_flags: Option<VertexFlags>,
chunk: &mut OpenChunk,
) -> Fallible<()> {
// Load all vertices in this facet into the vertex upload
// buffer, copying in the color and texture coords for each
// face. The layout appears to be for triangle fans.
// Load all vertices in this facet into the vertex upload buffer, copying in the color and
// texture coords for each face. The layout appears to be for triangle fans.
for i in 2..facet.indices.len() {
// Given that most facets are very short strips, and we
// need to copy the vertices anyway, it's not *that*
// must worse to just copy the tris over instead of
// trying to get strips or fans working.
// TODO: use triangle fans directly
// Unlike modern rendering systems, FA had all of the non-position properties on the
// face instead of the vertex. The upshot is that we end up needing to split most
// vertices per face in order to move the face properties to the vertices. We could
// take the time to reverse these into fans or strips, deduping vertices, but since the
// models were not designed with that in mind, we don't end up saving as much space as
// we'd like. Instead, we just upload three vertices per triangle and call it good.
let js = [0, i - 1, i];
for j in &js {
let index = facet.indices[*j] as usize;
Expand Down
8 changes: 4 additions & 4 deletions libs/render/draw/legacy_shape/src/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use sh::{Facet, FacetFlags, Instr, RawShape, VertexBuf, X86Code, X86Trampoline,
use std::{
cell::RefCell,
collections::{HashMap, HashSet},
sync::Arc,
sync::{Arc, RwLock},
time::Instant,
};
use vulkano::{
Expand Down Expand Up @@ -434,7 +434,7 @@ pub struct Transformer {
// Note that mutability is an implementation detail here. We could construct
// a new one for each frame, for each instance, for each transform, but that
// would get expensive fast and we shouldn't actually be changing the state.
vm: RefCell<Interpreter>,
vm: Arc<RwLock<Interpreter>>,
code_offset: u32,
data_offset: u32,
inputs: Vec<TransformInput>,
Expand All @@ -452,7 +452,7 @@ impl Transformer {
d * std::f32::consts::PI / 8192f32
}

let mut vm = self.vm.borrow_mut();
let mut vm = self.vm.write().unwrap();
for input in &self.inputs {
let (loc, value) = match input {
TransformInput::CurrentTicks(loc) => {
Expand Down Expand Up @@ -987,7 +987,7 @@ impl ShapeUploader {

transformers.push(Transformer {
xform_id,
vm: RefCell::new(interp),
vm: Arc::new(RwLock::new(interp)),
code_offset: x86.code_offset(SHAPE_LOAD_BASE),
data_offset: SHAPE_LOAD_BASE + xform.at_offset() as u32 + 2u32,
inputs,
Expand Down
Loading