From 361f586dfe56c7f395b14d816855abff08148692 Mon Sep 17 00:00:00 2001 From: Abdelilah-Majid Date: Tue, 4 Jan 2022 15:16:36 +0100 Subject: [PATCH] adding simd sse and sse2 versions of drawmodelex and drawmesh and also the math functions that thees two function uses this should improve the performance slitly --- src/Makefile | 9 +- src/raylib.h | 3 + src/raymath.h | 318 +++++++++++++++++++++++++++++++++++++++++++ src/rmodels.c | 365 +++++++++++++++++++++++++++++++++++++++++++++++++- src/simd.h | 94 +++++++++++++ 5 files changed, 786 insertions(+), 3 deletions(-) create mode 100644 src/simd.h diff --git a/src/Makefile b/src/Makefile index 4ecad6f8b..0417e0a6b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -199,9 +199,9 @@ endif # Define raylib graphics api depending on selected platform ifeq ($(PLATFORM),PLATFORM_DESKTOP) # By default use OpenGL 3.3 on desktop platforms - GRAPHICS ?= GRAPHICS_API_OPENGL_33 + #GRAPHICS ?= GRAPHICS_API_OPENGL_33 #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 - #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 + GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 endif ifeq ($(PLATFORM),PLATFORM_RPI) # On RPI OpenGL ES 2.0 must be used @@ -279,6 +279,11 @@ endif # -fno-strict-aliasing jar_xm.h does shady stuff (breaks strict aliasing) CFLAGS = -Wall -D_DEFAULT_SOURCE -D$(PLATFORM) -D$(GRAPHICS) -Wno-missing-braces -Werror=pointer-arith -fno-strict-aliasing $(CUSTOM_CFLAGS) +simd_flags = -Dsse_sse2 -msse -msse2 #flags for simd sse and sse2 +#simd_flags = + +CFLAGS += $(simd_flags) + ifneq ($(RAYLIB_CONFIG_FLAGS), NONE) CFLAGS += -DEXTERNAL_CONFIG_FLAGS $(RAYLIB_CONFIG_FLAGS) endif diff --git a/src/raylib.h b/src/raylib.h index 3805ba349..4224b94df 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -79,6 +79,7 @@ #define RAYLIB_H #include // Required for: va_list - Only used by TraceLogCallback +#include #define RAYLIB_VERSION "4.1-dev" @@ -1410,6 +1411,7 @@ RLAPI BoundingBox GetModelBoundingBox(Model model); // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters +RLAPI void DrawModelEx_simd(Model model[], Vector3_simd position, Vector3_simd rotationAxis, __simd_f rotationAngle, Vector3_simd scale, Color_float_simd tint);// Draw a model with extended parameters using sse and sse2 simd instruction set RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) @@ -1422,6 +1424,7 @@ RLAPI void UploadMesh(Mesh *mesh, bool dynamic); RLAPI void UpdateMeshBuffer(Mesh mesh, int index, void *data, int dataSize, int offset); // Update mesh vertex data in GPU for a specific buffer index RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform +RLAPI void DrawMesh_simd(Mesh mesh, Material material, Matrix transform);// Draw a 3d mesh with material and transform in simd RLAPI void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits diff --git a/src/raymath.h b/src/raymath.h index 9b86b2936..c63716c18 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -47,6 +47,9 @@ #ifndef RAYMATH_H #define RAYMATH_H + + + #if defined(RAYMATH_IMPLEMENTATION) && defined(RAYMATH_STATIC_INLINE) #error "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_STATIC_INLINE is contradictory" #endif @@ -154,7 +157,19 @@ typedef struct float16 { float v[16]; } float16; + + +//color structs +#if !defined(RL_COLOR_TYPE) +typedef struct Color { + unsigned char r, g, b, a; +}Color; +#define RL_COLOR_TYPE +#endif + + #include // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), fminf(), fmaxf(), fabs() +#include //---------------------------------------------------------------------------------- // Module Functions Definition - Utils math @@ -1847,4 +1862,307 @@ RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat) return result; } + +//simd math functions + + +RMAPI Color_float_simd Color_to_Color_float_simd(Color color[]){ + + Color_float_simd result = {0}; + + for(unsigned int i=0; i < __simd_32_size; i++){ + ((float*)&result.r)[i] = color[i].r; + ((float*)&result.g)[i] = color[i].g; + ((float*)&result.b)[i] = color[i].b; + ((float*)&result.a)[i] = color[i].a; + } + + return result; +} + +RMAPI Color *Color_float_simd_to_Color(Color_float_simd color_simd){ + + Color *result = malloc(sizeof(Color) * __simd_32_size); + + for(unsigned int i=0; i < __simd_32_size; i++){ + + result[i].r = ((float*)&color_simd.r)[i]; + result[i].g = ((float*)&color_simd.g)[i]; + result[i].b = ((float*)&color_simd.b)[i]; + result[i].a = ((float*)&color_simd.a)[i]; + + } + + return result; +} + + +RMAPI Matrix_simd Matrix_to_Matrix_simd(Matrix matrix[]){ + + Matrix_simd result = {0}; + + for(unsigned int i=0; i < __simd_32_size; i++){ + + ((float*)&result.m0)[i] = matrix[i].m0; + ((float*)&result.m1)[i] = matrix[i].m1; + ((float*)&result.m2)[i] = matrix[i].m2; + ((float*)&result.m3)[i] = matrix[i].m3; + ((float*)&result.m4)[i] = matrix[i].m4; + ((float*)&result.m5)[i] = matrix[i].m5; + ((float*)&result.m6)[i] = matrix[i].m6; + ((float*)&result.m7)[i] = matrix[i].m7; + ((float*)&result.m8)[i] = matrix[i].m8; + ((float*)&result.m9)[i] = matrix[i].m9; + ((float*)&result.m10)[i] = matrix[i].m10; + ((float*)&result.m11)[i] = matrix[i].m11; + ((float*)&result.m12)[i] = matrix[i].m12; + ((float*)&result.m13)[i] = matrix[i].m13; + ((float*)&result.m14)[i] = matrix[i].m14; + ((float*)&result.m15)[i] = matrix[i].m15; + + } + + return result; + +} + +RMAPI Matrix *Matrix_simd_to_Matrix(Matrix_simd matrix_simd){ + + Matrix *result = malloc(sizeof(Matrix) * __simd_32_size); + + for(unsigned int i=0; i < __simd_32_size; i++){ + + result[i].m0 = ((float*)&matrix_simd.m0)[i]; + result[i].m1 = ((float*)&matrix_simd.m1)[i]; + result[i].m2 = ((float*)&matrix_simd.m2)[i]; + result[i].m3 = ((float*)&matrix_simd.m3)[i]; + result[i].m4 = ((float*)&matrix_simd.m4)[i]; + result[i].m5 = ((float*)&matrix_simd.m5)[i]; + result[i].m6 = ((float*)&matrix_simd.m6)[i]; + result[i].m7 = ((float*)&matrix_simd.m7)[i]; + result[i].m8 = ((float*)&matrix_simd.m8)[i]; + result[i].m9 = ((float*)&matrix_simd.m9)[i]; + result[i].m10 = ((float*)&matrix_simd.m10)[i]; + result[i].m11 = ((float*)&matrix_simd.m11)[i]; + result[i].m12 = ((float*)&matrix_simd.m12)[i]; + result[i].m13 = ((float*)&matrix_simd.m13)[i]; + result[i].m14 = ((float*)&matrix_simd.m14)[i]; + result[i].m15 = ((float*)&matrix_simd.m15)[i]; + + } + + return result; + +} + + + +RMAPI Matrix_simd MatrixTranslate_simd(__simd_f x, __simd_f y, __simd_f z) +{ + Matrix_simd result = { __simd_f_set_ps1(1.0f), __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), x, + __simd_f_set_ps1(0.0f), __simd_f_set_ps1(1.0f), __simd_f_set_ps1(0.0f), y, + __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), __simd_f_set_ps1(1.0f), z, + __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), __simd_f_set_ps1(1.0f) }; + + return result; +} + + + + +RMAPI Matrix_simd MatrixScale_simd(__simd_f x, __simd_f y, __simd_f z) +{ + + + + Matrix_simd result = { x, __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), + __simd_f_set_ps1(0.0f), y, __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), + __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), z, __simd_f_set_ps1(0.0f), + __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), __simd_f_set_ps1(0.0f), __simd_f_set_ps1(1.0f) }; + + /* + Matrix_simd result = {0}; + for(unsigned int i=0; i < arr_size; i++){ + ((float*)&result.m0)[i] = x[i]; + ((float*)&result.m5)[i] = y[i]; + ((float*)&result.m10)[i] = z[i]; + } + + result.m1 = __simd_f_set_ps1(0.0f); + result.m2 = __simd_f_set_ps1(0.0f); + result.m3 = __simd_f_set_ps1(0.0f); + result.m4 = __simd_f_set_ps1(0.0f); + result.m6 = __simd_f_set_ps1(0.0f); + result.m7 = __simd_f_set_ps1(0.0f); + result.m8 = __simd_f_set_ps1(0.0f); + result.m9 = __simd_f_set_ps1(0.0f); + result.m11 = __simd_f_set_ps1(0.0f); + result.m12 = __simd_f_set_ps1(0.0f); + result.m13 = __simd_f_set_ps1(0.0f); + result.m14 = __simd_f_set_ps1(0.0f); + result.m15 = __simd_f_set_ps1(1.0f); + + */ + return result; +} + + +RMAPI Matrix_simd MatrixRotate_simd(Vector3_simd axis, __simd_f angle) +{ + Matrix_simd result = { 0 }; + + __simd_f x = axis.x, y = axis.y, z = axis.z; + + __simd_f lengthSquared = __simd_f_add_ps(__simd_f_add_ps(__simd_f_mul_ps(x, x), + __simd_f_mul_ps(y, y)), + __simd_f_mul_ps(z, z)); + + __simd_f if_0 = __simd_f_and_ps( + __simd_f_and_ps( + __simd_f_cmpare_not_equal_ps(lengthSquared, __simd_f_set_ps1(1.0f)), + __simd_f_cmpare_not_equal_ps(lengthSquared, __simd_f_set_ps1(0.0f))), + __simd_f_set_ps1(1.0f)); + + lengthSquared = lengthSquared * if_0 + 1 * (__simd_f_not_and_ps(if_0, __simd_f_set_ps1(1.0f))); + __simd_f ilength = __simd_f_reciprocal_sqrt_ps(lengthSquared)*if_0+ + 0*(__simd_f_not_and_ps(if_0, __simd_f_set_ps1(1.0f))); + x = (__simd_f_mul_ps(x, ilength)*if_0)+x*(__simd_f_not_and_ps(if_0, __simd_f_set_ps1(1.0f))); + y = (__simd_f_mul_ps(y, ilength)*if_0)+y*(__simd_f_not_and_ps(if_0, __simd_f_set_ps1(1.0f))); + z = (__simd_f_mul_ps(z, ilength)*if_0)+z*(__simd_f_not_and_ps(if_0, __simd_f_set_ps1(1.0f))); + + + __simd_f sinres = { 0 }; + __simd_f cosres = { 0 }; + + for (unsigned int i = 0; i < __simd_32_size; i++) { + ((float*)&sinres)[i] = sinf(((float*)&angle)[i]); + ((float*)&cosres)[i] = cosf(((float*)&angle)[i]); + } + + __simd_f t = __simd_f_sub_ps(__simd_f_set_ps1(1.0f), cosres); + + + /* + result.m0 = x*x*t + cosres; + result.m1 = y*x*t + z*sinres; + result.m2 = z*x*t - y*sinres; + result.m3 = 0.0f; + + result.m4 = x*y*t - z*sinres; + result.m5 = y*y*t + cosres; + result.m6 = z*y*t + x*sinres; + result.m7 = 0.0f; + + result.m8 = x*z*t + y*sinres; + result.m9 = y*z*t - x*sinres; + result.m10 = z*z*t + cosres; + result.m11 = 0.0f; + + result.m12 = 0.0f; + result.m13 = 0.0f; + result.m14 = 0.0f; + result.m15 = 1.0f; + + */ + + + result.m0 = __simd_f_add_ps(__simd_f_mul_ps(__simd_f_mul_ps(x, x), t), cosres); + result.m1 = __simd_f_add_ps(__simd_f_mul_ps(__simd_f_mul_ps(y, x), t), __simd_f_mul_ps(z, sinres)); + result.m2 = __simd_f_sub_ps(__simd_f_mul_ps(__simd_f_mul_ps(z, x), t), __simd_f_mul_ps(y, sinres)); + result.m3 = __simd_f_set_ps1(0.0f); + + result.m4 = __simd_f_sub_ps(__simd_f_mul_ps(__simd_f_mul_ps(x, y), t), __simd_f_mul_ps(z, sinres)); + result.m5 = __simd_f_add_ps(__simd_f_mul_ps(__simd_f_mul_ps(y, y), t), cosres); + result.m6 = __simd_f_add_ps(__simd_f_mul_ps(__simd_f_mul_ps(z, y), t), __simd_f_mul_ps(x, sinres)); + result.m7 = __simd_f_set_ps1(0.0f); + + result.m8 = __simd_f_add_ps(__simd_f_mul_ps(__simd_f_mul_ps(x, z), t), __simd_f_mul_ps(y, sinres)); + result.m9 = __simd_f_sub_ps(__simd_f_mul_ps(__simd_f_mul_ps(y, z), t), __simd_f_mul_ps(x, sinres)); + result.m10 = __simd_f_add_ps(__simd_f_mul_ps(__simd_f_mul_ps(z, z), t), cosres); + result.m11 = __simd_f_set_ps1(0.0f); + + result.m12 = __simd_f_set_ps1(0.0f); + result.m13 = __simd_f_set_ps1(0.0f); + result.m14 = __simd_f_set_ps1(0.0f); + result.m15 = __simd_f_set_ps1(1.0f); + + return result; +} + + + +RMAPI Matrix_simd MatrixMultiply_simd(Matrix_simd left, Matrix_simd right) +{ + Matrix_simd result = { 0 }; + + result.m0 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m0, right.m0), __simd_f_mul_ps(left.m1, right.m4)), + __simd_f_add_ps(__simd_f_mul_ps(left.m2, right.m8), __simd_f_mul_ps(left.m3, right.m12))); + + result.m1 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m0, right.m1), __simd_f_mul_ps(left.m1, right.m5)), + __simd_f_add_ps(__simd_f_mul_ps(left.m2, right.m9), __simd_f_mul_ps(left.m3, right.m13))); + + result.m2 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m0, right.m2), __simd_f_mul_ps(left.m1, right.m6)), + __simd_f_add_ps(__simd_f_mul_ps(left.m2, right.m10), __simd_f_mul_ps(left.m3, right.m14))); + + result.m3 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m0, right.m3), __simd_f_mul_ps(left.m1, right.m7)), + __simd_f_add_ps(__simd_f_mul_ps(left.m2, right.m11), __simd_f_mul_ps(left.m3, right.m15))); + + result.m4 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m4, right.m0), __simd_f_mul_ps(left.m5, right.m4)), + __simd_f_add_ps(__simd_f_mul_ps(left.m6, right.m8), __simd_f_mul_ps(left.m7, right.m12))); + + result.m5 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m4, right.m1), __simd_f_mul_ps(left.m5, right.m5)), + __simd_f_add_ps(__simd_f_mul_ps(left.m6, right.m9), __simd_f_mul_ps(left.m7, right.m13))); + + result.m6 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m4, right.m2), __simd_f_mul_ps(left.m5, right.m6)), + __simd_f_add_ps(__simd_f_mul_ps(left.m6, right.m10), __simd_f_mul_ps(left.m7, right.m14))); + + result.m7 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m4, right.m3), __simd_f_mul_ps(left.m5, right.m7)), + __simd_f_add_ps(__simd_f_mul_ps(left.m6, right.m11), __simd_f_mul_ps(left.m7, right.m15))); + + result.m8 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m8, right.m0), __simd_f_mul_ps(left.m9, right.m4)), + __simd_f_add_ps(__simd_f_mul_ps(left.m10, right.m8), __simd_f_mul_ps(left.m11, right.m12))); + + result.m9 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m8, right.m1), __simd_f_mul_ps(left.m9, right.m5)), + __simd_f_add_ps(__simd_f_mul_ps(left.m10, right.m9), __simd_f_mul_ps(left.m11, right.m13))); + + result.m10 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m8, right.m2), __simd_f_mul_ps(left.m9, right.m6)), + __simd_f_add_ps(__simd_f_mul_ps(left.m10, right.m10), __simd_f_mul_ps(left.m11, right.m14))); + + result.m11 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m8, right.m3), __simd_f_mul_ps(left.m9, right.m7)), + __simd_f_add_ps(__simd_f_mul_ps(left.m10, right.m11), __simd_f_mul_ps(left.m11, right.m15))); + + result.m12 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m12, right.m0), __simd_f_mul_ps(left.m13, right.m4)), + __simd_f_add_ps(__simd_f_mul_ps(left.m14, right.m8), __simd_f_mul_ps(left.m15, right.m12))); + + result.m13 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m12, right.m1), __simd_f_mul_ps(left.m13, right.m5)), + __simd_f_add_ps(__simd_f_mul_ps(left.m14, right.m9), __simd_f_mul_ps(left.m15, right.m13))); + + result.m14 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m12, right.m2), __simd_f_mul_ps(left.m13, right.m6)), + __simd_f_add_ps(__simd_f_mul_ps(left.m14, right.m10), __simd_f_mul_ps(left.m15, right.m14))); + + result.m15 = __simd_f_add_ps( + __simd_f_add_ps(__simd_f_mul_ps(left.m12, right.m3), __simd_f_mul_ps(left.m13, right.m7)), + __simd_f_add_ps(__simd_f_mul_ps(left.m14, right.m11), __simd_f_mul_ps(left.m15, right.m15))); + + return result; +} + + + + #endif // RAYMATH_H diff --git a/src/rmodels.c b/src/rmodels.c index 22559e34f..d534aa89e 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -57,6 +57,7 @@ #include // Required for: malloc(), free() #include // Required for: memcmp(), strlen() #include // Required for: sinf(), cosf(), sqrtf(), fabsf() +#include #if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL) #define TINYOBJ_MALLOC RL_MALLOC @@ -1372,7 +1373,7 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection); // Draw mesh - if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, 0); + if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, mesh.indices); else rlDrawVertexArray(0, mesh.vertexCount); } @@ -1403,6 +1404,257 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform) #endif } + +// Draw a 3d mesh with material and transform in simd +void DrawMesh_simd(Mesh mesh, Material material, Matrix transform) +{ +#if defined(GRAPHICS_API_OPENGL_11) + #define GL_VERTEX_ARRAY 0x8074 + #define GL_NORMAL_ARRAY 0x8075 + #define GL_COLOR_ARRAY 0x8076 + #define GL_TEXTURE_COORD_ARRAY 0x8078 + + rlEnableTexture(material.maps[MATERIAL_MAP_DIFFUSE].texture.id); + + rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.vertices); + rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords); + rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals); + rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors); + + rlPushMatrix(); + rlMultMatrixf(MatrixToFloat(transform)); + rlColor4ub(material.maps[MATERIAL_MAP_DIFFUSE].color.r, + material.maps[MATERIAL_MAP_DIFFUSE].color.g, + material.maps[MATERIAL_MAP_DIFFUSE].color.b, + material.maps[MATERIAL_MAP_DIFFUSE].color.a); + + if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, mesh.indices); + else rlDrawVertexArray(0, mesh.vertexCount); + rlPopMatrix(); + + rlDisableStatePointer(GL_VERTEX_ARRAY); + rlDisableStatePointer(GL_TEXTURE_COORD_ARRAY); + rlDisableStatePointer(GL_NORMAL_ARRAY); + rlDisableStatePointer(GL_COLOR_ARRAY); + + rlDisableTexture(); +#endif + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + // Bind shader program + rlEnableShader(material.shader.id); + + // Send required data to shader (matrices, values) + //----------------------------------------------------- + // Upload to shader material.colDiffuse + if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1) + { + __simd_f values = { + material.maps[MATERIAL_MAP_DIFFUSE].color.r,///255.0f, + material.maps[MATERIAL_MAP_DIFFUSE].color.g,///255.0f, + material.maps[MATERIAL_MAP_DIFFUSE].color.b,///255.0f, + material.maps[MATERIAL_MAP_DIFFUSE].color.a///255.0f + }; + + __simd_f divide_by = __simd_f_set_ps1(255.0f); + + values = values / divide_by; + + + float values_float[4] = { + ((float*)&values)[0],///255.0f, + ((float*)&values)[1],///255.0f, + ((float*)&values)[2],///255.0f, + ((float*)&values)[3]///255.0f + }; + + + rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values_float, SHADER_UNIFORM_VEC4, 1); + } + + // Upload to shader material.colSpecular (if location available) + if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1) + { + __simd_f values = { + material.maps[MATERIAL_MAP_DIFFUSE].color.r,///255.0f, + material.maps[MATERIAL_MAP_DIFFUSE].color.g,///255.0f, + material.maps[MATERIAL_MAP_DIFFUSE].color.b,///255.0f, + material.maps[MATERIAL_MAP_DIFFUSE].color.a///255.0f + }; + + __simd_f divide_by = __simd_f_set_ps1(255.0f); + + values = values / divide_by; + + + float values_float[4] = { + ((float*)&values)[0],///255.0f, + ((float*)&values)[1],///255.0f, + ((float*)&values)[2],///255.0f, + ((float*)&values)[3]///255.0f + }; + + rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values_float, SHADER_UNIFORM_VEC4, 1); + } + + // Get a copy of current matrices to work with, + // just in case stereo render is required and we need to modify them + // NOTE: At this point the modelview matrix just contains the view matrix (camera) + // That's because BeginMode3D() sets it and there is no model-drawing function + // that modifies it, all use rlPushMatrix() and rlPopMatrix() + Matrix matModel = MatrixIdentity(); + Matrix matView = rlGetMatrixModelview(); + Matrix matModelView = MatrixIdentity(); + Matrix matProjection = rlGetMatrixProjection(); + + // Upload view and projection matrices (if locations available) + if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView); + if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection); + + // Model transformation matrix is send to shader uniform location: SHADER_LOC_MATRIX_MODEL + if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], transform); + + // Accumulate several model transformations: + // transform: model transformation provided (includes DrawModel() params combined with model.transform) + // rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack + matModel = MatrixMultiply(transform, rlGetMatrixTransform()); + + // Get model-view matrix + matModelView = MatrixMultiply(matModel, matView); + + // Upload model normal matrix (if locations available) + if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); + //----------------------------------------------------- + + // Bind active texture maps (if available) + for (int i = 0; i < MAX_MATERIAL_MAPS; i++) + { + if (material.maps[i].texture.id > 0) + { + // Select current shader texture slot + rlActiveTextureSlot(i); + + // Enable texture for active slot + if ((i == MATERIAL_MAP_IRRADIANCE) || + (i == MATERIAL_MAP_PREFILTER) || + (i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id); + else rlEnableTexture(material.maps[i].texture.id); + + rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1); + } + } + + // Try binding vertex array objects (VAO) + // or use VBOs if not possible + if (!rlEnableVertexArray(mesh.vaoId)) + { + // Bind mesh VBO data: vertex position (shader-location = 0) + rlEnableVertexBuffer(mesh.vboId[0]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]); + + // Bind mesh VBO data: vertex texcoords (shader-location = 1) + rlEnableVertexBuffer(mesh.vboId[1]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); + + if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1) + { + // Bind mesh VBO data: vertex normals (shader-location = 2) + rlEnableVertexBuffer(mesh.vboId[2]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]); + } + + // Bind mesh VBO data: vertex colors (shader-location = 3, if available) + if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1) + { + if (mesh.vboId[3] != 0) + { + rlEnableVertexBuffer(mesh.vboId[3]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); + } + else + { + // Set default value for unused attribute + // NOTE: Required when using default shader and no VAO support + float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC2, 4); + rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); + } + } + + // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) + if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1) + { + rlEnableVertexBuffer(mesh.vboId[4]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]); + } + + // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) + if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1) + { + rlEnableVertexBuffer(mesh.vboId[5]); + rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); + rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); + } + + if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]); + } + + int eyeCount = 1; + if (rlIsStereoRenderEnabled()) eyeCount = 2; + + for (int eye = 0; eye < eyeCount; eye++) + { + // Calculate model-view-projection matrix (MVP) + Matrix matModelViewProjection = MatrixIdentity(); + if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection); + else + { + // Setup current eye viewport (half screen width) + rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight()); + matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye)); + } + + // Send combined model-view-projection matrix to shader + rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection); + + // Draw mesh + if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, mesh.indices); + else rlDrawVertexArray(0, mesh.vertexCount); + } + + // Unbind all binded texture maps + for (int i = 0; i < MAX_MATERIAL_MAPS; i++) + { + // Select current shader texture slot + rlActiveTextureSlot(i); + + // Disable texture for active slot + if ((i == MATERIAL_MAP_IRRADIANCE) || + (i == MATERIAL_MAP_PREFILTER) || + (i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap(); + else rlDisableTexture(); + } + + // Disable all possible vertex array objects (or VBOs) + rlDisableVertexArray(); + rlDisableVertexBuffer(); + rlDisableVertexBufferElement(); + + // Disable shader program + rlDisableShader(); + + // Restore rlgl internal modelview and projection matrices + rlSetMatrixModelview(matView); + rlSetMatrixProjection(matProjection); +#endif +} + + // Draw multiple mesh instances with material and different transforms void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int instances) { @@ -3295,6 +3547,117 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota } } + + +// Draw a model with extended parameters using sse and sse2 simd instruction set +void DrawModelEx_simd(Model model[], Vector3_simd position, Vector3_simd rotationAxis, __simd_f rotationAngle, Vector3_simd scale, Color_float_simd tint) +{ + // Calculate transformation matrix from function parameters + // Get transform matrix (rotation -> scale -> translation) + + + + Matrix_simd matScale = MatrixScale_simd(scale.x, scale.y, scale.z); + Matrix_simd matRotation = MatrixRotate_simd(rotationAxis, __simd_f_mul_ps(rotationAngle, __simd_f_set_ps1(DEG2RAD))); + Matrix_simd matTranslation = MatrixTranslate_simd(position.x, position.y, position.z); + + Matrix_simd matTransform = MatrixMultiply_simd(MatrixMultiply_simd(matScale, matRotation), matTranslation); + + // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform) + Matrix model_transform[__simd_32_size] = {0}; + + for(unsigned int i=0; i< __simd_32_size; i++){ + model_transform[i] = model[i].transform; + } + + Matrix_simd model_transform_simd = Matrix_to_Matrix_simd(model_transform); + + model_transform_simd = MatrixMultiply_simd(model_transform_simd, matTransform); + + Matrix *model_transform_ptr = Matrix_simd_to_Matrix(model_transform_simd); + + for(unsigned int i=0; i<__simd_32_size; i++) + model[i].transform = model_transform_ptr[i]; + + + Color color_arr[__simd_32_size] = {0}; + + + Color_float_simd colorTint = {WHITE.r, WHITE.g, WHITE.b, WHITE.a}; + + for(unsigned int i=0; i < __simd_32_size; i++){ + + unsigned int j_max = floorf((float)model[i].meshCount/(float)__simd_32_size); + for (unsigned int j = 0; j < j_max; j++) + { + + for(unsigned int a=0; a < __simd_32_size; a++){ + color_arr[a] = model[i].materials[model[i]. + meshMaterial[j*__simd_32_size+a]].maps[MATERIAL_MAP_DIFFUSE].color; + + } + + Color_float_simd color_simd = Color_to_Color_float_simd(color_arr); + + + colorTint.r = (((color_simd.r/255.0)*(tint.r/255.0))*255.0f); + colorTint.g = (((color_simd.g/255.0)*(tint.g/255.0))*255.0f); + colorTint.b = (((color_simd.b/255.0)*(tint.b/255.0))*255.0f); + colorTint.a = (((color_simd.a/255.0)*(tint.a/255.0))*255.0f); + + Color * color_tint= Color_float_simd_to_Color(colorTint); + + for(unsigned int a=0; a<__simd_32_size; a++){ + model[i].materials[model[i].meshMaterial[j*__simd_32_size+a]]. + maps[MATERIAL_MAP_DIFFUSE].color = color_tint[a]; + DrawMesh_simd(model[i].meshes[j*__simd_32_size+a], model[i]. + materials[model[i].meshMaterial[j*__simd_32_size+a]], model[i].transform); + model[i].materials[model[i].meshMaterial[j*__simd_32_size+a]]. + maps[MATERIAL_MAP_DIFFUSE].color = color_arr[a]; + } + + } + + + unsigned int j = {0}; + j = j_max * __simd_32_size; + + unsigned int j_max_2 = {0}; + j_max_2 = model[i].meshCount; + + if(j_max_2 - j){ + + for(unsigned int a=0; a < (j_max_2 - j); a++){ + color_arr[a] = model[i].materials[model[i]. + meshMaterial[j+a]].maps[MATERIAL_MAP_DIFFUSE].color; + + } + + Color_float_simd color_simd = Color_to_Color_float_simd(color_arr); + + colorTint.r = (((color_simd.r/255.0)*(tint.r/255.0))*255.0f); + colorTint.g = (((color_simd.g/255.0)*(tint.g/255.0))*255.0f); + colorTint.b = (((color_simd.b/255.0)*(tint.b/255.0))*255.0f); + colorTint.a = (((color_simd.a/255.0)*(tint.a/255.0))*255.0f); + + Color * color_tint= Color_float_simd_to_Color(colorTint); + + for(unsigned int a=0; a < (j_max_2-j); a++){ + model[i].materials[model[i].meshMaterial[j+a]]. + maps[MATERIAL_MAP_DIFFUSE].color = color_tint[a]; + DrawMesh_simd(model[i].meshes[j+a], model[i]. + materials[model[i].meshMaterial[j+a]], model[i].transform); + model[i].materials[model[i].meshMaterial[j+a]]. + maps[MATERIAL_MAP_DIFFUSE].color = color_arr[a]; + } + } + + + } +} + + + // Draw a model wires (with texture if set) void DrawModelWires(Model model, Vector3 position, float scale, Color tint) { diff --git a/src/simd.h b/src/simd.h new file mode 100644 index 000000000..0f84e96cc --- /dev/null +++ b/src/simd.h @@ -0,0 +1,94 @@ +#pragma once +#include +#include + + +#ifdef sse_sse2 + +//Sizes +#define __simd_8_size 16 +#define __simd_16_size 8 +#define __simd_32_size 4 +#define __simd_64_size 2 + +//Variables +#define __simd_f __m128 +#define __simd_d __m128d +#define __simd_i __m128i + +//Intrinsics +#define __simd_f_set_ps1(a) (_mm_set_ps1(a)) + +#define __simd_f_add_ps(a, b) (_mm_add_ps((a), (b))) +#define __simd_f_sub_ps(a, b) (_mm_sub_ps(a, b)) +#define __simd_f_mul_ps(a, b) (_mm_mul_ps(a, b)) +#define __simd_f_reciprocal_sqrt_ps(a) (_mm_rsqrt_ps(a)) + + +#define __simd_f_cmpare_lower_or_equal_ps(a, b) (_mm_cmple_ps(a, b)) +#define __simd_f_cmpare_grater_or_equal_ps(a, b) (_mm_cmpge_ps(a, b)) +#define __simd_f_cmpare_not_equal_ps(a, b) (_mm_cmpneq_ps(a, b)) + +#define __simd_i__mm_cast_f_to_i_ps_si128(a) (_mm_castps_si128(a)) + +#define __simd_f_and_ps(a, b) (_mm_and_ps(a, b)) +#define __simd_f_not_and_ps(a, b) (_mm_andnot_ps(a, b)) +#else + + +#define __simd_8_size 1 +#define __simd_16_size 1 +#define __simd_32_size 1 +#define __simd_64_size 1 + + + +#define __simd_f float +#define __simd_d double +#define __simd_i int + +#define __simd_f_set_ps1(a) (a) + +#define __simd_f_add_ps(a, b) (a+b) +#define __simd_f_sub_ps(a, b) (a-b) +#define __simd_f_mul_ps(a, b) (a*b) +#define __simd_f_reciprocal_sqrt_ps(a) (1/sqrtf(a)) + + +#define __simd_f_cmpare_lower_or_equal_ps(a, b) (a<=b) +#define __simd_f_cmpare_grater_or_equal_ps(a, b) (a>=b) +#define __simd_f_cmpare_not_equal_ps(a, b) (a!=b) + +#define __simd_i__mm_cast_f_to_i_ps_si128(a) ((int)a) + +#define __simd_f_and_ps(a, b) (a&&b) + +#define __simd_f_not_and_ps(a, b) (!a) + +#endif + + +//simd structs + +typedef struct Vector3_simd { + __simd_f x; + __simd_f y; + __simd_f z; +}Vector3_simd; + + +typedef struct Matrix_simd { + __simd_f m0, m4, m8, m12; // Matrix first row (4 components) + __simd_f m1, m5, m9, m13; // Matrix second row (4 components) + __simd_f m2, m6, m10, m14; // Matrix third row (4 components) + __simd_f m3, m7, m11, m15; // Matrix fourth row (4 components) +} Matrix_simd; + +typedef struct Color_float_simd{ + + __simd_f r, g, b, a; + +}Color_float_simd; + +// simd structs +