cglm icon indicating copy to clipboard operation
cglm copied to clipboard

Apple SIMD, Swift and Metal API Support and Helpers

Open recp opened this issue 5 years ago • 0 comments
trafficstars

cglm always tries to make things easier and faster. Currently I'm trying to switch my render engine from OpenGL to Metal and other graphics libraries by writing a GPU library (https://github.com/recp/gpu), it will be documented after first release...

cglm offers two APIs

  1. Array API which makes parameters easier to pass it, also easy to load CPU register
  2. Struct API which provides type safety and other maybe

A few things I would like to see in cglm

  1. Helpers to pass cglm types or values to Apple's platform or types.
  2. Make cglm work better with Swift language, struct API will help a lot here, I think.
  3. Make cglm work better with Metal API
  4. todo?

cglm already provides applesimd.h header and it contains helpers to convert cglm types to Apple's simd types.

But there may bee another option:


Now let's see Apple's tempale Metal project, see ShaderTypes.h:

typedef struct
{
    matrix_float4x4 projectionMatrix;
    matrix_float4x4 modelViewMatrix;
} Uniforms;

This is how I passed cglm values to Metal API:

- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
  mat4 proj;

  if (!uniforms)
    return;
  
  glm_perspective(glm_rad(65.0f), 
                  size.width / size.height, 
                  0.1f, 
                  100.0f, 
                  proj);
  
  uniforms->projectionMatrix = glm_mat4_applesimd(proj);
}

As you can see it contains extra copy (it may be fast). We can reduce the copy with this way maybe if this is not undefined behavior or similar:

/* common.h */
#if defined(__APPLE__)                                                        \
    && defined(SIMD_COMPILER_HAS_REQUIRED_FEATURES)                           \
    && defined(SIMD_BASE)                                                     \
    && defined(SIMD_TYPES)                                                    \
    && defined(SIMD_VECTOR_TYPES)
#  define CGLM_APPLE_SIMD
#endif
/* types-struct.h */
typedef union CGLM_ALIGN_MAT mat4s {
  mat4  raw;
  vec4s col[4];
#if CGLM_USE_ANONYMOUS_STRUCT
  struct {
    float m00, m01, m02, m03;
    float m10, m11, m12, m13;
    float m20, m21, m22, m23;
    float m30, m31, m32, m33;
  };
#endif

/* this could be magic ??? */
#ifdef CGLM_APPLE_SIMD
  simd_float4x4 apple;
#endif

} mat4s;

/* repeat for other types */

as you can see it adds a variable called apple to union. If this won't break anything e.g. C spec or clang... then everything will be easier, let's see how (compare with above example):

- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
  if (!uniforms)
    return;

  uniforms->projectionMatrix = glms_perspective(glm_rad(65.0f), 
                                                size.width / size.height, 
                                                0.1f, 
                                                100.0f).apple;
}

it converts cglm to Apple's simd directly and it reduces extra copy (glm_mat4_applesimd() ) and it reduces to define mat4 variable...

We are not including Apple's headers to cglm, we are testing a few macro to check if the header was included before cglm, so it should not break anything on Windows or on other platforms


Feedbacks? We can choose a better name than .apple but it indicates the purpose


EDIT: cglm may have different alignment, so this may cause troubles but not sure

recp avatar Jul 26 '20 18:07 recp