          (atom {:last-input {}
                 :programs {}
                 :shaders {}
-                :draws []}))
+                :buffers {}
+                :buffer-views {}}))
 
 (defn- load-shader! [gl {:keys [type uri]}]
   ;TODO dereference URI instead of using URI as source

(defn- load-programs! [gl shaders descs]
  (map-vals descs #(load-program! gl shaders %)))

(defn- make-draw-calls! [gl programs buffer-views accessors]
  (let [program (get programs "my-program")
        vertex-buffer (buffers/create-buffer gl (get buffer-views "my-array-buffer-view")
                                             buffer-object/array-buffer
                                             buffer-object/static-draw)
        element-buffer (buffers/create-buffer gl (get buffer-views "my-element-array-buffer-view")
                                              buffer-object/element-array-buffer
                                              buffer-object/static-draw)]
    [{:shader program
      :draw-mode draw-mode/triangles
      :count 3
      :attributes [(assoc (get accessors "my-position-accessor")
                     :buffer vertex-buffer
                     :location (shaders/get-attrib-location gl program "vertex_position"))]
      :element-array (assoc (get accessors "my-index-accessor")
                       :buffer element-buffer)}]))

(defn update-render-state! [old-state gl input]
  (if (= (:last-input old-state) input)
    old-state
    ; TODO: Unload removed shaders, programs, and buffers
    (let [shaders (load-shaders! gl (:shaders input))
          programs (load-programs! gl shaders (:programs input))]
      {:last-input input
       :shaders shaders
       :programs programs
       :draws (make-draw-calls! gl programs (:buffer-views input) (:accessors input))})))

(let [gl (context/get-context (sel1 :#glcanvas))]
  (swap! render-state update-render-state! gl input)        ;TODO swap! function must not have side-effects
  (buffers/clear-color-buffer gl 0 0 0 1)
  (doseq [draw-args (:draws @render-state)]
    (mapply buffers/draw! gl draw-args)))

   }")

(def input
  {:accessors {"my-position-accessor" {:buffer-view "my-array-view"
                                       :components-per-vertex 3
                                       :type data-type/float}
               "my-index-accessor" {:buffer-view "my-element-view"
                                    :count 3
                                    :type data-type/unsigned-short
                                    :offset 0}}
   :buffers {"my-array-buffer" {:uri [0.5 -0.5 0.0
                                      0.0 0.5 0.0
                                      -0.5 -0.5 0.0]
                                :type ta/float32}
             "my-element-buffer" {:uri [0 1 2]
                                  :type ta/unsigned-int16}}
   :buffer-views {"my-array-view" {:buffer "my-array-buffer"
                                   :byteOffset 0
                                   :byteLength 36
                                   :target buffer-object/array-buffer}
                  "my-element-view" {:buffer "my-element-buffer"
                                     :byteOffset 0
                                     :byteLength 6
                                     :target buffer-object/element-array-buffer}}
   :programs {"my-program" {:attributes ["vertex_position"]
                            :fragment-shader "my-fragment-shader"
                            :vertex-shader "my-vertex-shader"}}
   :shaders {"my-vertex-shader" {:type shader/vertex-shader
