intel: add intel_rmap for shader resource mapping

It will be used to parse XGL_DESCRIPTOR_SET_MAPPING and
XGL_DYNAMIC_MEMORY_VIEW_SLOT_INFO.
diff --git a/icd/intel/pipeline_rmap.c b/icd/intel/pipeline_rmap.c
new file mode 100644
index 0000000..123a6f1
--- /dev/null
+++ b/icd/intel/pipeline_rmap.c
@@ -0,0 +1,253 @@
+/*
+ * XGL
+ *
+ * Copyright (C) 2014 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "pipeline_priv.h"
+
+static struct intel_rmap_slot *rmap_get_slot(struct intel_rmap *rmap,
+                                             XGL_DESCRIPTOR_SET_SLOT_TYPE type,
+                                             XGL_UINT index)
+{
+    const XGL_UINT resource_offset = rmap->rt_count;
+    const XGL_UINT uav_offset = resource_offset + rmap->resource_count;
+    const XGL_UINT sampler_offset = uav_offset + rmap->uav_count;
+    struct intel_rmap_slot *slot;
+
+    switch (type) {
+    case XGL_SLOT_UNUSED:
+        slot = NULL;
+        break;
+    case XGL_SLOT_SHADER_RESOURCE:
+        slot = &rmap->slots[resource_offset + index];
+        break;
+    case XGL_SLOT_SHADER_UAV:
+        slot = &rmap->slots[uav_offset + index];
+        break;
+    case XGL_SLOT_SHADER_SAMPLER:
+        slot = &rmap->slots[sampler_offset + index];
+        break;
+    default:
+        assert(!"unknown rmap slot type");
+        slot = NULL;
+        break;
+    }
+
+    return slot;
+}
+
+static bool rmap_init_slots_with_path(struct intel_rmap *rmap,
+                                      const XGL_DESCRIPTOR_SET_MAPPING *mapping,
+                                      XGL_UINT *nest_path,
+                                      XGL_UINT nest_level)
+{
+    XGL_UINT i;
+
+    for (i = 0; i < mapping->descriptorCount; i++) {
+        const XGL_DESCRIPTOR_SLOT_INFO *info = &mapping->pDescriptorInfo[i];
+        struct intel_rmap_slot *slot;
+
+        if (info->slotObjectType == XGL_SLOT_NEXT_DESCRIPTOR_SET) {
+            nest_path[nest_level] = i;
+            if (!rmap_init_slots_with_path(rmap, info->pNextLevelSet,
+                        nest_path, nest_level + 1))
+                return false;
+
+            continue;
+        }
+
+        slot = rmap_get_slot(rmap, info->slotObjectType,
+                info->shaderEntityIndex);
+        if (!slot)
+            continue;
+
+        assert(!slot->path_len);
+        slot->path_len = nest_level + 1;
+
+        if (nest_level) {
+            slot->u.path = icd_alloc(sizeof(slot->u.path[0]) *
+                    slot->path_len, 0, XGL_SYSTEM_ALLOC_INTERNAL);
+            if (!slot->u.path) {
+                slot->path_len = 0;
+                return false;
+            }
+
+            memcpy(slot->u.path, nest_path,
+                    sizeof(slot->u.path[0]) * nest_level);
+            slot->u.path[nest_level] = i;
+        } else {
+            slot->u.index = i;
+        }
+    }
+
+    return true;
+}
+
+static bool rmap_init_slots(struct intel_rmap *rmap,
+                            const XGL_DESCRIPTOR_SET_MAPPING *mapping,
+                            XGL_UINT depth)
+{
+    XGL_UINT *nest_path;
+    bool ok;
+
+    if (depth) {
+        nest_path = icd_alloc(sizeof(nest_path[0]) * depth,
+                0, XGL_SYSTEM_ALLOC_INTERNAL_TEMP);
+        if (!nest_path)
+            return false;
+    } else {
+        nest_path = NULL;
+    }
+
+    ok = rmap_init_slots_with_path(rmap, mapping, nest_path, 0);
+
+    if (nest_path)
+        icd_free(nest_path);
+
+    return ok;
+}
+
+static void rmap_update_count(struct intel_rmap *rmap,
+                              XGL_DESCRIPTOR_SET_SLOT_TYPE type,
+                              XGL_UINT index)
+{
+    switch (type) {
+    case XGL_SLOT_UNUSED:
+        break;
+    case XGL_SLOT_SHADER_RESOURCE:
+        if (rmap->resource_count < index + 1)
+            rmap->resource_count = index + 1;
+        break;
+    case XGL_SLOT_SHADER_UAV:
+        if (rmap->uav_count < index + 1)
+            rmap->uav_count = index + 1;
+        break;
+    case XGL_SLOT_SHADER_SAMPLER:
+        if (rmap->sampler_count < index + 1)
+            rmap->sampler_count = index + 1;
+        break;
+    default:
+        assert(!"unknown rmap slot type");
+        break;
+    }
+}
+
+static XGL_UINT rmap_init_counts(struct intel_rmap *rmap,
+                                 const XGL_DESCRIPTOR_SET_MAPPING *mapping)
+{
+    XGL_UINT depth = 0;
+    XGL_UINT i;
+
+    for (i = 0; i < mapping->descriptorCount; i++) {
+        const XGL_DESCRIPTOR_SLOT_INFO *info = &mapping->pDescriptorInfo[i];
+
+        if (info->slotObjectType == XGL_SLOT_NEXT_DESCRIPTOR_SET) {
+            const XGL_UINT d = rmap_init_counts(rmap,
+                    info->pNextLevelSet);
+            if (depth < d + 1)
+                depth = d + 1;
+
+            continue;
+        }
+
+        rmap_update_count(rmap, info->slotObjectType,
+                info->shaderEntityIndex);
+    }
+
+    return depth;
+}
+
+struct intel_rmap *intel_rmap_create(struct intel_dev *dev,
+                                     const XGL_DESCRIPTOR_SET_MAPPING *mapping,
+                                     const XGL_DYNAMIC_MEMORY_VIEW_SLOT_INFO *dyn,
+                                     XGL_UINT rt_count)
+{
+    struct intel_rmap *rmap;
+    struct intel_rmap_slot *slot;
+    XGL_UINT depth, rt;
+
+    rmap = icd_alloc(sizeof(*rmap), 0, XGL_SYSTEM_ALLOC_INTERNAL);
+    if (!rmap)
+        return NULL;
+
+    memset(rmap, 0, sizeof(*rmap));
+
+    depth = rmap_init_counts(rmap, mapping);
+
+    /* add RTs and the dynamic memory view */
+    rmap_update_count(rmap, dyn->slotObjectType, dyn->shaderEntityIndex);
+    rmap->rt_count = rt_count;
+
+    rmap->slot_count = rmap->rt_count + rmap->resource_count +
+        rmap->uav_count + rmap->sampler_count;
+
+    rmap->slots = icd_alloc(sizeof(rmap->slots[0]) * rmap->slot_count,
+            0, XGL_SYSTEM_ALLOC_INTERNAL);
+    if (!rmap->slots) {
+        icd_free(rmap);
+        return NULL;
+    }
+
+    memset(rmap->slots, 0, sizeof(rmap->slots[0]) * rmap->slot_count);
+
+    if (!rmap_init_slots(rmap, mapping, depth)) {
+        intel_rmap_destroy(rmap);
+        return NULL;
+    }
+
+    /* add RTs and the dynamic memory view */
+    slot = rmap_get_slot(rmap, dyn->slotObjectType, dyn->shaderEntityIndex);
+    if (slot) {
+        slot->path_len = INTEL_RMAP_SLOT_DYN;
+        slot->u.index = 0;
+    }
+    for (rt = 0; rt < rmap->rt_count; rt++) {
+        slot = &rmap->slots[rt];
+        slot->path_len = INTEL_RMAP_SLOT_RT;
+        slot->u.index = rt;
+    }
+
+    return rmap;
+}
+
+void intel_rmap_destroy(struct intel_rmap *rmap)
+{
+    XGL_UINT i;
+
+    for (i = 0; i < rmap->slot_count; i++) {
+        struct intel_rmap_slot *slot = &rmap->slots[i];
+
+        switch (slot->path_len) {
+        case 0:
+        case 1:
+        case INTEL_RMAP_SLOT_RT:
+        case INTEL_RMAP_SLOT_DYN:
+            break;
+        default:
+            icd_free(slot->u.path);
+            break;
+        }
+    }
+
+    icd_free(rmap->slots);
+    icd_free(rmap);
+}