bug 14014: Fill out support for VkShaderModule

Updated tests and demos to properly use VkShaderModule.
Add support to shader_checker for shader module.
Doesn't do anything with the pName parameter.
diff --git a/include/vkLayer.h b/include/vkLayer.h
index e456a9c..154472c 100644
--- a/include/vkLayer.h
+++ b/include/vkLayer.h
@@ -141,7 +141,6 @@
     PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
     PFN_vkCreateInstance CreateInstance;
     PFN_vkDestroyInstance DestroyInstance;
-    PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
     PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
     PFN_vkGetPhysicalDeviceFormatInfo GetPhysicalDeviceFormatInfo;
diff --git a/include/vulkan.h b/include/vulkan.h
index bf721bd..874caf4 100644
--- a/include/vulkan.h
+++ b/include/vulkan.h
@@ -1593,9 +1593,7 @@
     VkStructureType                             sType;              // Must be VK_STRUCTURE_TYPE_SHADER_CREATE_INFO
     const void*                                 pNext;              // Pointer to next structure
     VkShaderModule                              module;             // Module containing entry point
-    const char*                                 name;               // Null-terminate entry point name
-    size_t                                      codeSize;           // Specified in bytes
-    const void*                                 pCode;
+    const char*                                 pName;              // Null-terminate entry point name
     VkShaderCreateFlags                         flags;              // Reserved
 } VkShaderCreateInfo;
 
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index ee891d6..48b6539 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -1556,7 +1556,7 @@
         layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback);
     }
 
-    layer_debug_report_destroy_instance(mid(instance));
+    layer_debug_report_destroy_instance(my_data->report_data);
     layer_data_map.erase(pTable);
 
     draw_state_instance_table_map.erase(key);
diff --git a/layers/layer_logging.h b/layers/layer_logging.h
index bcae4d9..68f5f89 100644
--- a/layers/layer_logging.h
+++ b/layers/layer_logging.h
@@ -99,9 +99,14 @@
 
 static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data)
 {
-    VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
+    VkLayerDbgFunctionNode *pTrav;
     VkLayerDbgFunctionNode *pTravNext;
 
+    if (!debug_data) {
+        return;
+    }
+
+    pTrav = debug_data->g_pDbgFunctionHead;
     /* Clear out any leftover callbacks */
     while (pTrav) {
         pTravNext = pTrav->pNext;
diff --git a/layers/layers_table.cpp b/layers/layers_table.cpp
index 51baf2e..5d1b9cf 100644
--- a/layers/layers_table.cpp
+++ b/layers/layers_table.cpp
@@ -95,7 +95,6 @@
 
 VkLayerDispatchTable *get_dispatch_table(device_table_map &map, VkObject object)
 {
-//    VkLayerDispatchTable *pDisp  = *(VkLayerDispatchTable **) object;
     dispatch_key key = get_dispatch_key(object);
     device_table_map::const_iterator it = map.find((void *) key);
 #if DISPATCH_MAP_DEBUG
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index 22ca3e0..8fa33ce 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -4538,6 +4538,90 @@
     return result;
 }
 
+void PreCreateShaderModule(
+    VkDevice device,
+    const VkShaderModuleCreateInfo* pCreateInfo)
+{
+    if(device == nullptr)
+    {
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
+        "vkCreateShaderModule parameter, VkDevice device, is null pointer");
+        return;
+    }
+
+    if(pCreateInfo == nullptr)
+    {
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
+        "vkCreateShaderModule parameter, const VkShaderCreateInfo* pCreateInfo, is null pointer");
+        return;
+    }
+    if(pCreateInfo->sType < VK_STRUCTURE_TYPE_BEGIN_RANGE ||
+        pCreateInfo->sType > VK_STRUCTURE_TYPE_END_RANGE)
+    {
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
+        "vkCreateShaderModule parameter, VkStructureType pCreateInfo->sType, is unrecognized enumerator");
+        return;
+    }
+    if(pCreateInfo->pCode == nullptr)
+    {
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
+        "vkCreateShaderModule parameter, const void* pCreateInfo->pCode, is null pointer");
+        return;
+    }
+    if(pCreateInfo->codeSize == 0)
+    {
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
+        "vkCreateShaderModule parameter, size_t pCreateInfo->codeSize, is zero");
+        return;
+    }
+}
+
+void PostCreateShaderModule(
+    VkDevice device,
+    VkShaderModule* pShaderModule,
+    VkResult result)
+{
+    if(device == nullptr)
+    {
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
+        "vkCreateShaderModule parameter, VkDevice device, is null pointer");
+        return;
+    }
+
+    if(pShaderModule == nullptr)
+    {
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
+        "vkCreateShaderModule parameter, VkShader* pShader, is null pointer");
+        return;
+    }
+    if((*pShaderModule) == nullptr)
+    {
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
+        "vkCreateShaderModule parameter, VkShader* pShader, is null pointer");
+        return;
+    }
+
+    if(result != VK_SUCCESS)
+    {
+        std::string reason = "vkCreateShaderModule parameter, VkResult result, is " + EnumeratorString(result);
+        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK", reason.c_str());
+        return;
+    }
+}
+
+VK_LAYER_EXPORT VkResult VKAPI vkCreateShaderModule(
+    VkDevice device,
+    const VkShaderModuleCreateInfo* pCreateInfo,
+    VkShaderModule* pShaderModule)
+{
+    PreCreateShaderModule(device, pCreateInfo);
+    VkResult result = get_dispatch_table(pc_device_table_map, device)->CreateShaderModule(device, pCreateInfo, pShaderModule);
+
+    PostCreateShaderModule(device, pShaderModule, result);
+
+    return result;
+}
+
 void PreCreateShader(
     VkDevice device,
     const VkShaderCreateInfo* pCreateInfo)
@@ -4568,18 +4652,12 @@
         "vkCreateShader parameter, VkShaderModule pCreateInfo->module, is null pointer");
         return;
     }
-    if(pCreateInfo->name == nullptr)
+    if(pCreateInfo->pName == nullptr)
     {
         log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
         "vkCreateShader parameter, const char* pCreateInfo->name, is null pointer");
         return;
     }
-    if(pCreateInfo->pCode == nullptr)
-    {
-        log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "PARAMCHECK",
-        "vkCreateShader parameter, const void* pCreateInfo->pCode, is null pointer");
-        return;
-    }
 }
 
 void PostCreateShader(
diff --git a/layers/shader_checker.cpp b/layers/shader_checker.cpp
index 6251122..df89d3c 100644
--- a/layers/shader_checker.cpp
+++ b/layers/shader_checker.cpp
@@ -28,6 +28,7 @@
 #include <unordered_map>
 #include <map>
 #include <vector>
+#include <string>
 #include "loader_platform.h"
 #include "vk_dispatch_table_helper.h"
 #include "vkLayer.h"
@@ -92,7 +93,7 @@
     }
 }
 
-struct shader_source {
+struct shader_module {
     /* the spirv image itself */
     std::vector<uint32_t> words;
     /* a mapping of <id> to the first word of its def. this is useful because walking type
@@ -101,7 +102,7 @@
     std::unordered_map<unsigned, unsigned> type_def_index;
     bool is_spirv;
 
-    shader_source(VkShaderCreateInfo const *pCreateInfo) :
+    shader_module(VkShaderModuleCreateInfo const *pCreateInfo) :
         words((uint32_t *)pCreateInfo->pCode, (uint32_t *)pCreateInfo->pCode + pCreateInfo->codeSize / sizeof(uint32_t)),
         type_def_index(),
         is_spirv(true) {
@@ -119,7 +120,19 @@
 };
 
 
-static std::unordered_map<void *, shader_source *> shader_map;
+static std::unordered_map<void *, shader_module *> shader_module_map;
+
+struct shader_object {
+    std::string name;
+    struct shader_module *module;
+
+    shader_object(VkShaderCreateInfo const *pCreateInfo)
+    {
+        module = shader_module_map[pCreateInfo->module];
+        name = pCreateInfo->pName;
+    }
+};
+static std::unordered_map<void *, shader_object *> shader_object_map;
 
 
 static void
@@ -221,7 +234,7 @@
 
 /* returns ptr to null terminator */
 static char *
-describe_type(char *dst, shader_source const *src, unsigned type)
+describe_type(char *dst, shader_module const *src, unsigned type)
 {
     auto type_def_it = src->type_def_index.find(type);
 
@@ -267,7 +280,7 @@
 
 
 static bool
-types_match(shader_source const *a, shader_source const *b, unsigned a_type, unsigned b_type, bool b_arrayed)
+types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool b_arrayed)
 {
     auto a_type_def_it = a->type_def_index.find(a_type);
     auto b_type_def_it = b->type_def_index.find(b_type);
@@ -368,7 +381,7 @@
 
 
 static void
-collect_interface_by_location(shader_source const *src, spv::StorageClass sinterface,
+collect_interface_by_location(shader_module const *src, spv::StorageClass sinterface,
                               std::map<uint32_t, interface_var> &out,
                               std::map<uint32_t, interface_var> &builtins_out)
 {
@@ -436,21 +449,35 @@
 }
 
 
-VK_LAYER_EXPORT VkResult VKAPI vkCreateShader(VkDevice device, const VkShaderCreateInfo *pCreateInfo,
-                                                   VkShader *pShader)
+VK_LAYER_EXPORT VkResult VKAPI vkCreateShaderModule(
+        VkDevice device,
+        const VkShaderModuleCreateInfo *pCreateInfo,
+        VkShaderModule *pShaderModule)
 {
     loader_platform_thread_lock_mutex(&globalLock);
-    VkResult res = device_dispatch_table(device)->CreateShader(device, pCreateInfo, pShader);
+    VkResult res = device_dispatch_table(device)->CreateShaderModule(device, pCreateInfo, pShaderModule);
 
-    shader_map[(VkBaseLayerObject *) *pShader] = new shader_source(pCreateInfo);
+    shader_module_map[(VkBaseLayerObject *) *pShaderModule] = new shader_module(pCreateInfo);
     loader_platform_thread_unlock_mutex(&globalLock);
     return res;
 }
 
+VK_LAYER_EXPORT VkResult VKAPI vkCreateShader(
+        VkDevice device,
+        const VkShaderCreateInfo *pCreateInfo,
+        VkShader *pShader)
+{
+    loader_platform_thread_lock_mutex(&globalLock);
+    VkResult res = device_dispatch_table(device)->CreateShader(device, pCreateInfo, pShader);
+
+    shader_object_map[(VkBaseLayerObject *) *pShader] = new shader_object(pCreateInfo);
+    loader_platform_thread_unlock_mutex(&globalLock);
+    return res;
+}
 
 static bool
-validate_interface_between_stages(shader_source const *producer, char const *producer_name,
-                                  shader_source const *consumer, char const *consumer_name,
+validate_interface_between_stages(shader_module const *producer, char const *producer_name,
+                                  shader_module const *consumer, char const *consumer_name,
                                   bool consumer_arrayed_input)
 {
     std::map<uint32_t, interface_var> outputs;
@@ -568,7 +595,7 @@
 /* characterizes a SPIR-V type appearing in an interface to a FF stage,
  * for comparison to a VkFormat's characterization above. */
 static unsigned
-get_fundamental_type(shader_source const *src, unsigned type)
+get_fundamental_type(shader_module const *src, unsigned type)
 {
     auto type_def_it = src->type_def_index.find(type);
 
@@ -625,7 +652,7 @@
 
 
 static bool
-validate_vi_against_vs_inputs(VkPipelineVertexInputStateCreateInfo const *vi, shader_source const *vs)
+validate_vi_against_vs_inputs(VkPipelineVertexInputStateCreateInfo const *vi, shader_module const *vs)
 {
     std::map<uint32_t, interface_var> inputs;
     /* we collect builtin inputs, but they will never appear in the VI state --
@@ -688,7 +715,7 @@
 
 
 static bool
-validate_fs_outputs_against_cb(shader_source const *fs, VkPipelineCbStateCreateInfo const *cb)
+validate_fs_outputs_against_cb(shader_module const *fs, VkPipelineCbStateCreateInfo const *cb)
 {
     std::map<uint32_t, interface_var> outputs;
     std::map<uint32_t, interface_var> builtin_outputs;
@@ -786,7 +813,7 @@
     /* We seem to allow pipeline stages to be specified out of order, so collect and identify them
      * before trying to do anything more: */
 
-    shader_source const *shaders[VK_SHADER_STAGE_FRAGMENT + 1];  /* exclude CS */
+    shader_module const *shaders[VK_SHADER_STAGE_FRAGMENT + 1];  /* exclude CS */
     memset(shaders, 0, sizeof(shaders));
     VkPipelineCbStateCreateInfo const *cb = 0;
     VkPipelineVertexInputStateCreateInfo const *vi = 0;
@@ -804,7 +831,8 @@
                 layerCbMsg(VK_DBG_REPORT_WARN_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_UNKNOWN_STAGE, "SC", str);
             }
             else {
-                shaders[pStage->stage] = shader_map[(void *)(pStage->shader)];
+                struct shader_object *shader = shader_object_map[(void *) pStage->shader];
+                shaders[pStage->stage] = shader->module;
             }
         }
     }
@@ -969,6 +997,7 @@
     if (!strncmp(#fn, pName, sizeof(#fn))) \
         return (void *) fn
 
+    ADD_HOOK(vkCreateShaderModule);
     ADD_HOOK(vkCreateShader);
     ADD_HOOK(vkDestroyDevice);
     ADD_HOOK(vkCreateGraphicsPipeline);
diff --git a/loader/table_ops.h b/loader/table_ops.h
index a29324f..be5f691 100644
--- a/loader/table_ops.h
+++ b/loader/table_ops.h
@@ -362,7 +362,6 @@
 
     table->CreateInstance = (PFN_vkCreateInstance) gpa(inst, "vkCreateInstance");
     table->DestroyInstance = (PFN_vkDestroyInstance) gpa(inst, "vkDestroyInstance");
-    table->CreateDevice = (PFN_vkCreateDevice) gpa(inst, "vkCreateDevice");
     table->EnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) gpa(inst, "vkEnumeratePhysicalDevices");
     table->GetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures) gpa(inst, "vkGetPhysicalDeviceFeatures");
     table->GetPhysicalDeviceFormatInfo = (PFN_vkGetPhysicalDeviceFormatInfo) gpa(inst, "vkGetPhysicalDeviceFormatInfo");
diff --git a/tests/init.cpp b/tests/init.cpp
index c1386fc..a501938 100644
--- a/tests/init.cpp
+++ b/tests/init.cpp
@@ -582,26 +582,30 @@
     pSPV->magic = ICD_SPV_MAGIC;
     pSPV->version = ICD_SPV_VERSION;
 
-//    typedef struct VkShaderCreateInfo_
-//    {
-//        VkStructureType                      sType;              // Must be VK_STRUCTURE_TYPE_SHADER_CREATE_INFO
-//        const void*                             pNext;              // Pointer to next structure
-//        size_t                                  codeSize;           // Specified in bytes
-//        const void*                             pCode;
-//        VkFlags                               flags;              // Reserved
-//    } VkShaderCreateInfo;
-
+    VkShaderModuleCreateInfo moduleCreateInfo;
+    VkShaderModule module;
     VkShaderCreateInfo createInfo;
     VkShader shader;
 
+    moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+    moduleCreateInfo.pNext = NULL;
+    moduleCreateInfo.pCode = code;
+    moduleCreateInfo.codeSize = codeSize;
+    moduleCreateInfo.flags = 0;
+    err = vkCreateShaderModule(device(), &moduleCreateInfo, &module);
+    ASSERT_VK_SUCCESS(err);
+
     createInfo.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO;
     createInfo.pNext = NULL;
-    createInfo.pCode = code;
-    createInfo.codeSize = codeSize;
+    createInfo.module = module;
+    createInfo.pName = "main";
     createInfo.flags = 0;
     err = vkCreateShader(device(), &createInfo, &shader);
     ASSERT_VK_SUCCESS(err);
 
+    err = vkDestroyObject(device(), VK_OBJECT_TYPE_SHADER_MODULE, module);
+    ASSERT_VK_SUCCESS(err);
+
     *pshader = shader;
 }
 
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 4aa594b..16b0fa9 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -1015,34 +1015,13 @@
     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, &pipeline_layout);
     ASSERT_VK_SUCCESS(err);
 
-    size_t shader_len = strlen(bindStateVertShaderText);
-    size_t codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
-    void* pCode = malloc(codeSize);
-
-    /* try version 0 first: VkShaderStage followed by GLSL */
-    ((uint32_t *) pCode)[0] = ICD_SPV_MAGIC;
-    ((uint32_t *) pCode)[1] = 0;
-    ((uint32_t *) pCode)[2] = VK_SHADER_STAGE_VERTEX;
-    memcpy(((uint32_t *) pCode + 3), bindStateVertShaderText, shader_len + 1);
-
-    const VkShaderCreateInfo vs_ci = {
-        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
-        .pNext = NULL,
-        .module = VK_NULL_HANDLE,
-        .name = "main",
-        .codeSize = codeSize,
-        .pCode = pCode,
-        .flags = 0,
-    };
-    VkShader vs;
-    err = vkCreateShader(m_device->device(), &vs_ci, &vs);
-    ASSERT_VK_SUCCESS(err);
+    VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX, this);
 
     const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
         .sType                = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
         .pNext                = NULL,
         .stage                = VK_SHADER_STAGE_VERTEX,
-        .shader               = vs,
+        .shader               = vs.obj(),
         .linkConstBufferCount = 0,
         .pLinkConstBufferInfo = NULL,
         .pSpecializationInfo  = NULL,
@@ -1298,33 +1277,13 @@
     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, &pipeline_layout);
     ASSERT_VK_SUCCESS(err);
 
-    size_t shader_len = strlen(bindStateVertShaderText);
-    size_t codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
-    void* pCode = malloc(codeSize);
-
-    /* try version 0 first: VkShaderStage followed by GLSL */
-    ((uint32_t *) pCode)[0] = ICD_SPV_MAGIC;
-    ((uint32_t *) pCode)[1] = 0;
-    ((uint32_t *) pCode)[2] = VK_SHADER_STAGE_VERTEX;
-    memcpy(((uint32_t *) pCode + 3), bindStateVertShaderText, shader_len + 1);
-
-    const VkShaderCreateInfo vs_ci = {
-        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
-        .pNext = NULL,
-        .module = VK_NULL_HANDLE,
-        .name = "main",
-        .codeSize = codeSize,
-        .pCode = pCode,
-        .flags = 0,
-    };
-    VkShader vs;
-    err = vkCreateShader(m_device->device(), &vs_ci, &vs);
+    VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX, this);
 
     const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
         .sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
         .pNext  = NULL,
         .stage                = VK_SHADER_STAGE_VERTEX,
-        .shader               = vs,
+        .shader               = vs.obj(),
         .linkConstBufferCount = 0,
         .pLinkConstBufferInfo = NULL,
         .pSpecializationInfo  = NULL,
@@ -1782,34 +1741,13 @@
     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, &pipeline_layout);
     ASSERT_VK_SUCCESS(err);
 
-    size_t shader_len = strlen(bindStateVertShaderText);
-    size_t codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
-    void* pCode = malloc(codeSize);
-
-    /* try version 0 first: VkShaderStage followed by GLSL */
-    ((uint32_t *) pCode)[0] = ICD_SPV_MAGIC;
-    ((uint32_t *) pCode)[1] = 0;
-    ((uint32_t *) pCode)[2] = VK_SHADER_STAGE_VERTEX;
-    memcpy(((uint32_t *) pCode + 3), bindStateVertShaderText, shader_len + 1);
-
-    const VkShaderCreateInfo vs_ci = {
-        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
-        .pNext = NULL,
-        .module = VK_NULL_HANDLE,
-        .name = "main",
-        .codeSize = codeSize,
-        .pCode = pCode,
-        .flags = 0,
-    };
-    VkShader vs;
-    err = vkCreateShader(m_device->device(), &vs_ci, &vs);
-    ASSERT_VK_SUCCESS(err);
+    VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX, this);
 
     const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
         .sType                = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
         .pNext                = NULL,
         .stage                = VK_SHADER_STAGE_VERTEX,
-        .shader               = vs,
+        .shader               = vs.obj(),
         .linkConstBufferCount = 0,
         .pLinkConstBufferInfo = NULL,
         .pSpecializationInfo  = NULL,
@@ -1902,29 +1840,6 @@
     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, &pipeline_layout);
     ASSERT_VK_SUCCESS(err);
 
-    size_t shader_len = strlen(bindStateVertShaderText);
-    size_t codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
-    void* pCode = malloc(codeSize);
-
-    /* try version 0 first: VkShaderStage followed by GLSL */
-    ((uint32_t *) pCode)[0] = ICD_SPV_MAGIC;
-    ((uint32_t *) pCode)[1] = 0;
-    ((uint32_t *) pCode)[2] = VK_SHADER_STAGE_VERTEX;
-    memcpy(((uint32_t *) pCode + 3), bindStateVertShaderText, shader_len + 1);
-
-    const VkShaderCreateInfo vs_ci = {
-        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
-        .pNext = NULL,
-        .module = VK_NULL_HANDLE,
-        .name = "main",
-        .codeSize = codeSize,
-        .pCode = pCode,
-        .flags = 0,
-    };
-    VkShader vs;
-    err = vkCreateShader(m_device->device(), &vs_ci, &vs);
-    ASSERT_VK_SUCCESS(err);
-
     VkPipeline badPipeline = (VkPipeline)0xbaadb1be;
     //err = vkCreateGraphicsPipeline(m_device->device(), &gp_ci, &pipeline);
     ASSERT_VK_SUCCESS(err);
@@ -2007,34 +1922,13 @@
     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, &pipeline_layout);
     ASSERT_VK_SUCCESS(err);
 
-    size_t shader_len = strlen(bindStateVertShaderText);
-    size_t codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
-    void* pCode = malloc(codeSize);
-
-    /* try version 0 first: VkShaderStage followed by GLSL */
-    ((uint32_t *) pCode)[0] = ICD_SPV_MAGIC;
-    ((uint32_t *) pCode)[1] = 0;
-    ((uint32_t *) pCode)[2] = VK_SHADER_STAGE_VERTEX;
-    memcpy(((uint32_t *) pCode + 3), bindStateVertShaderText, shader_len + 1);
-
-    const VkShaderCreateInfo vs_ci = {
-        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
-        .pNext = NULL,
-        .module = VK_NULL_HANDLE,
-        .name = "main",
-        .codeSize = codeSize,
-        .pCode = pCode,
-        .flags = 0,
-    };
-    VkShader vs;
-    err = vkCreateShader(m_device->device(), &vs_ci, &vs);
-    ASSERT_VK_SUCCESS(err);
+    VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX, this);
 
     const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
         .sType                = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
         .pNext                = NULL,
         .stage                = VK_SHADER_STAGE_VERTEX,
-        .shader               = vs,
+        .shader               = vs.obj(),
         .linkConstBufferCount = 0,
         .pLinkConstBufferInfo = NULL,
         .pSpecializationInfo  = NULL,
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index 4ee9d1f..b0c6657 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -1028,38 +1028,51 @@
     VkResult err = VK_SUCCESS;
     std::vector<unsigned int> spv;
     VkShaderCreateInfo createInfo;
+    VkShaderModuleCreateInfo moduleCreateInfo;
+    vk_testing::ShaderModule module;
     size_t shader_len;
 
     m_stage = stage;
     m_device = device;
 
+    moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+    moduleCreateInfo.pNext = NULL;
+
     createInfo.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO;
     createInfo.pNext = NULL;
 
     if (framework->m_use_glsl) {
 
         shader_len = strlen(shader_code);
-        createInfo.codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
-        createInfo.pCode = malloc(createInfo.codeSize);
-        createInfo.flags = 0;
+        moduleCreateInfo.codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
+        moduleCreateInfo.pCode = malloc(moduleCreateInfo.codeSize);
+        moduleCreateInfo.flags = 0;
 
         /* try version 0 first: VkShaderStage followed by GLSL */
-        ((uint32_t *) createInfo.pCode)[0] = ICD_SPV_MAGIC;
-        ((uint32_t *) createInfo.pCode)[1] = 0;
-        ((uint32_t *) createInfo.pCode)[2] = stage;
-        memcpy(((uint32_t *) createInfo.pCode + 3), shader_code, shader_len + 1);
+        ((uint32_t *) moduleCreateInfo.pCode)[0] = ICD_SPV_MAGIC;
+        ((uint32_t *) moduleCreateInfo.pCode)[1] = 0;
+        ((uint32_t *) moduleCreateInfo.pCode)[2] = stage;
+        memcpy(((uint32_t *) moduleCreateInfo.pCode + 3), shader_code, shader_len + 1);
 
     } else {
 
         // Use Reference GLSL to SPV compiler
         framework->GLSLtoSPV(stage, shader_code, spv);
-        createInfo.pCode = spv.data();
-        createInfo.codeSize = spv.size() * sizeof(unsigned int);
-        createInfo.flags = 0;
+        moduleCreateInfo.pCode = spv.data();
+        moduleCreateInfo.codeSize = spv.size() * sizeof(unsigned int);
+        moduleCreateInfo.flags = 0;
     }
 
-    err = init_try(*m_device, createInfo);
+    err = module.init_try(*m_device, moduleCreateInfo);
+    assert(VK_SUCCESS == err);
 
+    createInfo.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO;
+    createInfo.pNext = NULL;
+    createInfo.module = module.obj();
+    createInfo.pName = "main";
+    createInfo.flags = 0;
+
+    err = init_try(*m_device, createInfo);
     assert(VK_SUCCESS == err);
 }
 
diff --git a/tests/vktestbinding.cpp b/tests/vktestbinding.cpp
index da1c0d8..3e4c827 100644
--- a/tests/vktestbinding.cpp
+++ b/tests/vktestbinding.cpp
@@ -661,6 +661,26 @@
     alloc_memory();
 }
 
+void ShaderModule::init(const Device &dev, const VkShaderModuleCreateInfo &info)
+{
+    DERIVED_OBJECT_TYPE_INIT(vkCreateShaderModule, dev, VK_OBJECT_TYPE_SHADER_MODULE, &info);
+}
+
+VkResult ShaderModule::init_try(const Device &dev, const VkShaderModuleCreateInfo &info)
+{
+    /*
+     * Note: Cannot use DERIVED_OBJECT_TYPE_INIT as we need the
+     * return code.
+     */
+    VkShaderModule sh;
+    dev_ = &dev;
+    VkResult err = vkCreateShaderModule(dev.obj(), &info, &sh);
+    if (err == VK_SUCCESS)
+        Object::init(sh, VK_OBJECT_TYPE_SHADER_MODULE);
+
+    return err;
+}
+
 void Shader::init(const Device &dev, const VkShaderCreateInfo &info)
 {
     DERIVED_OBJECT_TYPE_INIT(vkCreateShader, dev, VK_OBJECT_TYPE_SHADER, &info);
diff --git a/tests/vktestbinding.h b/tests/vktestbinding.h
index 7475359..e55586b 100644
--- a/tests/vktestbinding.h
+++ b/tests/vktestbinding.h
@@ -481,13 +481,22 @@
     void init(const Device &dev, const VkDepthStencilViewCreateInfo &info);
 };
 
+class ShaderModule : public DerivedObject<VkShaderModule, Object, VK_OBJECT_TYPE_SHADER_MODULE> {
+public:
+    // vkCreateShaderModule()
+    void init(const Device &dev, const VkShaderModuleCreateInfo &info);
+    VkResult init_try(const Device &dev, const VkShaderModuleCreateInfo &info);
+
+    static VkShaderModuleCreateInfo create_info(size_t code_size, const void *code, VkFlags flags);
+};
+
 class Shader : public DerivedObject<VkShader, Object, VK_OBJECT_TYPE_SHADER> {
 public:
     // vkCreateShader()
     void init(const Device &dev, const VkShaderCreateInfo &info);
     VkResult init_try(const Device &dev, const VkShaderCreateInfo &info);
 
-    static VkShaderCreateInfo create_info(size_t code_size, const void *code, VkFlags flags);
+    static VkShaderCreateInfo create_info(VkShaderModule module, const char *pName, VkFlags flags);
 };
 
 class Pipeline : public DerivedObject<VkPipeline, Object, VK_OBJECT_TYPE_PIPELINE> {
@@ -758,12 +767,22 @@
     return Image::extent(width, height, depth);
 }
 
-inline VkShaderCreateInfo Shader::create_info(size_t code_size, const void *code, VkFlags flags)
+inline VkShaderModuleCreateInfo ShaderModule::create_info(size_t code_size, const void *code, VkFlags flags)
+{
+    VkShaderModuleCreateInfo info = {};
+    info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+    info.codeSize = code_size;
+    info.pCode = code;
+    info.flags = flags;
+    return info;
+}
+
+inline VkShaderCreateInfo Shader::create_info(VkShaderModule module, const char *pName, VkFlags flags)
 {
     VkShaderCreateInfo info = {};
     info.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO;
-    info.codeSize = code_size;
-    info.pCode = code;
+    info.module = module;
+    info.pName = pName;
     info.flags = flags;
     return info;
 }
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index 34340b5..f2804f6 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -1102,6 +1102,7 @@
             obj_type_mapping[objectName] = ucc_to_U_C_C(objectTypeEnum);
         # Command Buffer Object doesn't follow the rule.
         obj_type_mapping['VkCmdBuffer'] = "VK_OBJECT_TYPE_COMMAND_BUFFER"
+        obj_type_mapping['VkShaderModule'] = "VK_OBJECT_TYPE_SHADER_MODULE"
 
         explicit_object_tracker_functions = [
             "CreateInstance",