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
}
}
}
}