You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
486 lines
11 KiB
486 lines
11 KiB
Content-Type: text/x-zim-wiki
|
|
Wiki-Format: zim 0.4
|
|
Creation-Date: 2020-02-28T22:36:46-08:00
|
|
|
|
====== PossiblePathfinderPort ======
|
|
Created Friday 28 February 2020
|
|
|
|
So I'm just going to use this space to talk about hooking up vulkano to this backend.
|
|
All in all, this seems somewhat simple. This backend expects you to define a dozen or so types which are then passed around and manipulated using this interface.
|
|
|
|
|
|
pub struct RenderState<'a, D> where D: Device
|
|
pub target: &'a RenderTarget<'a, D>,
|
|
pub program: &'a D::Program,
|
|
pub vertex_array: &'a D::VertexArray,
|
|
pub primitive: Primitive,
|
|
pub uniforms: &'a [(&'a D::Uniform, UniformData)],
|
|
pub textures: &'a [&'a D::Texture],
|
|
pub viewport: RectI,
|
|
pub options: RenderOptions,
|
|
|
|
|
|
**So I need to define the following types in Vulkan syntax**
|
|
|
|
**The other port uses container classes for these **
|
|
|
|
|
|
type Buffer;
|
|
type Framebuffer;
|
|
type Program;
|
|
**VulkanProgram**
|
|
type Shader;
|
|
type Texture;
|
|
type TextureDataReceiver;
|
|
type TimerQuery;
|
|
type Uniform;
|
|
type VertexArray;
|
|
type VertexAttr;
|
|
|
|
|
|
|
|
[*] fn create_texture(&self, format: TextureFormat, size: Vector2I) -> Self::Texture;
|
|
|
|
[*] fn create_texture_from_data(&self,
|
|
format: TextureFormat,
|
|
size: Vector2I,
|
|
data: TextureDataRef
|
|
) -> Self::Texture;
|
|
|
|
**For now I'm going to create just the shader and not the pipeline**
|
|
[*] fn create_shader(&self,
|
|
resources: &dyn ResourceLoader,
|
|
name: &str,
|
|
kind: ShaderKind)
|
|
-> Self::Shader;
|
|
|
|
|
|
[*] fn create_shader_from_source(&self,
|
|
name: &str,
|
|
source: &[u8],
|
|
kind: ShaderKind) -> Self::Shader;
|
|
|
|
|
|
**This seems to just return a container, but what is the type of the container?**
|
|
[ ] fn create_vertex_array(&self) -> Self::VertexArray;
|
|
|
|
**This means more in GL as a program is a part of the state machine**
|
|
**In vk and metal this just returns the two shaders in one object**
|
|
[*] fn create_program_from_shaders(
|
|
&self,
|
|
resources: &dyn ResourceLoader,
|
|
name: &str,
|
|
vertex_shader: Self::Shader,
|
|
fragment_shader: Self::Shader,
|
|
) -> Self::Program;
|
|
|
|
**This one I'm a little shakey on. Where do I get these attributes?**
|
|
[ ] fn get_vertex_attr(&self, program: &Self::Program, name: &str) -> Option<Self::VertexAttr>;
|
|
|
|
**This function just looks up the uniform using the name**
|
|
[ ] fn get_uniform(&self, program: &Self::Program, name: &str) -> Self::Uniform;
|
|
|
|
**Probably just allocating a buffer with data. Target is just usage**
|
|
**See that it passes in a borrow for Buffer, I assume we should do an**
|
|
**uninitialized_buffer type of deal**
|
|
[>] fn bind_buffer(&self,
|
|
vertex_array: &Self::VertexArray,
|
|
buffer: &Self::Buffer,
|
|
target: BufferTarget);
|
|
|
|
**This first bind_vertex_array()'s **
|
|
**Then it appears to set the instancing using the descriptor and divisor?**
|
|
**Then it configures the vertex attributes for the state. it's push pop it seems in gl**
|
|
fn configure_vertex_attr(&self,
|
|
vertex_array: &Self::VertexArray,
|
|
attr: &Self::VertexAttr,
|
|
descriptor: &VertexAttrDescriptor);
|
|
|
|
**This creates the framebuffer using render_pass**
|
|
**Since it's single-frame. We don't use the swapchain**
|
|
fn create_framebuffer(&self, texture: Self::Texture) -> Self::Framebuffer;
|
|
|
|
**This just creates an empty buffer **
|
|
fn create_buffer(&self) -> Self::Buffer;
|
|
|
|
**Allocates using an empty buffer. target is buffer_usage**
|
|
fn allocate_buffer<T>(
|
|
&self,
|
|
buffer: &Self::Buffer,
|
|
data: BufferData<T>,
|
|
target: BufferTarget,
|
|
mode: BufferUploadMode,
|
|
);
|
|
fn framebuffer_texture<'f>(&self, framebuffer: &'f Self::Framebuffer) -> &'f Self::Texture;
|
|
fn destroy_framebuffer(&self, framebuffer: Self::Framebuffer) -> Self::Texture;
|
|
fn texture_format(&self, texture: &Self::Texture) -> TextureFormat;
|
|
fn texture_size(&self, texture: &Self::Texture) -> Vector2I;
|
|
fn set_texture_sampling_mode(&self, texture: &Self::Texture, flags: TextureSamplingFlags);
|
|
fn upload_to_texture(&self, texture: &Self::Texture, rect: RectI, data: TextureDataRef);
|
|
|
|
**Command buffer stuff**
|
|
fn begin_commands(&self);
|
|
fn end_commands(&self);
|
|
|
|
|
|
fn draw_arrays(&self, index_count: u32, render_state: &RenderState<Self>);
|
|
fn draw_elements(&self, index_count: u32, render_state: &RenderState<Self>);
|
|
fn draw_elements_instanced(&self,
|
|
index_count: u32,
|
|
instance_count: u32,
|
|
render_state: &RenderState<Self>);
|
|
|
|
**This is the weird timing stuff**
|
|
fn create_timer_query(&self) -> Self::TimerQuery;
|
|
fn begin_timer_query(&self, query: &Self::TimerQuery);
|
|
fn end_timer_query(&self, query: &Self::TimerQuery);
|
|
fn try_recv_timer_query(&self, query: &Self::TimerQuery) -> Option<Duration>;
|
|
fn recv_timer_query(&self, query: &Self::TimerQuery) -> Duration;
|
|
|
|
**And then the GPU reads**
|
|
fn try_recv_texture_data(&self, receiver: &Self::TextureDataReceiver) -> Option<TextureData>;
|
|
fn recv_texture_data(&self, receiver: &Self::TextureDataReceiver) -> TextureData;
|
|
|
|
**This maybe reads?**
|
|
fn read_pixels(&self, target: &RenderTarget<Self>, viewport: RectI)
|
|
-> Self::TextureDataReceiver;
|
|
|
|
**This just creates a texture like I do**
|
|
fn create_texture_from_png(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Texture;
|
|
|
|
**This one just **
|
|
fn create_program_from_shader_names(
|
|
&self,
|
|
resources: &dyn ResourceLoader,
|
|
program_name: &str,
|
|
vertex_shader_name: &str,
|
|
fragment_shader_name: &str,
|
|
) -> Self::Program {
|
|
let vertex_shader = self.create_shader(resources, vertex_shader_name, ShaderKind::Vertex);
|
|
let fragment_shader =
|
|
self.create_shader(resources, fragment_shader_name, ShaderKind::Fragment);
|
|
self.create_program_from_shaders(resources, program_name, vertex_shader, fragment_shader)
|
|
}
|
|
|
|
fn create_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program {
|
|
self.create_program_from_shader_names(resources, name, name, name)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum TextureFormat {
|
|
R8,
|
|
R16F,
|
|
RGBA8,
|
|
RGBA16F,
|
|
RGBA32F,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum VertexAttrType {
|
|
F32,
|
|
I16,
|
|
I8,
|
|
U16,
|
|
U8,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum BufferData<'a, T> {
|
|
Uninitialized(usize),
|
|
Memory(&'a [T]),
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum BufferTarget {
|
|
Vertex,
|
|
Index,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum BufferUploadMode {
|
|
Static,
|
|
Dynamic,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum ShaderKind {
|
|
Vertex,
|
|
Fragment,
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub enum UniformData {
|
|
Float(f32),
|
|
IVec3([i32; 3]),
|
|
Int(i32),
|
|
Mat2(F32x4),
|
|
Mat4([F32x4; 4]),
|
|
Vec2(F32x2),
|
|
Vec3([f32; 3]),
|
|
Vec4(F32x4),
|
|
TextureUnit(u32),
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub enum Primitive {
|
|
Triangles,
|
|
Lines,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct RenderState<'a, D> where D: Device {
|
|
pub target: &'a RenderTarget<'a, D>,
|
|
pub program: &'a D::Program,
|
|
pub vertex_array: &'a D::VertexArray,
|
|
pub primitive: Primitive,
|
|
pub uniforms: &'a [(&'a D::Uniform, UniformData)],
|
|
pub textures: &'a [&'a D::Texture],
|
|
pub viewport: RectI,
|
|
pub options: RenderOptions,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct RenderOptions {
|
|
pub blend: Option<BlendState>,
|
|
pub depth: Option<DepthState>,
|
|
pub stencil: Option<StencilState>,
|
|
pub clear_ops: ClearOps,
|
|
pub color_mask: bool,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
pub struct ClearOps {
|
|
pub color: Option<ColorF>,
|
|
pub depth: Option<f32>,
|
|
pub stencil: Option<u8>,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum RenderTarget<'a, D> where D: Device {
|
|
Default,
|
|
Framebuffer(&'a D::Framebuffer),
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub struct BlendState {
|
|
pub dest_rgb_factor: BlendFactor,
|
|
pub dest_alpha_factor: BlendFactor,
|
|
pub src_rgb_factor: BlendFactor,
|
|
pub src_alpha_factor: BlendFactor,
|
|
pub op: BlendOp,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum BlendFactor {
|
|
Zero,
|
|
One,
|
|
SrcAlpha,
|
|
OneMinusSrcAlpha,
|
|
DestAlpha,
|
|
OneMinusDestAlpha,
|
|
DestColor,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum BlendOp {
|
|
Add,
|
|
Subtract,
|
|
ReverseSubtract,
|
|
Min,
|
|
Max,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Default, Debug)]
|
|
pub struct DepthState {
|
|
pub func: DepthFunc,
|
|
pub write: bool,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum DepthFunc {
|
|
Less,
|
|
Always,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct StencilState {
|
|
pub func: StencilFunc,
|
|
pub reference: u32,
|
|
pub mask: u32,
|
|
pub write: bool,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum StencilFunc {
|
|
Always,
|
|
Equal,
|
|
}
|
|
|
|
impl Default for RenderOptions {
|
|
#[inline]
|
|
fn default() -> RenderOptions {
|
|
RenderOptions {
|
|
blend: None,
|
|
depth: None,
|
|
stencil: None,
|
|
clear_ops: ClearOps::default(),
|
|
color_mask: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for BlendOp {
|
|
#[inline]
|
|
fn default() -> BlendOp {
|
|
BlendOp::Add
|
|
}
|
|
}
|
|
|
|
impl Default for StencilState {
|
|
#[inline]
|
|
fn default() -> StencilState {
|
|
StencilState {
|
|
func: StencilFunc::default(),
|
|
reference: 0,
|
|
mask: !0,
|
|
write: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DepthFunc {
|
|
#[inline]
|
|
fn default() -> DepthFunc {
|
|
DepthFunc::Less
|
|
}
|
|
}
|
|
|
|
impl Default for StencilFunc {
|
|
#[inline]
|
|
fn default() -> StencilFunc {
|
|
StencilFunc::Always
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum TextureData {
|
|
U8(Vec<u8>),
|
|
U16(Vec<u16>),
|
|
F16(Vec<f16>),
|
|
F32(Vec<f32>),
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum TextureDataRef<'a> {
|
|
U8(&'a [u8]),
|
|
F16(&'a [f16]),
|
|
F32(&'a [f32]),
|
|
}
|
|
|
|
impl UniformData {
|
|
#[inline]
|
|
pub fn from_transform_3d(transform: &Transform4F) -> UniformData {
|
|
UniformData::Mat4([transform.c0, transform.c1, transform.c2, transform.c3])
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct VertexAttrDescriptor {
|
|
pub size: usize,
|
|
pub class: VertexAttrClass,
|
|
pub attr_type: VertexAttrType,
|
|
pub stride: usize,
|
|
pub offset: usize,
|
|
pub divisor: u32,
|
|
pub buffer_index: u32,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum VertexAttrClass {
|
|
Float,
|
|
FloatNorm,
|
|
Int,
|
|
}
|
|
|
|
impl TextureFormat {
|
|
#[inline]
|
|
pub fn channels(self) -> usize {
|
|
match self {
|
|
TextureFormat::R8 | TextureFormat::R16F => 1,
|
|
TextureFormat::RGBA8 | TextureFormat::RGBA16F | TextureFormat::RGBA32F => 4,
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn bytes_per_pixel(self) -> usize {
|
|
match self {
|
|
TextureFormat::R8 => 1,
|
|
TextureFormat::R16F => 2,
|
|
TextureFormat::RGBA8 => 4,
|
|
TextureFormat::RGBA16F => 8,
|
|
TextureFormat::RGBA32F => 16,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ClearOps {
|
|
#[inline]
|
|
pub fn has_ops(&self) -> bool {
|
|
self.color.is_some() || self.depth.is_some() || self.stencil.is_some()
|
|
}
|
|
}
|
|
|
|
impl Default for BlendState {
|
|
#[inline]
|
|
fn default() -> BlendState {
|
|
BlendState {
|
|
src_rgb_factor: BlendFactor::One,
|
|
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
|
|
src_alpha_factor: BlendFactor::One,
|
|
dest_alpha_factor: BlendFactor::One,
|
|
op: BlendOp::Add,
|
|
}
|
|
}
|
|
}
|
|
|
|
bitflags! {
|
|
pub struct TextureSamplingFlags: u8 {
|
|
const REPEAT_U = 0x01;
|
|
const REPEAT_V = 0x02;
|
|
const NEAREST_MIN = 0x04;
|
|
const NEAREST_MAG = 0x08;
|
|
}
|
|
}
|
|
|
|
impl<'a> TextureDataRef<'a> {
|
|
#[doc(hidden)]
|
|
pub fn check_and_extract_data_ptr(self, minimum_size: Vector2I, format: TextureFormat)
|
|
-> *const c_void {
|
|
let channels = match (format, self) {
|
|
(TextureFormat::R8, TextureDataRef::U8(_)) => 1,
|
|
(TextureFormat::RGBA8, TextureDataRef::U8(_)) => 4,
|
|
(TextureFormat::RGBA16F, TextureDataRef::F16(_)) => 4,
|
|
(TextureFormat::RGBA32F, TextureDataRef::F32(_)) => 4,
|
|
_ => panic!("Unimplemented texture format!"),
|
|
};
|
|
|
|
let area = minimum_size.x() as usize * minimum_size.y() as usize;
|
|
|
|
match self {
|
|
TextureDataRef::U8(data) => {
|
|
assert!(data.len() >= area * channels);
|
|
data.as_ptr() as *const c_void
|
|
}
|
|
TextureDataRef::F16(data) => {
|
|
assert!(data.len() >= area * channels);
|
|
data.as_ptr() as *const c_void
|
|
}
|
|
TextureDataRef::F32(data) => {
|
|
assert!(data.len() >= area * channels);
|
|
data.as_ptr() as *const c_void
|
|
}
|
|
}
|
|
}
|
|
}
|