static struct vrend_linked_shader_program *lookup_shader_program(struct vrend_sub_context *sub_ctx,
                                                                 GLuint vs_id,
                                                                 GLuint fs_id,
                                                                 GLuint gs_id,
                                                                 GLuint tcs_id,
                                                                 GLuint tes_id,
                                                                 bool dual_src)
{
   uint64_t vs_fs_key = (((uint64_t)fs_id) << 32) | (vs_id & ~VREND_PROGRAM_NQUEUE_MASK) |
                        (dual_src ? 1 : 0);

   struct vrend_linked_shader_program *ent;

   struct list_head *programs = &sub_ctx->gl_programs[vs_id & VREND_PROGRAM_NQUEUE_MASK];
   LIST_FOR_EACH_ENTRY(ent, programs, head) {
      if (likely(ent->vs_fs_key != vs_fs_key))
         continue;
      if (ent->ss[PIPE_SHADER_GEOMETRY] &&
          ent->ss[PIPE_SHADER_GEOMETRY]->id != gs_id)
        continue;
      if (ent->ss[PIPE_SHADER_TESS_CTRL] &&
          ent->ss[PIPE_SHADER_TESS_CTRL]->id != tcs_id)
         continue;
      if (ent->ss[PIPE_SHADER_TESS_EVAL] &&
          ent->ss[PIPE_SHADER_TESS_EVAL]->id != tes_id)
         continue;
      /* put the entry in front */
      if (programs->next != &ent->head) {
         list_del(&ent->head);
         list_add(&ent->head, programs);
      }
      return ent;
   }

   return NULL;
}
static struct vrend_linked_shader_program *lookup_shader_program(struct vrend_sub_context *sub_ctx,
                                                                 GLuint vs_id,
                                                                 GLuint fs_id,
                                                                 GLuint gs_id,
                                                                 GLuint tcs_id,
                                                                 GLuint tes_id,
                                                                 bool dual_src)
{
   uint64_t vs_fs_key = (((uint64_t)fs_id) << 32) | (vs_id & ~VREND_PROGRAM_NQUEUE_MASK) |
                        (dual_src ? 1 : 0);

   struct vrend_linked_shader_program *ent;

   struct list_head *programs = &sub_ctx->gl_programs[vs_id & VREND_PROGRAM_NQUEUE_MASK];
   LIST_FOR_EACH_ENTRY(ent, programs, head) {
      if (likely(ent->vs_fs_key != vs_fs_key))
         continue;
      if (ent->ss[PIPE_SHADER_GEOMETRY] &&
          ent->ss[PIPE_SHADER_GEOMETRY]->id != gs_id)
        continue;
      if (ent->ss[PIPE_SHADER_TESS_CTRL] &&
          ent->ss[PIPE_SHADER_TESS_CTRL]->id != tcs_id)
         continue;
      if (ent->ss[PIPE_SHADER_TESS_EVAL] &&
          ent->ss[PIPE_SHADER_TESS_EVAL]->id != tes_id)
         continue;
       
      if (programs->next != &ent->head) {
         list_del(&ent->head);
         list_add(&ent->head, programs);
      }
      return ent;
   }

   return NULL;
}