layers: Update unique_objects to make use of safe_structs
authorTobin Ehlis <tobine@google.com>
Wed, 10 Feb 2016 22:38:45 +0000 (15:38 -0700)
committerTobin Ehlis <tobine@google.com>
Thu, 11 Feb 2016 23:31:56 +0000 (16:31 -0700)
Stop overwriting const* data in unique_objects.
Instead, declare local safe_struct copies of data, update that
data in place with unwrapped objects, and pass down the local
safe_struct copy, which spoofs the original struct layout.

This includes code to build the layer using vk_safe_struct.h/cpp files.

buildAndroid/jni/Android.mk
layers/CMakeLists.txt
layers/unique_objects.h
vk-layer-generate.py

index bccb6458bcc7c9f93564a7b97b4f983a9de4e59b..ca9294bd146c0ca5e0e7589ccc55abb37fb49f27 100644 (file)
@@ -119,6 +119,7 @@ include $(BUILD_SHARED_LIBRARY)
 include $(CLEAR_VARS)\r
 LOCAL_MODULE := VkLayer_unique_objects\r
 LOCAL_SRC_FILES += $(SRC_DIR)/buildAndroid/generated/unique_objects.cpp\r
+LOCAL_SRC_FILES += $(SRC_DIR)/buildAndroid/generated/vk_safe_struct.cpp\r
 LOCAL_SRC_FILES += $(SRC_DIR)/layers/vk_layer_table.cpp\r
 LOCAL_C_INCLUDES += $(SRC_DIR)/include \\r
                     $(SRC_DIR)/layers \\r
index 391ac295b28133580fa269fd087731b1eece2803..7c26fb4721ec02aa8063740576a21eaebd115ecc 100644 (file)
@@ -126,6 +126,8 @@ run_vk_helper(gen_struct_wrappers
     vk_struct_size_helper.c
        vk_struct_wrappers.h
        vk_struct_wrappers.cpp
+    vk_safe_struct.h
+    vk_safe_struct.cpp
 )
 
 add_custom_target(generate_vk_layer_helpers DEPENDS
@@ -139,6 +141,8 @@ add_custom_target(generate_vk_layer_helpers DEPENDS
     vk_struct_size_helper.c
        vk_struct_wrappers.h
        vk_struct_wrappers.cpp
+    vk_safe_struct.h
+    vk_safe_struct.cpp
 )
 
 run_vk_layer_generate(object_tracker object_tracker.cpp)
@@ -163,4 +167,4 @@ add_vk_layer(swapchain swapchain.cpp vk_layer_table.cpp)
 # generated
 add_vk_layer(object_tracker object_tracker.cpp vk_layer_table.cpp)
 add_vk_layer(threading threading.cpp thread_check.h vk_layer_table.cpp)
-add_vk_layer(unique_objects unique_objects.cpp vk_layer_table.cpp)
+add_vk_layer(unique_objects unique_objects.cpp vk_layer_table.cpp vk_safe_struct.cpp)
index 0c65d7098d286e9cf56e8933da5f8ef85a32e58d..3ce6ddae3b7b991b98d75fa933f3bb9d0e058665 100644 (file)
@@ -42,6 +42,7 @@
 #include "vk_layer_data.h"
 #include "vk_layer_logging.h"
 #include "vk_layer_extension_utils.h"
+#include "vk_safe_struct.h"
 
 struct layer_data {
     bool wsi_enabled;
@@ -424,50 +425,31 @@ VkResult explicit_QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const V
 
 VkResult explicit_CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines)
 {
-// UNWRAP USES:
-//  0 : pipelineCache,VkPipelineCache, pCreateInfos[createInfoCount]->stage[0]->module,VkShaderModule, pCreateInfos[createInfoCount]->layout,VkPipelineLayout, pCreateInfos[createInfoCount]->basePipelineHandle,VkPipeline
-    if (VK_NULL_HANDLE != pipelineCache) {
-        pipelineCache = (VkPipelineCache)((VkUniqueObject*)pipelineCache)->actualObject;
-    }
-    std::vector<VkShaderModule> original_module = {};
-    std::vector<VkPipelineLayout> original_layout = {};
-    std::vector<VkPipeline> original_basePipelineHandle = {};
+// STRUCT USES:{'pipelineCache': 'VkPipelineCache', 'pCreateInfos[createInfoCount]': {'stage': {'module': 'VkShaderModule'}, 'layout': 'VkPipelineLayout', 'basePipelineHandle': 'VkPipeline'}}
+//LOCAL DECLS:{'pCreateInfos': 'VkComputePipelineCreateInfo*'}
+    safe_VkComputePipelineCreateInfo* local_pCreateInfos = NULL;
     if (pCreateInfos) {
-        for (uint32_t index0=0; index0<createInfoCount; ++index0) {
-            if (pCreateInfos[index0].stage.module) {
-                VkShaderModule* pShaderModule = (VkShaderModule*)&(pCreateInfos[index0].stage.module);
-                original_module.push_back(pCreateInfos[index0].stage.module);
-                *(pShaderModule) = (VkShaderModule)((VkUniqueObject*)pCreateInfos[index0].stage.module)->actualObject;
+        local_pCreateInfos = new safe_VkComputePipelineCreateInfo[createInfoCount];
+        for (uint32_t idx0=0; idx0<createInfoCount; ++idx0) {
+            local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
+            if (pCreateInfos[idx0].basePipelineHandle) {
+                local_pCreateInfos[idx0].basePipelineHandle = (VkPipeline)((VkUniqueObject*)pCreateInfos[idx0].basePipelineHandle)->actualObject;
             }
-            if (pCreateInfos[index0].layout) {
-                VkPipelineLayout* pPipelineLayout = (VkPipelineLayout*)&(pCreateInfos[index0].layout);
-                original_layout.push_back(pCreateInfos[index0].layout);
-                *(pPipelineLayout) = (VkPipelineLayout)((VkUniqueObject*)pCreateInfos[index0].layout)->actualObject;
+            if (pCreateInfos[idx0].layout) {
+                local_pCreateInfos[idx0].layout = (VkPipelineLayout)((VkUniqueObject*)pCreateInfos[idx0].layout)->actualObject;
             }
-            if (pCreateInfos[index0].basePipelineHandle) {
-                VkPipeline* pPipeline = (VkPipeline*)&(pCreateInfos[index0].basePipelineHandle);
-                original_basePipelineHandle.push_back(pCreateInfos[index0].basePipelineHandle);
-                *(pPipeline) = (VkPipeline)((VkUniqueObject*)pCreateInfos[index0].basePipelineHandle)->actualObject;
+            if (pCreateInfos[idx0].stage.module) {
+                local_pCreateInfos[idx0].stage.module = (VkShaderModule)((VkUniqueObject*)pCreateInfos[idx0].stage.module)->actualObject;
             }
         }
     }
-    VkResult result = get_dispatch_table(unique_objects_device_table_map, device)->CreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
-    if (pCreateInfos) {
-        for (uint32_t index0=0; index0<createInfoCount; ++index0) {
-            if (pCreateInfos[index0].stage.module) {
-                VkShaderModule* pShaderModule = (VkShaderModule*)&(pCreateInfos[index0].stage.module);
-                *(pShaderModule) = original_module[index0];
-            }
-            if (pCreateInfos[index0].layout) {
-                VkPipelineLayout* pPipelineLayout = (VkPipelineLayout*)&(pCreateInfos[index0].layout);
-                *(pPipelineLayout) = original_layout[index0];
-            }
-            if (pCreateInfos[index0].basePipelineHandle) {
-                VkPipeline* pPipeline = (VkPipeline*)&(pCreateInfos[index0].basePipelineHandle);
-                *(pPipeline) = original_basePipelineHandle[index0];
-            }
-        }
+    if (pipelineCache) {
+        pipelineCache = (VkPipelineCache)((VkUniqueObject*)pipelineCache)->actualObject;
     }
+// CODEGEN : file /usr/local/google/home/tobine/vulkan_work/LoaderAndTools/vk-layer-generate.py line #1671
+    VkResult result = get_dispatch_table(unique_objects_device_table_map, device)->CreateComputePipelines(device, pipelineCache, createInfoCount, (const VkComputePipelineCreateInfo*)local_pCreateInfos, pAllocator, pPipelines);
+    if (local_pCreateInfos)
+        delete[] local_pCreateInfos;
     if (VK_SUCCESS == result) {
         VkUniqueObject* pUO = NULL;
         for (uint32_t i=0; i<createInfoCount; ++i) {
@@ -481,68 +463,38 @@ VkResult explicit_CreateComputePipelines(VkDevice device, VkPipelineCache pipeli
 
 VkResult explicit_CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines)
 {
-// UNWRAP USES:
-//  0 : pipelineCache,VkPipelineCache, pCreateInfos[createInfoCount]->pStages[stageCount]->module,VkShaderModule, pCreateInfos[createInfoCount]->layout,VkPipelineLayout, pCreateInfos[createInfoCount]->renderPass,VkRenderPass, pCreateInfos[createInfoCount]->basePipelineHandle,VkPipeline
-    if (VK_NULL_HANDLE != pipelineCache) {
-        pipelineCache = (VkPipelineCache)((VkUniqueObject*)pipelineCache)->actualObject;
-    }
-    std::vector<VkShaderModule> original_module = {};
-    std::vector<VkPipelineLayout> original_layout = {};
-    std::vector<VkRenderPass> original_renderPass = {};
-    std::vector<VkPipeline> original_basePipelineHandle = {};
+// STRUCT USES:{'pipelineCache': 'VkPipelineCache', 'pCreateInfos[createInfoCount]': {'layout': 'VkPipelineLayout', 'pStages[stageCount]': {'module': 'VkShaderModule'}, 'renderPass': 'VkRenderPass', 'basePipelineHandle': 'VkPipeline'}}
+//LOCAL DECLS:{'pCreateInfos': 'VkGraphicsPipelineCreateInfo*'}
+    safe_VkGraphicsPipelineCreateInfo* local_pCreateInfos = NULL;
     if (pCreateInfos) {
-        for (uint32_t index0=0; index0<createInfoCount; ++index0) {
-            if (pCreateInfos[index0].pStages) {
-                for (uint32_t index1=0; index1<pCreateInfos[index0].stageCount; ++index1) {
-                    if (pCreateInfos[index0].pStages[index1].module) {
-                        VkShaderModule* pShaderModule = (VkShaderModule*)&(pCreateInfos[index0].pStages[index1].module);
-                        original_module.push_back(pCreateInfos[index0].pStages[index1].module);
-                        *(pShaderModule) = (VkShaderModule)((VkUniqueObject*)pCreateInfos[index0].pStages[index1].module)->actualObject;
-                    }
-                }
-            }
-            if (pCreateInfos[index0].layout) {
-                VkPipelineLayout* pPipelineLayout = (VkPipelineLayout*)&(pCreateInfos[index0].layout);
-                original_layout.push_back(pCreateInfos[index0].layout);
-                *(pPipelineLayout) = (VkPipelineLayout)((VkUniqueObject*)pCreateInfos[index0].layout)->actualObject;
+        local_pCreateInfos = new safe_VkGraphicsPipelineCreateInfo[createInfoCount];
+        for (uint32_t idx0=0; idx0<createInfoCount; ++idx0) {
+            local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
+            if (pCreateInfos[idx0].basePipelineHandle) {
+                local_pCreateInfos[idx0].basePipelineHandle = (VkPipeline)((VkUniqueObject*)pCreateInfos[idx0].basePipelineHandle)->actualObject;
             }
-            if (pCreateInfos[index0].renderPass) {
-                VkRenderPass* pRenderPass = (VkRenderPass*)&(pCreateInfos[index0].renderPass);
-                original_renderPass.push_back(pCreateInfos[index0].renderPass);
-                *(pRenderPass) = (VkRenderPass)((VkUniqueObject*)pCreateInfos[index0].renderPass)->actualObject;
+            if (pCreateInfos[idx0].layout) {
+                local_pCreateInfos[idx0].layout = (VkPipelineLayout)((VkUniqueObject*)pCreateInfos[idx0].layout)->actualObject;
             }
-            if (pCreateInfos[index0].basePipelineHandle) {
-                VkPipeline* pPipeline = (VkPipeline*)&(pCreateInfos[index0].basePipelineHandle);
-                original_basePipelineHandle.push_back(pCreateInfos[index0].basePipelineHandle);
-                *(pPipeline) = (VkPipeline)((VkUniqueObject*)pCreateInfos[index0].basePipelineHandle)->actualObject;
-            }
-        }
-    }
-    VkResult result = get_dispatch_table(unique_objects_device_table_map, device)->CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
-    if (pCreateInfos) {
-        for (uint32_t index0=0; index0<createInfoCount; ++index0) {
-            if (pCreateInfos[index0].pStages) {
-                for (uint32_t index1=0; index1<pCreateInfos[index0].stageCount; ++index1) {
-                    if (pCreateInfos[index0].pStages[index1].module) {
-                        VkShaderModule* pShaderModule = (VkShaderModule*)&(pCreateInfos[index0].pStages[index1].module);
-                        *(pShaderModule) = original_module[index1];
+            if (pCreateInfos[idx0].pStages) {
+                for (uint32_t idx1=0; idx1<pCreateInfos[idx0].stageCount; ++idx1) {
+                    if (pCreateInfos[idx0].pStages[idx1].module) {
+                        local_pCreateInfos[idx0].pStages[idx1].module = (VkShaderModule)((VkUniqueObject*)pCreateInfos[idx0].pStages[idx1].module)->actualObject;
                     }
                 }
             }
-            if (pCreateInfos[index0].layout) {
-                VkPipelineLayout* pPipelineLayout = (VkPipelineLayout*)&(pCreateInfos[index0].layout);
-                *(pPipelineLayout) = original_layout[index0];
-            }
-            if (pCreateInfos[index0].renderPass) {
-                VkRenderPass* pRenderPass = (VkRenderPass*)&(pCreateInfos[index0].renderPass);
-                *(pRenderPass) = original_renderPass[index0];
-            }
-            if (pCreateInfos[index0].basePipelineHandle) {
-                VkPipeline* pPipeline = (VkPipeline*)&(pCreateInfos[index0].basePipelineHandle);
-                *(pPipeline) = original_basePipelineHandle[index0];
+            if (pCreateInfos[idx0].renderPass) {
+                local_pCreateInfos[idx0].renderPass = (VkRenderPass)((VkUniqueObject*)pCreateInfos[idx0].renderPass)->actualObject;
             }
         }
     }
+    if (pipelineCache) {
+        pipelineCache = (VkPipelineCache)((VkUniqueObject*)pipelineCache)->actualObject;
+    }
+// CODEGEN : file /usr/local/google/home/tobine/vulkan_work/LoaderAndTools/vk-layer-generate.py line #1671
+    VkResult result = get_dispatch_table(unique_objects_device_table_map, device)->CreateGraphicsPipelines(device, pipelineCache, createInfoCount, (const VkGraphicsPipelineCreateInfo*)local_pCreateInfos, pAllocator, pPipelines);
+    if (local_pCreateInfos)
+        delete[] local_pCreateInfos;
     if (VK_SUCCESS == result) {
         VkUniqueObject* pUO = NULL;
         for (uint32_t i=0; i<createInfoCount; ++i) {
index 5fed8791ab6751702912c2f11cbc5ee7b4153691..ebeddd138c5e711d685d23026689f9f335eb2537 100755 (executable)
@@ -137,6 +137,7 @@ def gather_object_uses_in_struct(obj_list, struct_type):
 # TODO : This analysis could be done up-front at vk_helper time
 def get_object_uses(obj_list, params):
     obj_uses = {}
+    local_decls = {}
     param_count = 'NONE' # track params that give array sizes
     for p in params:
         base_type = p.ty.replace('const ', '').strip('*')
@@ -144,11 +145,15 @@ def get_object_uses(obj_list, params):
         is_ptr = False
         if 'count' in p.name.lower():
             param_count = p.name
+        ptr_txt = ''
         if '*' in p.ty:
             is_ptr = True
+            ptr_txt = '*'
         if base_type in obj_list:
             if is_ptr and 'const' in p.ty and param_count != 'NONE':
                 array_len = "[%s]" % param_count
+                # Non-arrays we can overwrite in place, but need local decl for arrays
+                local_decls[p.name] = '%s%s' % (base_type, ptr_txt)
             #if array_len not in obj_uses:
             #    obj_uses[array_len] = {}
             # obj_uses[array_len][p.name] = base_type
@@ -160,7 +165,9 @@ def get_object_uses(obj_list, params):
             struct_uses = gather_object_uses_in_struct(obj_list, base_type)
             if len(struct_uses) > 0:
                 obj_uses[struct_name] = struct_uses
-    return obj_uses
+                # This is a top-level struct w/ uses below it, so need local decl
+                local_decls['%s' % (p.name)] = '%s%s' % (base_type, ptr_txt)
+    return (obj_uses, local_decls)
 
 class Subcommand(object):
     def __init__(self, argv):
@@ -1286,7 +1293,7 @@ class ObjectTrackerSubcommand(Subcommand):
         if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
             create_func = True
             last_param_index = -1 # For create funcs don't validate last object
-        struct_uses = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index])
+        (struct_uses, local_decls) = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index])
         funcs = []
         mutex_unlock = False
         funcs.append('%s\n' % self.lineinfo.get())
@@ -1426,7 +1433,7 @@ class UniqueObjectsSubcommand(Subcommand):
     # vector_name_set is used to make sure we don't replicate vector names
     # first_level_param indicates if elements are passed directly into the function else they're below a ptr/struct
     # TODO : Comment this code
-    def _gen_obj_code(self, struct_uses, indent, prefix, array_index, vector_name_set, first_level_param):
+    def _gen_obj_code(self, struct_uses, param_type, indent, prefix, array_index, vector_name_set, first_level_param):
         decls = ''
         pre_code = ''
         post_code = ''
@@ -1444,85 +1451,77 @@ class UniqueObjectsSubcommand(Subcommand):
                 name = '%s%s' % (prefix, name)
                 if ptr_type:
                     pre_code += '%sif (%s) {\n' % (indent, name)
-                    post_code += '%sif (%s) {\n' % (indent, name)
                     indent += '    '
                 if array != '':
                     idx = 'idx%s' % str(array_index)
                     array_index += 1
+                    if first_level_param and name in param_type:
+                        pre_code += '%slocal_%s = new safe_%s[%s];\n' % (indent, name, param_type[name].strip('*'), array)
+                        post_code += '    if (local_%s)\n' % (name)
+                        post_code += '        delete[] local_%s;\n' % (name)
                     pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
-                    post_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
                     indent += '    '
+                    if first_level_param:
+                        pre_code += '%slocal_%s[%s].initialize(&%s[%s]);\n' % (indent, name, idx, name, idx)
                     local_prefix = '%s[%s].' % (name, idx)
                 elif ptr_type:
+                    if first_level_param and name in param_type:
+                        pre_code += '%slocal_%s = new safe_%s(%s);\n' % (indent, name, param_type[name].strip('*'), name)
+                        post_code += '    if (local_%s)\n' % (name)
+                        post_code += '        delete local_%s;\n' % (name)
                     local_prefix = '%s->' % (name)
                 else:
                     local_prefix = '%s.' % (name)
                 assert isinstance(decls, object)
-                (tmp_decl, tmp_pre, tmp_post) = self._gen_obj_code(struct_uses[obj], indent, local_prefix, array_index, vector_name_set, False)
+                (tmp_decl, tmp_pre, tmp_post) = self._gen_obj_code(struct_uses[obj], param_type, indent, local_prefix, array_index, vector_name_set, False)
                 decls += tmp_decl
                 pre_code += tmp_pre
                 post_code += tmp_post
                 if array != '':
                     indent = indent[4:]
                     pre_code += '%s}\n' % (indent)
-                    post_code += '%s}\n' % (indent)
                 if ptr_type:
                     indent = indent[4:]
                     pre_code += '%s}\n' % (indent)
-                    post_code += '%s}\n' % (indent)
             else:
                 if (array_index > 0) or array != '': # TODO : This is not ideal, really want to know if we're anywhere under an array
+                    if first_level_param:
+                        pre_code += '%s%s* local_%s = NULL;\n' % (indent, struct_uses[obj], name)
                     pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
-                    post_code += '%sif (%s%s) {\n' %(indent, prefix, name)
                     indent += '    '
-                    # Append unique_count to make sure name is unique (some aliasing for "buffer" and "image" names
-                    vec_name = 'original_%s' % (name)
                     if array != '':
                         idx = 'idx%s' % str(array_index)
                         array_index += 1
+                        if first_level_param:
+                            pre_code += '%slocal_%s = new %s[%s];\n' % (indent, name, struct_uses[obj], array)
+                            post_code += '    if (local_%s)\n' % (name)
+                            post_code += '        delete[] local_%s;\n' % (name)
                         pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
-                        post_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
                         indent += '    '
                         name = '%s[%s]' % (name, idx)
                     pName = 'p%s' % (struct_uses[obj][2:])
-                    pre_code += '%s%s* %s = (%s*)&(%s%s);\n' % (indent, struct_uses[obj], pName, struct_uses[obj], prefix, name)
-                    post_code += '%s%s* %s = (%s*)&(%s%s);\n' % (indent, struct_uses[obj], pName, struct_uses[obj], prefix, name)
                     if name not in vector_name_set:
                         vector_name_set.add(name)
-                        decls += '    std::vector<%s> %s = {};\n' % (struct_uses[obj], vec_name)
-                    pre_code += '%s%s.push_back(%s%s);\n' % (indent, vec_name, prefix, name)
-                    pre_code += '%s*(%s) = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, pName, struct_uses[obj], prefix, name)
-                    post_code += '%s*(%s) = %s.front();\n' % (indent, pName, vec_name)
-                    post_code += '%s%s.erase(%s.begin());\n' % (indent, vec_name, vec_name)
+                    pre_code += '%slocal_%s%s = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, prefix, name, struct_uses[obj], prefix, name)
                     if array != '':
                         indent = indent[4:]
                         pre_code += '%s}\n' % (indent)
-                        post_code += '%s}\n' % (indent)
                     indent = indent[4:]
                     pre_code += '%s}\n' % (indent)
-                    post_code += '%s}\n' % (indent)
                 else:
+                    pre_code += '%s\n' % (self.lineinfo.get())
                     pre_code += '%sif (%s%s) {\n' %(indent, prefix, name)
                     indent += '    '
                     deref_txt = '&'
                     if ptr_type:
                         deref_txt = ''
-                    pre_code += '%s%s* p%s = (%s*)%s%s%s;\n' % (indent, struct_uses[obj], name, struct_uses[obj], deref_txt, prefix, name)
-                    pre_code += '%s*p%s = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, name, struct_uses[obj], prefix, name)
+                    if '->' in prefix: # need to update local struct
+                        pre_code += '%slocal_%s%s = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, prefix, name, struct_uses[obj], prefix, name)
+                    else:
+                        pre_code += '%s%s* p%s = (%s*)%s%s%s;\n' % (indent, struct_uses[obj], name, struct_uses[obj], deref_txt, prefix, name)
+                        pre_code += '%s*p%s = (%s)((VkUniqueObject*)%s%s)->actualObject;\n' % (indent, name, struct_uses[obj], prefix, name)
                     indent = indent[4:]
                     pre_code += '%s}\n' % (indent)
-                    if not first_level_param: # embedded in a ptr/struct so need to undo the update
-                        if '->' in prefix:
-                            # Since this variable is embedded under a ptr, need to decl up front, but wait
-                            #  to assign it inside of the "if" block(s) for surrounding ptr(s)
-                            decls += '    %s local_%s = VK_NULL_HANDLE;\n' % (struct_uses[obj], name)
-                            pre_code = '%slocal_%s = %s%s;\n%s' % (indent, name, prefix, name, pre_code)
-                        else:
-                            decls += '    %s local_%s = %s%s;\n' % (struct_uses[obj], name, prefix, name)
-                        post_code += '%sif (%s%s) {\n' %(indent, prefix, name)
-                        post_code += '%s    %s* p%s = (%s*)%s%s%s;\n' % (indent, struct_uses[obj], name, struct_uses[obj], deref_txt, prefix, name)
-                        post_code += '%s    *p%s = local_%s;\n' % (indent, name, name)
-                        post_code += '%s}\n' % (indent)
         return decls, pre_code, post_code
 
     def generate_intercept(self, proto, qual):
@@ -1540,7 +1539,8 @@ class UniqueObjectsSubcommand(Subcommand):
                                              'CreateInstance',
                                              'CreateDevice',
                                              'CreateComputePipelines',
-                                             'CreateGraphicsPipelines']
+                                             'CreateGraphicsPipelines'
+                                             ]
         # TODO : This is hacky, need to make this a more general-purpose solution for all layers
         ifdef_dict = {'CreateXcbSurfaceKHR': 'VK_USE_PLATFORM_XCB_KHR'}
         # Give special treatment to create functions that return multiple new objects
@@ -1561,16 +1561,25 @@ class UniqueObjectsSubcommand(Subcommand):
                 destroy_func = True
 
         # First thing we need to do is gather uses of non-dispatchable-objects (ndos)
-        struct_uses = get_object_uses(vulkan.object_non_dispatch_list, proto.params[1:last_param_index])
+        (struct_uses, local_decls) = get_object_uses(vulkan.object_non_dispatch_list, proto.params[1:last_param_index])
 
         if len(struct_uses) > 0:
             pre_call_txt += '// STRUCT USES:%s\n' % struct_uses
+            if len(local_decls) > 0:
+                pre_call_txt += '//LOCAL DECLS:%s\n' % local_decls
             if destroy_func: # only one object
                 for del_obj in struct_uses:
                     pre_call_txt += '%s%s local_%s = %s;\n' % (indent, struct_uses[del_obj], del_obj, del_obj)
-            (pre_decl, pre_code, post_code) = self._gen_obj_code(struct_uses, '    ', '', 0, set(), True)
+            (pre_decl, pre_code, post_code) = self._gen_obj_code(struct_uses, local_decls, '    ', '', 0, set(), True)
+            # This is a bit hacky but works for now. Need to decl local versions of top-level structs
+            for ld in local_decls:
+                init_null_txt = 'NULL';
+                if '*' not in local_decls[ld]:
+                    init_null_txt = '{}';
+                if local_decls[ld].strip('*') not in vulkan.object_non_dispatch_list:
+                    pre_decl += '    safe_%s local_%s = %s;\n' % (local_decls[ld], ld, init_null_txt)
             pre_call_txt += '%s%s' % (pre_decl, pre_code)
-            post_call_txt += post_code
+            post_call_txt += '%s' % (post_code)
         elif create_func:
             base_type = proto.params[-1].ty.replace('const ', '').strip('*')
             if base_type not in vulkan.object_non_dispatch_list:
@@ -1626,6 +1635,9 @@ class UniqueObjectsSubcommand(Subcommand):
                 post_call_txt = '%sdelete (VkUniqueObject*)local_%s;\n' % (indent, proto.params[-2].name)
 
         call_sig = proto.c_call()
+        # Replace default params with any custom local params
+        for ld in local_decls:
+            call_sig = call_sig.replace(ld, '(const %s)local_%s' % (local_decls[ld], ld))
         if proto_is_global(proto):
             table_type = "instance"
         else: