static int vrend_shader_select(struct vrend_sub_context *sub_ctx,
                               struct vrend_shader_selector *sel,
                               bool *dirty)
{
   struct vrend_shader_key key;
   struct vrend_shader *shader = NULL;
   int r;

   memset(&key, 0, sizeof(key));
   vrend_fill_shader_key(sub_ctx, sel, &key);

   if (sel->current && !memcmp(&sel->current->key, &key, sizeof(key)))
      return 0;

   if (sel->num_shaders > 1) {
      struct vrend_shader *p = sel->current;
      struct vrend_shader *c = p->next_variant;
      while (c && memcmp(&c->key, &key, sizeof(key)) != 0) {
         p = c;
         c = c->next_variant;
      }
      if (c) {
         p->next_variant = c->next_variant;
         shader = c;
      }
   }

   if (!shader) {
      shader = CALLOC_STRUCT(vrend_shader);
      shader->sel = sel;
      list_inithead(&shader->programs);
      strarray_alloc(&shader->glsl_strings, SHADER_MAX_STRINGS);

      r = vrend_shader_create(sub_ctx->parent, shader, &key);
      if (r) {
         sel->current = NULL;
         FREE(shader);
         return r;
      }
      sel->num_shaders++;
   }
   if (dirty)
      *dirty = true;

   shader->next_variant = sel->current;
   sel->current = shader;
   return 0;
}
static int vrend_shader_select(struct vrend_sub_context *sub_ctx,
                               struct vrend_shader_selector *sel,
                               bool *dirty)
{
   struct vrend_shader_key key;
   struct vrend_shader *shader = NULL;
   int r;

   memset(&key, 0, sizeof(key));
   vrend_fill_shader_key(sub_ctx, sel, &key);

   if (sel->current && !memcmp(&sel->current->key, &key, sizeof(key)))
      return 0;

   if (sel->num_shaders > 1) {
      struct vrend_shader *p = sel->current;
      struct vrend_shader *c = p->next_variant;
      while (c && memcmp(&c->key, &key, sizeof(key)) != 0) {
         p = c;
         c = c->next_variant;
      }
      if (c) {
         p->next_variant = c->next_variant;
         shader = c;
      }
   }

   if (!shader) {
      shader = CALLOC_STRUCT(vrend_shader);
      shader->sel = sel;
      list_inithead(&shader->programs);
      strarray_alloc(&shader->glsl_strings, SHADER_MAX_STRINGS);

      r = vrend_shader_create(sub_ctx->parent, shader, &key);
      if (r) {
         sel->current = NULL;
         FREE(shader);
         return r;
      }
      sel->num_shaders++;
   }
   if (dirty)
      *dirty = true;

   shader->next_variant = sel->current;
   sel->current = shader;
   return 0;
}