Compare commits

..

35 Commits

Author SHA1 Message Date
7d35ac0e5b Move vertex format to utils. 2023-01-07 06:30:08 +01:00
7384a014ff Improve enum declaration. 2023-01-06 18:42:58 +01:00
cb763962fd Merge vertex and param formats. 2023-01-06 18:40:58 +01:00
39c449a763 Add direct copy when output and input vertex formats are matching. 2023-01-06 18:16:10 +01:00
a02d8e4d7d Fix unsigned packed vertex format. 2023-01-06 18:15:19 +01:00
81d52086fe Rework params packing. 2023-01-06 17:05:09 +01:00
16c7c91508 Add function attributes to cmp_memcpy. 2023-01-06 17:03:21 +01:00
9181d58ecd Add template for packed ints and fix missing define. 2023-01-06 17:02:24 +01:00
a6ec35ebd1 Remove heavy optims flags from makefile and add predefined function attributes instead. 2023-01-06 17:00:11 +01:00
596caef7ee Move cmp_memcpy into directory utils. 2023-01-05 03:39:32 +01:00
f463db316f Fix signed integers normalisation. 2023-01-04 15:24:18 +01:00
59d13684be Improve typing in render. 2023-01-04 12:41:05 +01:00
d6ec77207f Cleanup includes. 2023-01-04 10:22:12 +01:00
b46b4bddba Improve typing in render. 2023-01-04 09:33:49 +01:00
ebc6ededf3 Improve mesh struct after switching to mesh indices. 2023-01-04 09:06:13 +01:00
74b6f58794 Fix redondant modification test in batch sorting. 2023-01-03 21:41:03 +01:00
39a95e24c3 Switch to buckets sorting. 2023-01-03 21:31:36 +01:00
3e0ea2560a Improve compare-memcopy. 2023-01-03 20:50:18 +01:00
558ec08614 Buckets sorting. 2023-01-03 16:06:11 +01:00
211762c279 Remove obvious flags from makefile. 2023-01-03 16:05:37 +01:00
a5adfacdfd Use mesh indices in batch. 2023-01-03 14:05:25 +01:00
d0741afda7 Stores meshes into vertices. 2023-01-03 12:59:07 +01:00
66980e6ea9 Move vertices and indicies buffers to vertices. 2023-01-03 11:38:19 +01:00
a91a852887 Automatic batch freezing. 2023-01-03 11:10:37 +01:00
357066b315 Cleanup makefile. 2023-01-03 11:10:14 +01:00
baac333b44 Batch freezing. 2023-01-03 05:28:24 +01:00
ed87f292ff Split batch fill and batch draw. 2023-01-02 17:01:36 +01:00
afad17d517 Fix interface types and constness. 2023-01-02 12:14:13 +01:00
beca8798bf Rename create_shader. 2023-01-01 08:09:37 +01:00
e80bbe2418 Remove begin_frame and end_frame, add clear_buffer. 2023-01-01 07:57:10 +01:00
ae3333e22e Move samplers bindings to shaders. 2022-12-31 13:36:48 +01:00
2095e335ea More errors handling. 2022-12-31 12:26:41 +01:00
6ec993c6f8 Some errors handling. 2022-12-31 11:52:26 +01:00
38a692bc42 Disable dithering. 2022-12-31 11:50:09 +01:00
7706fe3a26 Print max textures layers and max attribs. 2022-12-31 11:49:47 +01:00
10 changed files with 1059 additions and 532 deletions

View File

@ -21,7 +21,7 @@ cpp/math.cpp
OUTPUTFILE = engine.so OUTPUTFILE = engine.so
CXXFLAGS = -fpic -Wall -Werror -O2 -flto -fomit-frame-pointer -ffast-math -funroll-loops -fno-rtti -fno-exceptions CXXFLAGS = -std=c++17 -Wall -Werror -O2 -msse2 -fpic -flto -fno-rtti -fno-exceptions
.PHONY: all .PHONY: all
all: clean $(OUTPUTFILE) all: clean $(OUTPUTFILE)

View File

@ -21,6 +21,12 @@ _engine = ctypes.cdll.LoadLibrary(Path(__file__).parent / "engine.so")
# types.hpp # types.hpp
_handle = ctypes.c_void_p
def _check_handle(result, func, arguments):
assert result
return result
def _flag(x): def _flag(x):
return 1 << x return 1 << x
@ -38,6 +44,10 @@ def _ushort_addr(x):
assert x.typecode == 'H' assert x.typecode == 'H'
return x.buffer_info()[0] return x.buffer_info()[0]
def _uint_addr(x):
assert x.typecode == 'I'
return x.buffer_info()[0]
def _float_addr(x): def _float_addr(x):
assert x.typecode == 'f' assert x.typecode == 'f'
return x.buffer_info()[0] return x.buffer_info()[0]
@ -138,6 +148,7 @@ mat4_identity = mat4(
vec4_origin) vec4_origin)
vec3_rotate = _engine.rk_vec3_rotate vec3_rotate = _engine.rk_vec3_rotate
vec3_rotate.restype = None
vec3_rotate.argtypes = ( vec3_rotate.argtypes = (
_vec3_p, # ret _vec3_p, # ret
_vec3_p, # vec3 _vec3_p, # vec3
@ -145,30 +156,35 @@ vec3_rotate.argtypes = (
ctypes.c_float) # angle ctypes.c_float) # angle
vec3_mul_vec3 = _engine.rk_vec3_mul_vec3 vec3_mul_vec3 = _engine.rk_vec3_mul_vec3
vec3_mul_vec3.restype = None
vec3_mul_vec3.argtypes = ( vec3_mul_vec3.argtypes = (
_vec3_p, # ret _vec3_p, # ret
_vec3_p, # a _vec3_p, # a
_vec3_p) # b _vec3_p) # b
mat3_rotation = _engine.rk_mat3_rotation mat3_rotation = _engine.rk_mat3_rotation
mat3_rotation.restype = None
mat3_rotation.argtypes = ( mat3_rotation.argtypes = (
_mat3_p, # ret _mat3_p, # ret
_vec3_p, # axis _vec3_p, # axis
ctypes.c_float) # angle ctypes.c_float) # angle
mat3_mul_vec3 = _engine.rk_mat3_mul_vec3 mat3_mul_vec3 = _engine.rk_mat3_mul_vec3
mat3_mul_vec3.restype = None
mat3_mul_vec3.argtypes = ( mat3_mul_vec3.argtypes = (
_vec3_p, # ret _vec3_p, # ret
_mat3_p, # a _mat3_p, # a
_vec3_p) # b _vec3_p) # b
mat3_mul_mat3 = _engine.rk_mat3_mul_mat3 mat3_mul_mat3 = _engine.rk_mat3_mul_mat3
mat3_mul_mat3.restype = None
mat3_mul_mat3.argtypes = ( mat3_mul_mat3.argtypes = (
_mat3_p, # ret _mat3_p, # ret
_mat3_p, # a _mat3_p, # a
_mat3_p) # b _mat3_p) # b
mat4_projection = _engine.rk_mat4_projection mat4_projection = _engine.rk_mat4_projection
mat4_projection.restype = None
mat4_projection.argtypes = ( mat4_projection.argtypes = (
_mat4_p, # ret _mat4_p, # ret
ctypes.c_float, # hfov ctypes.c_float, # hfov
@ -177,12 +193,14 @@ mat4_projection.argtypes = (
ctypes.c_float) # far ctypes.c_float) # far
mat4_lookat = _engine.rk_mat4_lookat mat4_lookat = _engine.rk_mat4_lookat
mat4_lookat.restype = None
mat4_lookat.argtypes = ( mat4_lookat.argtypes = (
_mat4_p, # ret _mat4_p, # ret
_vec3_p, # position _vec3_p, # position
_vec3_p) # lookat _vec3_p) # lookat
mat4_orbit = _engine.rk_mat4_orbit mat4_orbit = _engine.rk_mat4_orbit
mat4_orbit.restype = None
mat4_orbit.argtypes = ( mat4_orbit.argtypes = (
_mat4_p, # ret _mat4_p, # ret
_vec3_p, # origin _vec3_p, # origin
@ -191,6 +209,7 @@ mat4_orbit.argtypes = (
ctypes.c_float) # distance ctypes.c_float) # distance
mat4_mul_vec3 = _engine.rk_mat4_mul_vec3 mat4_mul_vec3 = _engine.rk_mat4_mul_vec3
mat4_mul_vec3.restype = None
mat4_mul_vec3.argtypes = ( mat4_mul_vec3.argtypes = (
_vec3_p, # ret _vec3_p, # ret
_mat4_p, # a _mat4_p, # a
@ -198,12 +217,14 @@ mat4_mul_vec3.argtypes = (
ctypes.c_float) # w ctypes.c_float) # w
mat4_mul_vec4 = _engine.rk_mat4_mul_vec4 mat4_mul_vec4 = _engine.rk_mat4_mul_vec4
mat4_mul_vec4.restype = None
mat4_mul_vec4.argtypes = ( mat4_mul_vec4.argtypes = (
_vec4_p, # ret _vec4_p, # ret
_mat4_p, # a _mat4_p, # a
_vec4_p) # b _vec4_p) # b
mat4_mul_mat4 = _engine.rk_mat4_mul_mat4 mat4_mul_mat4 = _engine.rk_mat4_mul_mat4
mat4_mul_mat4.restype = None
mat4_mul_mat4.argtypes = ( mat4_mul_mat4.argtypes = (
_mat4_p, # ret _mat4_p, # ret
_mat4_p, # a _mat4_p, # a
@ -212,17 +233,20 @@ mat4_mul_mat4.argtypes = (
# display.hpp # display.hpp
create_display = _engine.rk_create_display create_display = _engine.rk_create_display
create_display.restype = ctypes.c_void_p create_display.restype = _handle
create_display.errcheck = _check_handle
create_display.argtypes = ( create_display.argtypes = (
ctypes.c_char_p, # name ctypes.c_char_p, # name
ctypes.c_uint, # width ctypes.c_uint, # width
ctypes.c_uint) # height ctypes.c_uint) # height
destroy_display = _engine.rk_destroy_display destroy_display = _engine.rk_destroy_display
destroy_display.restype = None
destroy_display.argtypes = ( destroy_display.argtypes = (
ctypes.c_void_p,) # display ctypes.c_void_p,) # display
swap_buffers = _engine.rk_swap_buffers swap_buffers = _engine.rk_swap_buffers
swap_buffers.restype = None
swap_buffers.argtypes = ( swap_buffers.argtypes = (
ctypes.c_void_p,) # display ctypes.c_void_p,) # display
@ -244,34 +268,28 @@ TEXTURE_FLAG_MAG_NEAREST = 0
TEXTURE_FLAG_MAG_LINEAR = _flag(3) TEXTURE_FLAG_MAG_LINEAR = _flag(3)
VERTEX_FORMAT_VEC3_FLOAT = 1 VERTEX_FORMAT_VEC3_FLOAT = 1
VERTEX_FORMAT_VEC3_INT10 = 2 VERTEX_FORMAT_VEC3_SHORT = 2
VERTEX_FORMAT_VEC3_UINT10 = 3 VERTEX_FORMAT_VEC3_INT10 = 3
VERTEX_FORMAT_VEC3_UINT10 = 4
VERTEX_FORMAT_MAT3_FLOAT = 5
VERTEX_FORMAT_MAT3_INT10 = 6
VERTEX_FORMAT_NORMALIZE = _flag(7) VERTEX_FORMAT_NORMALIZE = _flag(7)
_VERTEX_FORMAT_MASK = VERTEX_FORMAT_NORMALIZE - 1
def vertex_format(*format): def vertex_format(*format):
return array('B', format).tobytes() return array('B', format).tobytes()
PARAM_FORMAT_VEC3_FLOAT = 1 _VERTEX_TYPES = (
PARAM_FORMAT_VEC3_SHORT = 2
PARAM_FORMAT_VEC3_INT10 = 3
PARAM_FORMAT_MAT3_FLOAT = 4
PARAM_FORMAT_MAT3_INT10 = 5
PARAM_FORMAT_NORMALIZE = _flag(7)
_PARAM_FORMAT_MASK = PARAM_FORMAT_NORMALIZE - 1
_PARAMS_TYPES = (
None, None,
vec3, # PARAM_FORMAT_VEC3_FLOAT vec3, # VERTEX_FORMAT_VEC3_FLOAT
vec3, # PARAM_FORMAT_VEC3_SHORT vec3, # VERTEX_FORMAT_VEC3_SHORT
vec3, # PARAM_FORMAT_VEC3_INT10 vec3, # VERTEX_FORMAT_VEC3_INT10
mat3, # PARAM_FORMAT_MAT3_FLOAT vec3, # VERTEX_FORMAT_VEC3_UINT10
mat3) # PARAM_FORMAT_MAT3_INT10 mat3, # VERTEX_FORMAT_MAT3_FLOAT
mat3) # VERTEX_FORMAT_MAT3_INT10
def param_type(format): def vertex_type(format):
return _PARAMS_TYPES[format & _PARAM_FORMAT_MASK] return _VERTEX_TYPES[format & _VERTEX_FORMAT_MASK]
def params_format(*format):
return array('B', format).tobytes()
INSTANCE_FLAG_SPAWNED = _flag(0) INSTANCE_FLAG_SPAWNED = _flag(0)
INSTANCE_FLAG_VISIBLE = _flag(1) INSTANCE_FLAG_VISIBLE = _flag(1)
@ -279,42 +297,46 @@ INSTANCE_FLAG_VISIBLE = _flag(1)
BATCH_MAX_SIZE = 65536 BATCH_MAX_SIZE = 65536
render_initialize = _engine.rk_render_initialize render_initialize = _engine.rk_render_initialize
render_initialize.restype = None
render_initialize.argtypes = ( render_initialize.argtypes = (
ctypes.c_bool,) # debug ctypes.c_bool,) # debug
render_terminate = _engine.rk_render_terminate render_terminate = _engine.rk_render_terminate
render_terminate.restype = None
_load_shader = _engine.rk_load_shader _create_shader = _engine.rk_create_shader
_load_shader.restype = ctypes.c_void_p _create_shader.restype = _handle
_load_shader.argtypes = ( _create_shader.errcheck = _check_handle
_create_shader.argtypes = (
ctypes.c_uint, # vert_nlines ctypes.c_uint, # vert_nlines
ctypes.POINTER(ctypes.c_char_p), # vert_lines ctypes.POINTER(ctypes.c_char_p), # vert_lines
ctypes.c_uint, # frag_nlines ctypes.c_uint, # frag_nlines
ctypes.POINTER(ctypes.c_char_p)) # frag_lines ctypes.POINTER(ctypes.c_char_p)) # frag_lines
def load_shader(vert_lines, frag_lines): def create_shader(vert_lines, frag_lines):
vert_nlines = len(vert_lines) vert_nlines = len(vert_lines)
vert_type = ctypes.c_char_p * vert_nlines vert_type = ctypes.c_char_p * vert_nlines
vert_lines = vert_type(*map(ctypes.c_char_p, vert_lines)) vert_lines = vert_type(*map(ctypes.c_char_p, vert_lines))
frag_nlines = len(frag_lines) frag_nlines = len(frag_lines)
frag_type = ctypes.c_char_p * frag_nlines frag_type = ctypes.c_char_p * frag_nlines
frag_lines = frag_type(*map(ctypes.c_char_p, frag_lines)) frag_lines = frag_type(*map(ctypes.c_char_p, frag_lines))
return _load_shader(vert_nlines, vert_lines, frag_nlines, frag_lines) return _create_shader(vert_nlines, vert_lines, frag_nlines, frag_lines)
resolve_input = _engine.rk_resolve_input resolve_input = _engine.rk_resolve_input
resolve_input.restype = ctypes.c_void_p resolve_input.restype = _handle
resolve_input.argtypes = ( resolve_input.argtypes = (
ctypes.c_void_p, # shader ctypes.c_void_p, # shader
ctypes.c_char_p) # name ctypes.c_char_p) # name
resolve_param = _engine.rk_resolve_param resolve_param = _engine.rk_resolve_param
resolve_param.restype = ctypes.c_void_p resolve_param.restype = _handle
resolve_param.argtypes = ( resolve_param.argtypes = (
ctypes.c_void_p, # shader ctypes.c_void_p, # shader
ctypes.c_char_p) # name ctypes.c_char_p) # name
_create_texture = _engine.rk_create_texture _create_texture = _engine.rk_create_texture
_create_texture.restype = ctypes.c_void_p _create_texture.restype = _handle
_create_texture.errcheck = _check_handle
_create_texture.argtypes = ( _create_texture.argtypes = (
ctypes.c_uint, # format ctypes.c_uint, # format
ctypes.c_uint, # width ctypes.c_uint, # width
@ -329,7 +351,8 @@ def create_texture(format, width, height, nlevels, flags, pixels):
return _create_texture(format, width, height, nlevels, flags, _void_addr(pixels)) return _create_texture(format, width, height, nlevels, flags, _void_addr(pixels))
_create_triangles = _engine.rk_create_triangles _create_triangles = _engine.rk_create_triangles
_create_triangles.restype = ctypes.c_void_p _create_triangles.restype = _handle
_create_triangles.errcheck = _check_handle
_create_triangles.argtypes = ( _create_triangles.argtypes = (
ctypes.c_uint, # nvertices ctypes.c_uint, # nvertices
ctypes.c_void_p) # vertices ctypes.c_void_p) # vertices
@ -339,107 +362,136 @@ def create_triangles(vertices):
return _create_triangles(len(vertices) // 3, _float_addr(vertices)) return _create_triangles(len(vertices) // 3, _float_addr(vertices))
_create_vertices = _engine.rk_create_vertices _create_vertices = _engine.rk_create_vertices
_create_vertices.restype = ctypes.c_void_p _create_vertices.restype = _handle
_create_vertices.errcheck = _check_handle
_create_vertices.argtypes = ( _create_vertices.argtypes = (
ctypes.c_char_p, # format ctypes.c_char_p, # format
ctypes.c_uint, # nvertices ctypes.c_uint, # nvertices
ctypes.c_void_p, # vertices ctypes.c_void_p, # vertices
ctypes.c_uint, # nindices ctypes.c_uint, # nindices
ctypes.c_void_p) # indices ctypes.c_void_p, # vertices
ctypes.c_uint, # nmeshes
ctypes.c_void_p) # meshes
def create_vertices(format, nvertices, vertices, indices): def create_vertices(format, nvertices, vertices, indices, meshes):
return _create_vertices(format, nvertices, _ubyte_addr(vertices), len(indices), _ushort_addr(indices)) assert len(meshes) % 2 == 0
return _create_vertices(format,
nvertices, _ubyte_addr(vertices), len(indices), _ushort_addr(indices), len(meshes) // 2, _uint_addr(meshes))
create_batch = _engine.rk_create_batch create_batch = _engine.rk_create_batch
create_batch.restype = ctypes.c_void_p create_batch.restype = _handle
create_batch.errcheck = _check_handle
create_batch.argtypes = ( create_batch.argtypes = (
ctypes.c_void_p, # vertices ctypes.c_void_p, # vertices
ctypes.c_uint, # max_size ctypes.c_uint, # max_size
ctypes.c_uint, # max_meshes
ctypes.c_char_p) # params_format ctypes.c_char_p) # params_format
begin_frame = _engine.rk_begin_frame fill_batch = _engine.rk_fill_batch
fill_batch.restype = None
fill_batch.argtypes = (
ctypes.c_void_p, # batch
ctypes.c_uint, # count
ctypes.POINTER(ctypes.c_ubyte), # flags
ctypes.POINTER(ctypes.c_ushort), # meshes
ctypes.POINTER(ctypes.c_void_p)) # params
clear_buffer = _engine.rk_clear_buffer
clear_buffer.restype = None
clear_buffer.argtypes = (
ctypes.c_bool, # pixels
ctypes.c_bool, # depth
ctypes.c_bool) # stencil
select_shader = _engine.rk_select_shader select_shader = _engine.rk_select_shader
select_shader.restype = None
select_shader.argtypes = ( select_shader.argtypes = (
ctypes.c_void_p,) # shader ctypes.c_void_p,) # shader
set_input_float = _engine.rk_set_input_float set_input_float = _engine.rk_set_input_float
set_input_float.restype = None
set_input_float.argtypes = ( set_input_float.argtypes = (
ctypes.c_void_p, # input ctypes.c_void_p, # input
ctypes.c_float) # value ctypes.c_float) # value
set_input_vec3 = _engine.rk_set_input_vec3 set_input_vec3 = _engine.rk_set_input_vec3
set_input_vec3.restype = None
set_input_vec3.argtypes = ( set_input_vec3.argtypes = (
ctypes.c_void_p, # input ctypes.c_void_p, # input
_vec3_p) # value _vec3_p) # value
set_input_mat3 = _engine.rk_set_input_mat3 set_input_mat3 = _engine.rk_set_input_mat3
set_input_mat3.restype = None
set_input_mat3.argtypes = ( set_input_mat3.argtypes = (
ctypes.c_void_p, # input ctypes.c_void_p, # input
_mat3_p) # value _mat3_p) # value
set_input_mat4 = _engine.rk_set_input_mat4 set_input_mat4 = _engine.rk_set_input_mat4
set_input_mat4.restype = None
set_input_mat4.argtypes = ( set_input_mat4.argtypes = (
ctypes.c_void_p, # input ctypes.c_void_p, # input
_mat4_p) # value _mat4_p) # value
set_param_vec3 = _engine.rk_set_param_vec3 set_param_vec3 = _engine.rk_set_param_vec3
set_param_vec3.restype = None
set_param_vec3.argtypes = ( set_param_vec3.argtypes = (
ctypes.c_uint, # layout ctypes.c_uint, # layout
_vec3_p) # value _vec3_p) # value
set_param_mat3 = _engine.rk_set_param_mat3 set_param_mat3 = _engine.rk_set_param_mat3
set_param_mat3.restype = None
set_param_mat3.argtypes = ( set_param_mat3.argtypes = (
ctypes.c_uint, # layout ctypes.c_uint, # layout
_mat3_p) # value _mat3_p) # value
select_texture = _engine.rk_select_texture select_texture = _engine.rk_select_texture
select_texture.restype = None
select_texture.argtypes = ( select_texture.argtypes = (
ctypes.c_uint, # slot ctypes.c_uint, # slot
ctypes.c_void_p, # texture ctypes.c_void_p) # texture
ctypes.c_void_p) # sampler
draw_triangles = _engine.rk_draw_triangles draw_triangles = _engine.rk_draw_triangles
draw_triangles.restype = None
draw_triangles.argtypes = ( draw_triangles.argtypes = (
ctypes.c_void_p,) # triangles ctypes.c_void_p,) # triangles
draw_batch = _engine.rk_draw_batch draw_batch = _engine.rk_draw_batch
draw_batch.restype = None
draw_batch.argtypes = ( draw_batch.argtypes = (
ctypes.c_void_p, # batch ctypes.c_void_p,) # batch
ctypes.c_uint, # count
ctypes.POINTER(ctypes.c_ubyte), # flags
ctypes.POINTER(ctypes.c_uint), # meshes
ctypes.POINTER(ctypes.c_void_p)) # params
unselect_texture = _engine.rk_unselect_texture unselect_texture = _engine.rk_unselect_texture
unselect_texture.restype = None
unselect_texture.argtypes = ( unselect_texture.argtypes = (
ctypes.c_uint, # slot ctypes.c_uint, # slot
ctypes.c_void_p) # texture ctypes.c_void_p) # texture
unselect_shader = _engine.rk_unselect_shader unselect_shader = _engine.rk_unselect_shader
unselect_shader.restype = None
unselect_shader.argtypes = ( unselect_shader.argtypes = (
ctypes.c_void_p,) # shader ctypes.c_void_p,) # shader
end_frame = _engine.rk_end_frame
destroy_batch = _engine.rk_destroy_batch destroy_batch = _engine.rk_destroy_batch
destroy_batch.restype = None
destroy_batch.argtypes = ( destroy_batch.argtypes = (
ctypes.c_void_p,) # batch ctypes.c_void_p,) # batch
destroy_triangles = _engine.rk_destroy_triangles destroy_triangles = _engine.rk_destroy_triangles
destroy_triangles.restype = None
destroy_triangles.argtypes = ( destroy_triangles.argtypes = (
ctypes.c_void_p,) # triangles ctypes.c_void_p,) # triangles
destroy_vertices = _engine.rk_destroy_vertices destroy_vertices = _engine.rk_destroy_vertices
destroy_vertices.restype = None
destroy_vertices.argtypes = ( destroy_vertices.argtypes = (
ctypes.c_void_p,) # vertices ctypes.c_void_p,) # vertices
destroy_texture = _engine.rk_destroy_texture destroy_texture = _engine.rk_destroy_texture
destroy_texture.restype = None
destroy_texture.argtypes = ( destroy_texture.argtypes = (
ctypes.c_void_p,) # texture ctypes.c_void_p,) # texture
destroy_shader = _engine.rk_destroy_shader destroy_shader = _engine.rk_destroy_shader
destroy_shader.restype = None
destroy_shader.argtypes = ( destroy_shader.argtypes = (
ctypes.c_void_p,) # shader ctypes.c_void_p,) # shader
@ -483,21 +535,25 @@ class Event(ctypes.Structure):
_fields_ = ('type', ctypes.c_uint), ('data', _Events) _fields_ = ('type', ctypes.c_uint), ('data', _Events)
create_events = _engine.rk_create_events create_events = _engine.rk_create_events
create_events.restype = ctypes.c_void_p create_events.restype = _handle
create_events.errcheck = _check_handle
create_events.argtypes = ( create_events.argtypes = (
ctypes.c_void_p,) # display ctypes.c_void_p,) # display
destroy_events = _engine.rk_destroy_events destroy_events = _engine.rk_destroy_events
destroy_events.restype = None
destroy_events.argtypes = ( destroy_events.argtypes = (
ctypes.c_void_p, # display ctypes.c_void_p, # display
ctypes.c_void_p) # events ctypes.c_void_p) # events
set_key_autorepeat = _engine.rk_set_key_autorepeat set_key_autorepeat = _engine.rk_set_key_autorepeat
set_key_autorepeat.restype = None
set_key_autorepeat.argtypes = ( set_key_autorepeat.argtypes = (
ctypes.c_void_p, # events ctypes.c_void_p, # events
ctypes.c_bool) # autorepeat ctypes.c_bool) # autorepeat
set_motion_acceleration = _engine.rk_set_motion_acceleration set_motion_acceleration = _engine.rk_set_motion_acceleration
set_motion_acceleration.restype = None
set_motion_acceleration.argtypes = ( set_motion_acceleration.argtypes = (
ctypes.c_void_p, # events ctypes.c_void_p, # events
ctypes.c_uint, # numerator ctypes.c_uint, # numerator

View File

@ -19,7 +19,7 @@ void rk_vec3_rotate(
rk_vec3 & ret, rk_vec3 & ret,
rk_vec3 const & vec3, rk_vec3 const & vec3,
rk_vec3 const & axis, rk_vec3 const & axis,
float const angle) { rk_float const angle) {
ret = glm::angleAxis(angle, axis) * vec3; ret = glm::angleAxis(angle, axis) * vec3;
} }
@ -33,7 +33,7 @@ void rk_vec3_mul_vec3(
void rk_mat3_rotation( void rk_mat3_rotation(
rk_mat3 & ret, rk_mat3 & ret,
rk_vec3 const & axis, rk_vec3 const & axis,
float const angle) { rk_float const angle) {
ret = glm::mat3_cast(glm::angleAxis(angle, axis)); ret = glm::mat3_cast(glm::angleAxis(angle, axis));
} }
@ -53,10 +53,10 @@ void rk_mat3_mul_mat3(
void rk_mat4_projection( void rk_mat4_projection(
rk_mat4 & ret, rk_mat4 & ret,
float hfov, rk_float hfov,
float ratio, rk_float ratio,
float near, rk_float near,
float far) { rk_float far) {
ret = glm::perspectiveRH(hfov, ratio, near, far); ret = glm::perspectiveRH(hfov, ratio, near, far);
} }
@ -70,9 +70,9 @@ void rk_mat4_lookat(
void rk_mat4_orbit( void rk_mat4_orbit(
rk_mat4 & ret, rk_mat4 & ret,
rk_vec3 const & origin, rk_vec3 const & origin,
float const yaw, rk_float const yaw,
float const pitch, rk_float const pitch,
float const distance) { rk_float const distance) {
ret = glm::translate( ret = glm::translate(
glm::lookAtRH(glm::vec3(0.f, -distance, 0.f), vec3_origin, vec3_up) * glm::lookAtRH(glm::vec3(0.f, -distance, 0.f), vec3_origin, vec3_up) *
glm::mat4(glm::angleAxis(pitch, vec3_right) * glm::angleAxis(yaw, vec3_up)), glm::mat4(glm::angleAxis(pitch, vec3_right) * glm::angleAxis(yaw, vec3_up)),
@ -83,7 +83,7 @@ void rk_mat4_mul_vec3(
rk_vec3 & ret, rk_vec3 & ret,
rk_mat4 const & a, rk_mat4 const & a,
rk_vec3 const & b, rk_vec3 const & b,
float const w) { rk_float const w) {
ret = glm::vec3(a * glm::vec4(b, w)); ret = glm::vec3(a * glm::vec4(b, w));
} }

View File

@ -26,6 +26,14 @@ typedef glm::vec4 rk_vec4;
typedef glm::mat3 rk_mat3; typedef glm::mat3 rk_mat3;
typedef glm::mat4 rk_mat4; typedef glm::mat4 rk_mat4;
#define RK_CHECK_MATH_TYPE(_t, _e, _c) static_assert(sizeof(_t) == sizeof(_e) * (_c))
RK_CHECK_MATH_TYPE(rk_vec2, float, 2);
RK_CHECK_MATH_TYPE(rk_vec3, float, 3);
RK_CHECK_MATH_TYPE(rk_vec4, float, 4);
RK_CHECK_MATH_TYPE(rk_mat3, rk_vec3, 3);
RK_CHECK_MATH_TYPE(rk_mat4, rk_vec4, 4);
#define vec3_right (rk_vec3(1.f, 0.f, 0.f)) #define vec3_right (rk_vec3(1.f, 0.f, 0.f))
#define vec3_forward (rk_vec3(0.f, 1.f, 0.f)) #define vec3_forward (rk_vec3(0.f, 1.f, 0.f))
#define vec3_up (rk_vec3(0.f, 0.f, 1.f)) #define vec3_up (rk_vec3(0.f, 0.f, 1.f))
@ -35,7 +43,7 @@ RK_EXPORT void rk_vec3_rotate(
rk_vec3 & ret, rk_vec3 & ret,
rk_vec3 const & vec3, rk_vec3 const & vec3,
rk_vec3 const & axis, rk_vec3 const & axis,
float const angle); rk_float const angle);
RK_EXPORT void rk_vec3_mul_vec3( RK_EXPORT void rk_vec3_mul_vec3(
rk_vec3 & ret, rk_vec3 & ret,
@ -45,7 +53,7 @@ RK_EXPORT void rk_vec3_mul_vec3(
RK_EXPORT void rk_mat3_rotation( RK_EXPORT void rk_mat3_rotation(
rk_mat3 & ret, rk_mat3 & ret,
rk_vec3 const & axis, rk_vec3 const & axis,
float const angle); rk_float const angle);
RK_EXPORT void rk_mat3_mul_vec3( RK_EXPORT void rk_mat3_mul_vec3(
rk_vec3 & ret, rk_vec3 & ret,
@ -59,10 +67,10 @@ RK_EXPORT void rk_mat3_mul_mat3(
RK_EXPORT void rk_mat4_projection( RK_EXPORT void rk_mat4_projection(
rk_mat4 & ret, rk_mat4 & ret,
float hfov, rk_float hfov,
float ratio, rk_float ratio,
float near, rk_float near,
float far); rk_float far);
RK_EXPORT void rk_mat4_lookat( RK_EXPORT void rk_mat4_lookat(
rk_mat4 & ret, rk_mat4 & ret,
@ -72,15 +80,15 @@ RK_EXPORT void rk_mat4_lookat(
RK_EXPORT void rk_mat4_orbit( RK_EXPORT void rk_mat4_orbit(
rk_mat4 & ret, rk_mat4 & ret,
rk_vec3 const & origin, rk_vec3 const & origin,
float const yaw, rk_float const yaw,
float const pitch, rk_float const pitch,
float const distance); rk_float const distance);
RK_EXPORT void rk_mat4_mul_vec3( RK_EXPORT void rk_mat4_mul_vec3(
rk_vec3 & ret, rk_vec3 & ret,
rk_mat4 const & a, rk_mat4 const & a,
rk_vec3 const & b, rk_vec3 const & b,
float const w); rk_float const w);
RK_EXPORT void rk_mat4_mul_vec4( RK_EXPORT void rk_mat4_mul_vec4(
rk_vec4 & ret, rk_vec4 & ret,

View File

@ -27,14 +27,18 @@ typedef rk_handle_t rk_triangles_t;
typedef rk_handle_t rk_vertices_t; typedef rk_handle_t rk_vertices_t;
typedef rk_handle_t rk_batch_t; typedef rk_handle_t rk_batch_t;
enum rk_texture_format : rk_uint { typedef rk_uint rk_texture_format;
enum : rk_texture_format {
RK_TEXTURE_FORMAT_SRGB8_A8 = 0, RK_TEXTURE_FORMAT_SRGB8_A8 = 0,
RK_TEXTURE_FORMAT_RGBA8 = 1, RK_TEXTURE_FORMAT_RGBA8 = 1,
RK_TEXTURE_FORMAT_RGB10_A2 = 2, RK_TEXTURE_FORMAT_RGB10_A2 = 2,
RK_TEXTURE_FORMAT_FLOAT_32 = 3 RK_TEXTURE_FORMAT_FLOAT_32 = 3
}; };
enum rk_texture_flags : rk_uint { typedef rk_uint rk_texture_flags;
enum : rk_texture_flags {
RK_TEXTURE_FLAG_3D = RK_FLAG(0), RK_TEXTURE_FLAG_3D = RK_FLAG(0),
RK_TEXTURE_FLAG_MIPMAPS = RK_FLAG(1), RK_TEXTURE_FLAG_MIPMAPS = RK_FLAG(1),
RK_TEXTURE_FLAG_MIN_NEAREST = 0, RK_TEXTURE_FLAG_MIN_NEAREST = 0,
@ -43,41 +47,40 @@ enum rk_texture_flags : rk_uint {
RK_TEXTURE_FLAG_MAG_LINEAR = RK_FLAG(3), RK_TEXTURE_FLAG_MAG_LINEAR = RK_FLAG(3),
}; };
enum rk_vertex_format : rk_ubyte { typedef rk_ubyte rk_vertex_format;
enum : rk_vertex_format {
RK_VERTEX_FORMAT_VEC3_FLOAT = 1, RK_VERTEX_FORMAT_VEC3_FLOAT = 1,
RK_VERTEX_FORMAT_VEC3_INT10 = 2, RK_VERTEX_FORMAT_VEC3_SHORT = 2,
RK_VERTEX_FORMAT_VEC3_UINT10 = 3 RK_VERTEX_FORMAT_VEC3_INT10 = 3,
RK_VERTEX_FORMAT_VEC3_UINT10 = 4,
RK_VERTEX_FORMAT_MAT3_FLOAT = 5,
RK_VERTEX_FORMAT_MAT3_INT10 = 6,
RK_VERTEX_FORMAT_NORMALIZE = RK_FLAG(7),
RK_VERTEX_FORMAT_MASK = RK_VERTEX_FORMAT_NORMALIZE - 1
}; };
enum : rk_ubyte { RK_VERTEX_FORMAT_NORMALIZE = RK_FLAG(7) }; typedef rk_ubyte rk_instance_flags;
enum : rk_ubyte { RK_VERTEX_FORMAT_MASK = RK_VERTEX_FORMAT_NORMALIZE - 1 };
enum rk_param_format : rk_ubyte { enum : rk_instance_flags {
RK_PARAM_FORMAT_VEC3_FLOAT = 1,
RK_PARAM_FORMAT_VEC3_SHORT = 2,
RK_PARAM_FORMAT_VEC3_INT10 = 3,
RK_PARAM_FORMAT_MAT3_FLOAT = 4,
RK_PARAM_FORMAT_MAT3_INT10 = 5
};
enum : rk_ubyte { RK_PARAM_FORMAT_NORMALIZE = RK_FLAG(7) };
enum : rk_ubyte { RK_PARAM_FORMAT_MASK = RK_PARAM_FORMAT_NORMALIZE - 1 };
enum rk_instance_flags : rk_ubyte {
RK_INSTANCE_FLAG_SPAWNED = RK_FLAG(0), RK_INSTANCE_FLAG_SPAWNED = RK_FLAG(0),
RK_INSTANCE_FLAG_VISIBLE = RK_FLAG(1) RK_INSTANCE_FLAG_VISIBLE = RK_FLAG(1),
RK_INSTANCE_FLAGS_SPAWNED_VISIBLE = RK_INSTANCE_FLAG_SPAWNED | RK_INSTANCE_FLAG_VISIBLE
}; };
enum : rk_ubyte { RK_INSTANCE_FLAGS_SPAWNED_VISIBLE = RK_INSTANCE_FLAG_SPAWNED | RK_INSTANCE_FLAG_VISIBLE }; enum : rk_uint {
RK_BATCH_MAX_SIZE = 65536
};
enum : rk_uint { RK_BATCH_MAX_SIZE = 65536 }; typedef rk_ushort rk_vertex_index;
typedef rk_ushort rk_mesh_index;
typedef rk_ushort rk_instance_index;
typedef rk_uint rk_vertex_input;
typedef rk_uint rk_vertex_output;
union rk_mesh { struct rk_mesh {
rk_uint packed; rk_uint base_index;
struct { rk_uint ntriangles;
rk_ushort base_index;
rk_ushort ntriangles;
};
}; };
RK_EXPORT void rk_render_initialize( RK_EXPORT void rk_render_initialize(
@ -85,19 +88,19 @@ RK_EXPORT void rk_render_initialize(
RK_EXPORT void rk_render_terminate(); RK_EXPORT void rk_render_terminate();
RK_EXPORT rk_shader_t rk_load_shader( RK_EXPORT rk_shader_t rk_create_shader(
rk_uint const vert_nlines, rk_uint const vert_nlines,
char const ** const vert_lines, rk_char const * const * vert_lines,
rk_uint const frag_nlines, rk_uint const frag_nlines,
char const ** const frag_lines); rk_char const * const * frag_lines);
RK_EXPORT rk_input_t rk_resolve_input( RK_EXPORT rk_input_t rk_resolve_input(
rk_shader_t shader, rk_shader_t shader,
char const * name); rk_char const * name);
RK_EXPORT rk_param_t rk_resolve_param( RK_EXPORT rk_param_t rk_resolve_param(
rk_shader_t shader, rk_shader_t shader,
char const * name); rk_char const * name);
RK_EXPORT rk_texture_t rk_create_texture( RK_EXPORT rk_texture_t rk_create_texture(
rk_texture_format format, rk_texture_format format,
@ -116,15 +119,26 @@ RK_EXPORT rk_vertices_t rk_create_vertices(
rk_uint nvertices, rk_uint nvertices,
rk_ubyte const * vertices, rk_ubyte const * vertices,
rk_uint nindices, rk_uint nindices,
rk_ushort const * indices); rk_vertex_index const * indices,
rk_uint nmeshes,
rk_mesh const * meshes);
RK_EXPORT rk_batch_t rk_create_batch( RK_EXPORT rk_batch_t rk_create_batch(
rk_vertices_t vertices, rk_vertices_t vertices,
rk_uint max_size, rk_uint max_size,
rk_uint max_meshes, rk_vertex_format const * params_format);
rk_param_format const * params_format);
RK_EXPORT void rk_begin_frame(); RK_EXPORT void rk_fill_batch(
rk_batch_t batch,
rk_uint count,
rk_instance_flags const * flags,
rk_mesh_index const * meshes,
rk_vertex_input const * const * params);
RK_EXPORT void rk_clear_buffer(
rk_bool pixels,
rk_bool depth,
rk_bool stencil);
RK_EXPORT void rk_select_shader( RK_EXPORT void rk_select_shader(
rk_shader_t _shader); rk_shader_t _shader);
@ -155,18 +169,13 @@ RK_EXPORT void rk_set_param_mat3(
RK_EXPORT void rk_select_texture( RK_EXPORT void rk_select_texture(
rk_uint slot, rk_uint slot,
rk_texture_t texture, rk_texture_t texture);
rk_input_t sampler);
RK_EXPORT void rk_draw_triangles( RK_EXPORT void rk_draw_triangles(
rk_triangles_t triangles); rk_triangles_t triangles);
RK_EXPORT void rk_draw_batch( RK_EXPORT void rk_draw_batch(
rk_batch_t batch, rk_batch_t batch);
rk_uint size,
rk_instance_flags const * flags,
rk_mesh const * meshes,
rk_ubyte const ** params);
RK_EXPORT void rk_unselect_texture( RK_EXPORT void rk_unselect_texture(
rk_uint slot, rk_uint slot,
@ -175,8 +184,6 @@ RK_EXPORT void rk_unselect_texture(
RK_EXPORT void rk_unselect_shader( RK_EXPORT void rk_unselect_shader(
rk_shader_t shader); rk_shader_t shader);
RK_EXPORT void rk_end_frame();
RK_EXPORT void rk_destroy_batch( RK_EXPORT void rk_destroy_batch(
rk_batch_t batch); rk_batch_t batch);

File diff suppressed because it is too large Load Diff

View File

@ -16,11 +16,13 @@
#ifndef _RK_ENGINE_RENDER_OPENGLES_H #ifndef _RK_ENGINE_RENDER_OPENGLES_H
#define _RK_ENGINE_RENDER_OPENGLES_H #define _RK_ENGINE_RENDER_OPENGLES_H
#include "../types.hpp" #include "../render.hpp"
#include <GLES3/gl32.h> #include <GLES3/gl32.h>
#include <GLES3/gl3ext.h> #include <GLES3/gl3ext.h>
#include <GLES3/gl3platform.h> #include <GLES3/gl3platform.h>
static_assert(sizeof(rk_vertex_output) == 4);
struct rk_shader { struct rk_shader {
GLuint vertex; GLuint vertex;
GLuint fragment; GLuint fragment;
@ -41,9 +43,13 @@ struct rk_triangles {
struct rk_vertices { struct rk_vertices {
unsigned nvertices; unsigned nvertices;
unsigned nindices; unsigned nindices;
unsigned nmeshes;
rk_vertex_format * format; rk_vertex_format * format;
rk_ubyte * vertices; rk_ubyte * vertices;
rk_ushort * indices; rk_vertex_index * indices;
rk_mesh * meshes;
GLuint vertices_buffer;
GLuint indices_buffer;
}; };
struct rk_command { struct rk_command {
@ -54,57 +60,51 @@ struct rk_command {
GLuint base_instance; GLuint base_instance;
}; };
struct rk_vec3_float {
float x;
float y;
float z;
};
struct rk_vec3_short {
rk_short x;
rk_short y;
rk_short z;
rk_short pad;
};
typedef rk_int rk_vec3_int10;
typedef rk_uint rk_vec3_uint10;
struct rk_mat3_float {
rk_vec3_float x;
rk_vec3_float y;
rk_vec3_float z;
};
struct rk_mat3_int10 {
rk_vec3_int10 x;
rk_vec3_int10 y;
rk_vec3_int10 z;
};
typedef void (*rk_packer)( typedef void (*rk_packer)(
unsigned const, // count unsigned const, // count
rk_ushort const * const, // indices rk_instance_index const * const __restrict, // indices
rk_ubyte *, // dst rk_vertex_output * __restrict, // dst
rk_ubyte const * const); // src rk_vertex_input const * const __restrict); // src
struct rk_parameter { struct rk_parameter {
mutable bool dirty;
unsigned binding; unsigned binding;
unsigned offset; unsigned offset;
unsigned size; unsigned src_size;
unsigned src_len;
unsigned dst_size;
unsigned dst_len;
rk_vertex_input * source;
rk_packer packer; rk_packer packer;
}; };
struct rk_bucket {
unsigned size;
unsigned count;
rk_instance_index * indices;
};
enum rk_batch_state {
RK_BATCH_STATE_EMPTY = 0,
RK_BATCH_STATE_FILLED = 1,
RK_BATCH_STATE_SORTED = 2,
RK_BATCH_STATE_PACKED = 3
};
struct rk_batch { struct rk_batch {
mutable rk_batch_state state;
mutable unsigned count;
mutable unsigned ninstances;
mutable unsigned ncommands;
unsigned max_size; unsigned max_size;
unsigned max_meshes;
unsigned nparams; unsigned nparams;
rk_ushort * indices; rk_vertices const * vertices;
rk_instance_flags * flags;
rk_mesh_index * meshes;
rk_instance_index * indices;
rk_command * commands; rk_command * commands;
rk_parameter * params; rk_parameter * params;
GLuint vertex_array; GLuint vertex_array;
GLuint vertices_buffer;
GLuint indices_buffer;
GLuint commands_buffer; GLuint commands_buffer;
GLuint params_buffer; GLuint params_buffer;
}; };

View File

@ -20,6 +20,11 @@
#include <cstdint> #include <cstdint>
#define RK_EXPORT extern "C" #define RK_EXPORT extern "C"
#define RK_HOT gnu::hot
#define RK_FLATTEN gnu::flatten
#define RK_UNROLLED gnu::optimize("unroll-loops")
#define RK_FAST gnu::optimize("Ofast")
#define RK_INVALID_HANDLE nullptr
#define RK_FLAG(_bit) (1 << (_bit)) #define RK_FLAG(_bit) (1 << (_bit))
typedef bool rk_bool; typedef bool rk_bool;
@ -33,7 +38,33 @@ typedef int32_t rk_int;
typedef uint32_t rk_uint; typedef uint32_t rk_uint;
typedef int64_t rk_long; typedef int64_t rk_long;
typedef uint64_t rk_ulong; typedef uint64_t rk_ulong;
typedef __int128 rk_llong;
typedef unsigned __int128 rk_ullong;
typedef float rk_float;
typedef void * rk_handle_t; typedef void * rk_handle_t;
static_assert(sizeof(rk_char) == 1);
static_assert(sizeof(rk_wchar) == 4);
static_assert(sizeof(rk_float) == 4);
#pragma pack(push, 4)
template<bool _signed, unsigned _cols>
struct rk_packed {
};
template<unsigned _cols>
struct alignas(alignof(rk_int)) rk_packed<true, _cols> {
typedef rk_int type;
rk_int packed;
};
template<unsigned _cols>
struct alignas(alignof(rk_uint)) rk_packed<false, _cols> {
typedef rk_uint type;
rk_uint packed;
};
#pragma pack(pop)
#endif // _RK_ENGINE_TYPES_H #endif // _RK_ENGINE_TYPES_H

102
cpp/utils/cmp_memcpy.hpp Normal file
View File

@ -0,0 +1,102 @@
// Copyright (C) 2023 RozK
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef RK_ENGINE_CMP_MEMCPY_H
#define RK_ENGINE_CMP_MEMCPY_H
#include "../types.hpp"
template<typename _small>
[[RK_FAST]]
inline bool _rk_cmp_memcpy_small(
_small * __restrict dst,
_small const * __restrict src,
unsigned count) {
_small cmp = 0;
do {
cmp |= *dst ^ *src;
*dst++ = *src++;
} while(--count > 0);
return (cmp != 0);
}
template<typename _big, typename _small>
[[RK_FAST, RK_FLATTEN]]
inline bool _rk_cmp_memcpy_big(
_small * const __restrict _dst,
_small const * const __restrict _src,
unsigned const _count) {
unsigned const ratio = sizeof(_big) / sizeof(_small);
unsigned big_count = _count / ratio;
unsigned const small_count = _count % ratio;
_big * dst = reinterpret_cast<_big *>(_dst);
_big const * src = reinterpret_cast<_big const *>(_src);
_big cmp = 0;
do {
cmp |= *dst ^ *src;
*dst++ = *src++;
} while(--big_count > 0);
bool modified = (cmp != 0);
if (small_count) {
modified |= _rk_cmp_memcpy_small<_small>(
reinterpret_cast<_small *>(dst), reinterpret_cast<_small const *>(src), small_count);
}
return modified;
}
#ifdef RK_CMP_MEMCPY_UNALIGNED
#define _rk_count_and_alignment(_t) (count >= (sizeof(_t) / sizeof(_small)))
#else
#define _rk_count_and_alignment(_t) ((count >= (sizeof(_t) / sizeof(_small))) && !(alignment % sizeof(_t)))
#endif
template<typename _small>
[[RK_HOT, RK_FAST, RK_FLATTEN]]
bool rk_cmp_memcpy(
_small * const __restrict _dst,
_small const * const __restrict _src,
unsigned const count) {
#ifndef RK_CMP_MEMCPY_UNALIGNED
unsigned const alignment = reinterpret_cast<uintptr_t>(_dst) | reinterpret_cast<uintptr_t const>(_src);
#endif
if (sizeof(_small) < sizeof(rk_ullong)) {
if (_rk_count_and_alignment(rk_ullong)) {
return _rk_cmp_memcpy_big<rk_ullong, _small>(_dst, _src, count);
}
}
if (sizeof(_small) < sizeof(rk_ulong)) {
if (_rk_count_and_alignment(rk_ulong)) {
return _rk_cmp_memcpy_big<rk_ulong, _small>(_dst, _src, count);
}
}
if (sizeof(_small) < sizeof(rk_uint)) {
if (_rk_count_and_alignment(rk_uint)) {
return _rk_cmp_memcpy_big<rk_uint, _small>(_dst, _src, count);
}
}
if (sizeof(_small) < sizeof(rk_ushort)) {
if (_rk_count_and_alignment(rk_ushort)) {
return _rk_cmp_memcpy_big<rk_ushort, _small>(_dst, _src, count);
}
}
if (count) {
return _rk_cmp_memcpy_small<_small>(_dst, _src, count);
}
return false;
}
#undef _rk_count_and_alignment
#endif // RK_ENGINE_CMP_MEMCPY_H

258
cpp/utils/vertex_format.hpp Normal file
View File

@ -0,0 +1,258 @@
// Copyright (C) 2023 RozK
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef RK_ENGINE_VERTEX_FORMAT_H
#define RK_ENGINE_VERTEX_FORMAT_H
#include "../render.hpp"
#include <limits>
namespace rk_vertex {
#pragma pack(push, 1)
template<typename _type>
struct alignas(alignof(_type)) rk_input {
_type input;
};
template<typename _type, typename _input, bool _signed, bool _normalized>
struct alignas(alignof(_type)) rk_output {
_type output;
[[RK_FAST]]
inline void convert(
rk_input<_input> const & __restrict src) {
output = static_cast<_type>(src.input);
}
};
template<typename _type, bool _signed>
struct alignas(alignof(_type)) rk_output<_type, rk_float, _signed, true> {
_type output;
[[RK_FAST]]
inline void convert(
rk_input<rk_float> const & __restrict src) {
enum : _type { max = std::numeric_limits<_type>::max() };
output = static_cast<_type>(src.input * static_cast<float>(max));
}
};
#pragma pack(4)
template<typename _input, unsigned _cols>
struct alignas(4) rk_input_row {
rk_input<_input> input_col[_cols];
};
template<typename _output, typename _input, unsigned _cols, bool _signed, bool _normalized>
struct alignas(4) rk_output_row {
rk_output<_output, _input, _signed, _normalized> output_col[_cols];
[[RK_FAST, RK_FLATTEN, RK_UNROLLED]]
inline void convert(
rk_input_row<_input, _cols> const & __restrict src) {
for (unsigned col = 0; col < _cols; ++col) {
output_col[col].convert(src.input_col[col]);
}
}
};
template<typename _output, unsigned _cols, bool _signed, bool _normalized>
struct alignas(4) rk_output_row<_output, _output, _cols, _signed, _normalized> {
rk_output<_output, _output, _signed, _normalized> output_col[_cols];
[[RK_FAST]]
inline void convert(
rk_input_row<_output, _cols> const & __restrict src) {
static_assert(sizeof(output_col) == sizeof(src.input_col));
rk_output<_output, _output, _signed, _normalized> const * const input_col =
reinterpret_cast<rk_output<_output, _output, _signed, _normalized> const *>(src.input_col);
*output_col = *input_col;
}
};
template<typename _input, unsigned _cols, bool _signed, bool _normalized>
struct alignas(4) rk_output_row<rk_packed<_signed, _cols>, _input, _cols, _signed, _normalized> {
rk_output<rk_packed<_signed, _cols>, _input, _signed, _normalized> output_cols;
[[RK_FAST, RK_FLATTEN]]
inline void convert(
rk_input_row<_input, _cols> const & __restrict src) {
output_cols.convert(src);
}
};
template<typename _input, unsigned _cols, unsigned _rows>
struct alignas(4) rk_input_format {
rk_input_row<_input, _cols> input_row[_rows];
};
template<typename _output, typename _input, unsigned _cols, unsigned _rows, bool _signed, bool _normalized>
struct alignas(4) rk_output_format {
rk_output_row<_output, _input, _cols, _signed, _normalized> output_row[_rows];
[[RK_FAST, RK_FLATTEN, RK_UNROLLED]]
inline void convert(
rk_input_format<_input, _cols, _rows> const & __restrict src) {
for (unsigned row = 0; row < _rows; ++row) {
output_row[row].convert(src.input_row[row]);
}
}
};
template<typename _output, unsigned _cols, unsigned _rows, bool _signed, bool _normalized>
struct alignas(4) rk_output_format<_output, _output, _cols, _rows, _signed, _normalized> {
rk_output_row<_output, _output, _cols, _signed, _normalized> output_row[_rows];
[[RK_FAST]]
inline void convert(
rk_input_format<_output, _cols, _rows> const & __restrict src) {
static_assert(sizeof(output_row) == sizeof(src.input_row));
rk_output_row<_output, _output, _cols, _signed, _normalized> const * const input_row =
reinterpret_cast<rk_output_row<_output, _output, _cols, _signed, _normalized> const *>(src.input_row);
*output_row = *input_row;
}
};
template<typename _input, bool _signed, bool _normalized>
struct alignas(alignof(rk_packed<_signed, 3>)) rk_output<rk_packed<_signed, 3>, _input, _signed, _normalized> {
rk_packed<_signed, 3> output;
[[RK_FAST]]
inline void convert(
rk_input_row<_input, 3> const & __restrict src) {
typedef typename rk_packed<_signed, 3>::type packed_type;
output.packed =
((static_cast<packed_type>(src.input_col[0].input) & 1023)) |
((static_cast<packed_type>(src.input_col[1].input) & 1023) << 10) |
((static_cast<packed_type>(src.input_col[2].input) & 1023) << 20);
}
};
template<typename _input, bool _signed, bool _normalized>
struct alignas(alignof(rk_packed<_signed, 4>)) rk_output<rk_packed<_signed, 4>, _input, _signed, _normalized> {
rk_packed<_signed, 4> output;
[[RK_FAST]]
inline void convert(
rk_input_row<_input, 4> const & __restrict src) {
typedef typename rk_packed<_signed, 4>::type packed_type;
output.packed =
((static_cast<packed_type>(src.input_col[0].input) & 1023)) |
((static_cast<packed_type>(src.input_col[1].input) & 1023) << 10) |
((static_cast<packed_type>(src.input_col[2].input) & 1023) << 20) |
((static_cast<packed_type>(src.input_col[3].input) & 3) << 30);
}
};
template<>
struct alignas(alignof(rk_packed<true, 3>)) rk_output<rk_packed<true, 3>, rk_float, true, true> {
rk_packed<true, 3> output;
[[RK_FAST]]
inline void convert(
rk_input_row<rk_float, 3> const & __restrict src) {
output.packed =
((static_cast<rk_int>(src.input_col[0].input * 511.f) & 1023)) |
((static_cast<rk_int>(src.input_col[1].input * 511.f) & 1023) << 10) |
((static_cast<rk_int>(src.input_col[2].input * 511.f) & 1023) << 20);
}
};
template<>
struct alignas(alignof(rk_packed<true, 4>)) rk_output<rk_packed<true, 4>, rk_float, true, true> {
rk_packed<true, 4> output;
[[RK_FAST]]
inline void convert(
rk_input_row<rk_float, 4> const & __restrict src) {
output.packed =
((static_cast<rk_uint>(src.input_col[0].input * 511.f) & 1023)) |
((static_cast<rk_uint>(src.input_col[1].input * 511.f) & 1023) << 10) |
((static_cast<rk_uint>(src.input_col[2].input * 511.f) & 1023) << 20) |
((static_cast<rk_uint>(src.input_col[3].input) & 3) << 30);
}
};
#pragma pack(pop)
template<typename _output, typename _input, unsigned _cols, unsigned _rows, bool _signed, bool _normalized>
struct rk_format {
typedef rk_input<_input> input;
typedef rk_output<_output, input, _signed, _normalized> output;
typedef rk_input_row<_input, _cols> input_row;
typedef rk_output_row<_output, _input, _cols, _signed, _normalized> output_row;
typedef rk_input_format<_input, _cols, _rows> input_format;
typedef rk_output_format<_output, _input, _cols, _rows, _signed, _normalized> output_format;
static_assert(sizeof(input) == sizeof(_input));
static_assert(sizeof(output) == sizeof(_output));
static_assert((sizeof(input_row) % sizeof(rk_vertex_input)) == 0);
static_assert((sizeof(output_row) % sizeof(rk_vertex_output)) == 0);
static_assert((sizeof(input_format) % sizeof(rk_vertex_input)) == 0);
static_assert((sizeof(output_format) % sizeof(rk_vertex_output)) == 0);
static unsigned get_input_size() {
return sizeof(input_format);
}
static unsigned get_output_size() {
return sizeof(output_format);
}
static unsigned get_output_offset(unsigned const index) {
return index * sizeof(output_row);
}
[[RK_FAST, RK_FLATTEN]]
inline static void convert(
output_format & __restrict dst,
input_format const & __restrict src) {
dst.convert(src);
}
[[RK_HOT, RK_FAST, RK_FLATTEN]]
static void param_packer(
unsigned const count,
rk_instance_index const * const __restrict indices,
rk_vertex_output * __restrict _dst,
rk_vertex_input const * const __restrict _src) {
rk_instance_index const * const last_index = indices + count;
output_format * __restrict dst = reinterpret_cast<output_format *>(_dst);
input_format const * const __restrict src = reinterpret_cast<input_format const *>(_src);
for (rk_instance_index const * __restrict index = indices; index < last_index; ++index, ++dst) {
dst->convert(src[*index]);
}
}
};
} // namepace rk_vertex
typedef rk_vertex::rk_format<rk_float, rk_float, 3, 1, true, false> rk_vec3_float;
typedef rk_vertex::rk_format<rk_short, rk_float, 3, 1, true, false> rk_vec3_short;
typedef rk_vertex::rk_format<rk_short, rk_float, 3, 1, true, true> rk_vec3_short_norm;
typedef rk_vertex::rk_format<rk_packed<true, 3>, rk_float, 3, 1, true, false> rk_vec3_int10;
typedef rk_vertex::rk_format<rk_packed<true, 3>, rk_float, 3, 1, true, true> rk_vec3_int10_norm;
typedef rk_vertex::rk_format<rk_packed<false, 3>, rk_float, 3, 1, false, false> rk_vec3_uint10;
typedef rk_vertex::rk_format<rk_packed<false, 3>, rk_float, 3, 1, false, true> rk_vec3_uint10_norm;
typedef rk_vertex::rk_format<rk_float, rk_float, 3, 3, true, false> rk_mat3_float;
typedef rk_vertex::rk_format<rk_packed<true, 3>, rk_float, 3, 3, true, false> rk_mat3_int10;
typedef rk_vertex::rk_format<rk_packed<true, 3>, rk_float, 3, 3, true, true> rk_mat3_int10_norm;
#endif // RK_ENGINE_VERTEX_FORMAT_H