Harbor

branch main
showing the latest snapshot on main
d3d12_convert.odin 5.1 KB · Plain text
backend/d3d12/d3d12_convert.odin 0644 Raw
package d3d12_backend

import d3d12 "vendor:directx/d3d12"
import dxgi "vendor:directx/dxgi"

import bk ".."

// --- Format conversion ---

@(private)
to_dxgi_format :: proc(fmt: bk.Format) -> dxgi.FORMAT {
	switch fmt {
	case .Undefined:
		return .UNKNOWN
	case .R8G8B8A8_SRGB:
		return .R8G8B8A8_UNORM_SRGB
	case .R8G8B8A8_UNORM:
		return .R8G8B8A8_UNORM
	case .B8G8R8A8_SRGB:
		return .B8G8R8A8_UNORM_SRGB
	case .D32_SFLOAT:
		return .D32_FLOAT
	case .D32_SFLOAT_S8_UINT:
		return .D32_FLOAT_S8X24_UINT
	case .D24_UNORM_S8_UINT:
		return .D24_UNORM_S8_UINT
	}
	return .UNKNOWN
}

@(private)
from_dxgi_format :: proc(fmt: dxgi.FORMAT) -> bk.Format {
	#partial switch fmt {
	case .R8G8B8A8_UNORM_SRGB:
		return .R8G8B8A8_SRGB
	case .R8G8B8A8_UNORM:
		return .R8G8B8A8_UNORM
	case .B8G8R8A8_UNORM_SRGB:
		return .B8G8R8A8_SRGB
	case .D32_FLOAT:
		return .D32_SFLOAT
	case .D32_FLOAT_S8X24_UINT:
		return .D32_SFLOAT_S8_UINT
	case .D24_UNORM_S8_UINT:
		return .D24_UNORM_S8_UINT
	case:
		return .Undefined
	}
}

// --- Topology conversion (PSO type) ---

@(private)
to_d3d12_topology_type :: proc(t: bk.Topology) -> d3d12.PRIMITIVE_TOPOLOGY_TYPE {
	switch t {
	case .Triangle_List, .Triangle_Strip:
		return .TRIANGLE
	case .Line_List:
		return .LINE
	case .Point_List:
		return .POINT
	}
	return .TRIANGLE
}

// --- Topology conversion (draw-time) ---

@(private)
to_d3d12_topology :: proc(t: bk.Topology) -> d3d12.PRIMITIVE_TOPOLOGY {
	switch t {
	case .Triangle_List:
		return .TRIANGLELIST
	case .Triangle_Strip:
		return .TRIANGLESTRIP
	case .Line_List:
		return .LINELIST
	case .Point_List:
		return .POINTLIST
	}
	return .TRIANGLELIST
}

// --- Cull mode conversion ---

@(private)
to_d3d12_cull_mode :: proc(c: bk.Cull_Mode) -> d3d12.CULL_MODE {
	switch c {
	case .None:
		return .NONE
	case .Front:
		return .FRONT
	case .Back:
		return .BACK
	case .Front_And_Back:
		return .BACK
	}
	return .NONE
}

// --- Filter conversion ---

@(private)
to_d3d12_filter :: proc(mag, min, mip: bk.Filter) -> d3d12.FILTER {
	mag_linear := mag == .Linear
	min_linear := min == .Linear
	mip_linear := mip == .Linear

	if mag_linear && min_linear && mip_linear {
		return .MIN_MAG_MIP_LINEAR
	} else if mag_linear && min_linear && !mip_linear {
		return .MIN_MAG_LINEAR_MIP_POINT
	} else if !mag_linear && !min_linear && !mip_linear {
		return .MIN_MAG_MIP_POINT
	} else if !mag_linear && !min_linear && mip_linear {
		return .MIN_MAG_POINT_MIP_LINEAR
	} else if mag_linear && !min_linear {
		return .MIN_POINT_MAG_LINEAR_MIP_POINT
	} else if !mag_linear && min_linear {
		return .MIN_LINEAR_MAG_MIP_POINT
	}
	return .MIN_MAG_MIP_LINEAR
}

// --- Address mode conversion ---

@(private)
to_d3d12_address_mode :: proc(m: bk.Address_Mode) -> d3d12.TEXTURE_ADDRESS_MODE {
	switch m {
	case .Repeat:
		return .WRAP
	case .Clamp_To_Edge:
		return .CLAMP
	case .Clamp_To_Border:
		return .BORDER
	}
	return .WRAP
}

// --- Compare op conversion ---

@(private)
to_d3d12_compare_func :: proc(op: bk.Compare_Op) -> d3d12.COMPARISON_FUNC {
	switch op {
	case .Never:
		return .NEVER
	case .Less:
		return .LESS
	case .Less_Or_Equal:
		return .LESS_EQUAL
	case .Equal:
		return .EQUAL
	case .Greater_Or_Equal:
		return .GREATER_EQUAL
	case .Greater:
		return .GREATER
	case .Not_Equal:
		return .NOT_EQUAL
	case .Always:
		return .ALWAYS
	}
	return .ALWAYS
}

@(private)
to_d3d12_stencil_op :: proc(op: bk.Stencil_Op) -> d3d12.STENCIL_OP {
	switch op {
	case .Keep:
		return .KEEP
	case .Zero:
		return .ZERO
	case .Replace:
		return .REPLACE
	case .Increment_Clamp:
		return .INCR_SAT
	case .Decrement_Clamp:
		return .DECR_SAT
	case .Invert:
		return .INVERT
	}
	return .KEEP
}

@(private)
to_d3d12_stencil_face :: proc(face: bk.Stencil_Face_State) -> d3d12.DEPTH_STENCILOP_DESC {
	return {
		StencilFailOp      = to_d3d12_stencil_op(face.fail_op),
		StencilDepthFailOp = to_d3d12_stencil_op(face.depth_fail_op),
		StencilPassOp      = to_d3d12_stencil_op(face.pass_op),
		StencilFunc        = to_d3d12_compare_func(face.compare_op),
	}
}

// --- Vertex format conversion ---

@(private)
to_dxgi_vertex_format :: proc(fmt: bk.Vertex_Format) -> dxgi.FORMAT {
	switch fmt {
	case .Float2:
		return .R32G32_FLOAT
	case .Float3:
		return .R32G32B32_FLOAT
	case .Float4:
		return .R32G32B32A32_FLOAT
	}
	return .UNKNOWN
}

// --- Helpers ---

@(private)
format_pixel_size :: proc(fmt: bk.Format) -> u32 {
	switch fmt {
	case .R8G8B8A8_SRGB, .R8G8B8A8_UNORM, .B8G8R8A8_SRGB:
		return 4
	case .D32_SFLOAT:
		return 4
	case .D32_SFLOAT_S8_UINT:
		return 8
	case .D24_UNORM_S8_UINT:
		return 4
	case .Undefined:
		return 0
	}
	return 0
}

@(private)
depth_format_to_typeless :: proc(fmt: dxgi.FORMAT) -> dxgi.FORMAT {
	#partial switch fmt {
	case .D32_FLOAT:
		return .R32_TYPELESS
	case .D32_FLOAT_S8X24_UINT:
		return .R32G8X24_TYPELESS
	case .D24_UNORM_S8_UINT:
		return .R24G8_TYPELESS
	case:
		return fmt
	}
}

@(private)
depth_format_to_srv :: proc(fmt: dxgi.FORMAT) -> dxgi.FORMAT {
	#partial switch fmt {
	case .D32_FLOAT:
		return .R32_FLOAT
	case .D32_FLOAT_S8X24_UINT:
		return .R32_FLOAT_X8X24_TYPELESS
	case .D24_UNORM_S8_UINT:
		return .R24_UNORM_X8_TYPELESS
	case:
		return fmt
	}
}