anchor.diff:      ;; the member following the sub-structure is rounded up to the
       ;; next multiple of the base alignment of the structure.
       ((v-typep type 'v-struct)
  -     (let ((layout (calc-struct-layout :??????
  -                                       base-offset
  -                                       aligned-offset)))
  -       (destructuring-bind (name
  -                            &key base-offset aligned-offset machine-unit-size
  -                            members)
  -           layout
  -         (declare (ignore name base-offset aligned-offset))
  -         members))
  -     (round-to-next-multiple
  -      (reduce #'max (mapcar (lambda (child)
  -                              ;; {TODO} need to main loop here, will fill
  -                              ;;        in when I've worked it out
  -                              (base-alignment self &&&&& child))
  -                            (children self)))
  -      (base-alignment :vec4)))
  +     'TODO-PADDING
  +     (calc-struct-layout name
  +                         parent-type-aligned-offset
  +                         last-slot-base-offset
  +                         last-slot-aligned-offset
  +                         last-slot-machine-size
  +                         type))
  +    ;; 6. If the member is an array of S column-major matrices with C
  +    ;; columns and R rows, the matrix is stored identically to a row of
  +    ;; S × C column vectors with R components each, according to rule (4).
  +    ((and (v-typep type 'v-array)
  +          (v-typep (v-element-type type) 'v-matrix))
  +     (let ((len (first (v-dimensions type)))
  +           (elem-type (v-element-type type)))
  +       (destructuring-bind (rows cols) (v-dimensions elem-type)
  +         (let* ((new-elem-spec (ecase= rows
  +                                 (2 :vec2)
  +                                 (3 :vec3)
  +                                 (4 :vec4)))
  +                (equiv-array-type-spec (list new-elem-spec (* cols len)))
  +                (equiv-array-type (type-spec->type equiv-array-type-spec)))
  +           (calc-layout name
  +                        parent-type-base-offset
  +                        parent-type-aligned-offset
  +                        last-slot-base-offset
  +                        last-slot-aligned-offset
  +                        last-slot-machine-size
  +                        equiv-array-type)))))
  +    ;; 10. If the member is an array of S structures, the S elements of
  +    ;; the array are laid out in order, according to rule (9).
  +    ((and (v-typep type 'v-array)
  +          (v-typep (v-element-type type) 'v-struct))
  +     (let ((elem-layout (calc-layout :dummy
  +                                     parent-type-base-offset
  +                                     parent-type-aligned-offset
  +                                     last-slot-base-offset
  +                                     last-slot-aligned-offset
  +                                     last-slot-machine-size
  +                                     (v-element-type type))))
  +       (setf (slot-value elem-layout 'machine-unit-size)
  +             (* (slot-value elem-layout 'machine-unit-size)
  +                (first (v-dimensions type))))
  +       elem-layout))
       ;; 4. If the member is an array of scalars or vectors, the base
       ;;    alignment and array stride are set to match the base alignment of
       ;;    a single array element, according to rules (1), (2), and (3), and
  
positive.code:       ;; The base offset of the first member of a structure is taken from the
        ;; aligned offset of the structure itself
        parent-type-aligned-offset
        ;; The base offset of all other structure members is derived by taking
        ;; the offset of the last basic machine unit consumed by the previous
        ;; member and adding one
        ;;
        ;; {TODO} see rule 4 second paragraph, sounds relevent
        ;; {TODO} see rule 9 second paragraph, sounds relevent
        (+ last-slot-aligned-offset ;; which offset?
           last-slot-machine-size
           1)))
  
  (defun calc-scalar-layout (parent-type-aligned-offset
                             last-slot-base-offset
                             last-slot-aligned-offset
                             last-slot-machine-size
  
negative.code: ;;
  ;; - slots in memory will be in same order as in definition
  
  (defclass gl-layout ()
    ((name :initarg :name
           :initform nil
           :reader layout-name)
     (base-offset :initarg :base-offset
                  :initform nil
                  :reader layout-base-offset)
     (base-alignment :initarg :base-alignment
                     :initform nil
                     :reader layout-base-alignment)
     (aligned-offset :initarg :aligned-offset
                     :initform nil
                     :reader layout-aligned-offset)
     (machine-unit-size :initarg :machine-unit-size
                        :initform nil
                        :reader layout-machine-unit-size)
     (members :initarg :members
              :initform nil
              :reader layout-members)))
  
  (defclass std-140 (gl-layout) ())
  (defclass std-430 (gl-layout) ())
  
  (defun calc-block-layout (varjo-struct-type-name)
    (let ((type (type-spec->type varjo-struct-type-name))
          (parent-type-aligned-offset 0)
          (last-slot-base-offset nil)
          (last-slot-aligned-offset nil)
          (last-slot-machine-size nil))
      (assert (v-typep type 'v-struct))
      (calc-struct-layout 'block
                          parent-type-aligned-offset
                          last-slot-base-offset
                          last-slot-aligned-offset
                          last-slot-machine-size
                          type)))
  
  (defun calc-struct-layout (name
                             parent-type-aligned-offset
                             last-slot-base-offset
                             last-slot-aligned-offset
                             last-slot-machine-size
                             type)
    ;; The members of a top-level uniform block are laid out in buffer
    ;; storage by treating the uniform block as a structure with a base
    ;; offset of zero.
    ;; --
    ;; 9. If the member is a structure, the base alignment of the
    ;; structure is N , where N is the largest base alignment value of any
    ;; of its members, and rounded up to the base alignment of a vec4.
    ;; The structure may have padding at the end; the base offset of
    ;; the member following the sub-structure is rounded up to the
    ;; next multiple of the base alignment of the structure.
    (let* ((base-offset (calc-base-offset parent-type-aligned-offset
                                          last-slot-base-offset
                                          last-slot-aligned-offset
                                          last-slot-machine-size))
           (slots (varjo.internals:v-slots type))
           (members (let ((aligned-offset parent-type-aligned-offset)
                          (last-slot-base-offset nil)
                          (last-slot-aligned-offset nil)
                          (last-slot-machine-size nil))
                      (loop :for (name stype) :in slots :collect
                         (let* ((layout (calc-layout name
                                                     base-offset
                                                     aligned-offset
                                                     last-slot-base-offset
                                                     last-slot-aligned-offset
                                                     last-slot-machine-size
                                                     stype)))
                           (with-slots (base-offset
                                        aligned-offset
                                        machine-unit-size)
                               layout
                             (setf last-slot-base-offset base-offset
                                   last-slot-aligned-offset aligned-offset
                                   last-slot-machine-size machine-unit-size))
                           layout))))
           (base-alignment
            (round-to-next-multiple
             (reduce #'max (mapcar #'layout-base-alignment members))
             (calc-vector-base-alignment (type-spec->type :vec4)))))
      (make-instance
       'std-140
       :name name
       :base-offset base-offset
       :base-alignment base-alignment
       :aligned-offset (calc-aligned-offset base-offset base-alignment)
       :machine-unit-size (machine-unit-size type)
       :members members)))
  
  (defun calc-base-offset (parent-type-aligned-offset
                           last-slot-base-offset
  