for (i = 0; i < count; i++) {
pipe_state.push_back(std::unique_ptr<PIPELINE_STATE>(new PIPELINE_STATE));
- pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i]);
pipe_state[i]->render_pass_ci.initialize(GetRenderPassState(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr());
+ pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i]);
pipe_state[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout);
}
pipeline_layout() {}
void initGraphicsPipeline(const VkGraphicsPipelineCreateInfo *pCreateInfo) {
- graphicsPipelineCI.initialize(pCreateInfo);
+ bool uses_color_attachment = false;
+ bool uses_depthstencil_attachment = false;
+ if (pCreateInfo->subpass < render_pass_ci.subpassCount) {
+ const auto &subpass = render_pass_ci.pSubpasses[pCreateInfo->subpass];
+
+ for (uint32_t i = 0; i < subpass.colorAttachmentCount; ++i) {
+ if (subpass.pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) {
+ uses_color_attachment = true;
+ break;
+ }
+ }
+
+ if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
+ uses_depthstencil_attachment = true;
+ }
+ }
+ graphicsPipelineCI.initialize(pCreateInfo, uses_color_attachment, uses_depthstencil_attachment);
// Make sure compute pipeline is null
VkComputePipelineCreateInfo emptyComputeCI = {};
computePipelineCI.initialize(&emptyComputeCI);
this->duplicate_shaders |= this->active_shaders & pPSSCI->stage;
this->active_shaders |= pPSSCI->stage;
}
- if (pCreateInfo->pVertexInputState) {
- const VkPipelineVertexInputStateCreateInfo *pVICI = pCreateInfo->pVertexInputState;
+ if (graphicsPipelineCI.pVertexInputState) {
+ const auto pVICI = graphicsPipelineCI.pVertexInputState;
if (pVICI->vertexBindingDescriptionCount) {
this->vertexBindingDescriptions = std::vector<VkVertexInputBindingDescription>(
pVICI->pVertexBindingDescriptions, pVICI->pVertexBindingDescriptions + pVICI->vertexBindingDescriptionCount);
}
}
- if (pCreateInfo->pColorBlendState) {
- const VkPipelineColorBlendStateCreateInfo *pCBCI = pCreateInfo->pColorBlendState;
+ if (graphicsPipelineCI.pColorBlendState) {
+ const auto pCBCI = graphicsPipelineCI.pColorBlendState;
if (pCBCI->attachmentCount) {
this->attachments = std::vector<VkPipelineColorBlendAttachmentState>(pCBCI->pAttachments,
pCBCI->pAttachments + pCBCI->attachmentCount);
computePipelineCI.initialize(pCreateInfo);
// Make sure gfx pipeline is null
VkGraphicsPipelineCreateInfo emptyGraphicsCI = {};
- graphicsPipelineCI.initialize(&emptyGraphicsCI);
+ graphicsPipelineCI.initialize(&emptyGraphicsCI, false, false);
switch (computePipelineCI.stage.stage) {
case VK_SHADER_STAGE_COMPUTE_BIT:
this->active_shaders |= VK_SHADER_STAGE_COMPUTE_BIT;
#include <cstdlib>
#include <string>
#include <bitset>
-#include <mutex>
+#include <unordered_map>
#include <unordered_set>
+#include <mutex>
#include "vulkan/vulkan.h"
#include "vk_enum_string_helper.h"
VkDevice device = VK_NULL_HANDLE;
DeviceExtensions extensions;
+ struct SubpassesUsageStates {
+ std::unordered_set<uint32_t> subpasses_using_color_attachment;
+ std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
+ };
+
+ std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
+
VkLayerDispatchTable dispatch_table = {};
};
const VkAllocationCallbacks *pAllocator);
extern bool parameter_validation_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool);
+extern bool parameter_validation_vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
+extern bool parameter_validation_vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
+ const VkAllocationCallbacks *pAllocator);
// TODO : This can be much smarter, using separate locks for separate global data
std::mutex global_lock;
return result;
}
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
+ layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ bool skip = false;
+ VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
+
+ {
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= parameter_validation_vkCreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
+
+ typedef bool (*PFN_manual_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
+ PFN_manual_vkCreateRenderPass custom_func = (PFN_manual_vkCreateRenderPass)custom_functions["vkCreateRenderPass"];
+ if (custom_func != nullptr) {
+ skip |= custom_func(device, pCreateInfo, pAllocator, pRenderPass);
+ }
+ }
+
+ if (!skip) {
+ result = device_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
+
+ // track the state necessary for checking vkCreateGraphicsPipeline (subpass usage of depth and color attachments)
+ if (result == VK_SUCCESS) {
+ std::unique_lock<std::mutex> lock(global_lock);
+ const auto renderPass = *pRenderPass;
+ auto &renderpass_state = device_data->renderpasses_states[renderPass];
+
+ for (uint32_t subpass = 0; subpass < pCreateInfo->subpassCount; ++subpass) {
+ bool uses_color = false;
+ for (uint32_t i = 0; i < pCreateInfo->pSubpasses[subpass].colorAttachmentCount && !uses_color; ++i)
+ if (pCreateInfo->pSubpasses[subpass].pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) uses_color = true;
+
+ bool uses_depthstencil = false;
+ if (pCreateInfo->pSubpasses[subpass].pDepthStencilAttachment)
+ if (pCreateInfo->pSubpasses[subpass].pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
+ uses_depthstencil = true;
+
+ if (uses_color) renderpass_state.subpasses_using_color_attachment.insert(subpass);
+ if (uses_depthstencil) renderpass_state.subpasses_using_depthstencil_attachment.insert(subpass);
+ }
+ }
+ }
+ return result;
+}
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
+ layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ bool skip = false;
+
+ {
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= parameter_validation_vkDestroyRenderPass(device, renderPass, pAllocator);
+
+ typedef bool (*PFN_manual_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass,
+ const VkAllocationCallbacks *pAllocator);
+ PFN_manual_vkDestroyRenderPass custom_func = (PFN_manual_vkDestroyRenderPass)custom_functions["vkDestroyRenderPass"];
+ if (custom_func != nullptr) {
+ skip |= custom_func(device, renderPass, pAllocator);
+ }
+ }
+
+ if (!skip) {
+ device_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator);
+
+ // track the state necessary for checking vkCreateGraphicsPipeline (subpass usage of depth and color attachments)
+ {
+ std::unique_lock<std::mutex> lock(global_lock);
+ device_data->renderpasses_states.erase(renderPass);
+ }
+ }
+}
+
bool pv_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
VkBuffer *pBuffer) {
bool skip = false;
}
}
- // TODO: Conditional NULL check based on subpass depth/stencil attachment
- if (pCreateInfos[i].pDepthStencilState != nullptr) {
+ bool uses_color_attachment = false;
+ bool uses_depthstencil_attachment = false;
+ {
+ const auto subpasses_uses_it = device_data->renderpasses_states.find(pCreateInfos[i].renderPass);
+ if (subpasses_uses_it != device_data->renderpasses_states.end()) {
+ const auto &subpasses_uses = subpasses_uses_it->second;
+ if (subpasses_uses.subpasses_using_color_attachment.count(pCreateInfos[i].subpass))
+ uses_color_attachment = true;
+ if (subpasses_uses.subpasses_using_depthstencil_attachment.count(pCreateInfos[i].subpass))
+ uses_depthstencil_attachment = true;
+ }
+ }
+
+ if (pCreateInfos[i].pDepthStencilState != nullptr && uses_depthstencil_attachment) {
skip |= validate_struct_pnext(
report_data, "vkCreateGraphicsPipelines",
ParameterName("pCreateInfos[%i].pDepthStencilState->pNext", ParameterName::IndexVector{i}), NULL,
}
}
- // TODO: Conditional NULL check based on subpass color attachment
- if (pCreateInfos[i].pColorBlendState != nullptr) {
+ if (pCreateInfos[i].pColorBlendState != nullptr && uses_color_attachment) {
skip |= validate_struct_pnext(
report_data, "vkCreateGraphicsPipelines",
ParameterName("pCreateInfos[%i].pColorBlendState->pNext", ParameterName::IndexVector{i}), NULL,
local_pCreateInfos = new safe_VkGraphicsPipelineCreateInfo[createInfoCount];
std::lock_guard<std::mutex> lock(global_lock);
for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) {
- local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]);
+ bool uses_color_attachment = false;
+ bool uses_depthstencil_attachment = false;
+ {
+ const auto subpasses_uses_it =
+ device_data->renderpasses_states.find(Unwrap(device_data, pCreateInfos[idx0].renderPass));
+ if (subpasses_uses_it != device_data->renderpasses_states.end()) {
+ const auto &subpasses_uses = subpasses_uses_it->second;
+ if (subpasses_uses.subpasses_using_color_attachment.count(pCreateInfos[idx0].subpass))
+ uses_color_attachment = true;
+ if (subpasses_uses.subpasses_using_depthstencil_attachment.count(pCreateInfos[idx0].subpass))
+ uses_depthstencil_attachment = true;
+ }
+ }
+
+ local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0], uses_color_attachment, uses_depthstencil_attachment);
+
if (pCreateInfos[idx0].basePipelineHandle) {
local_pCreateInfos[idx0].basePipelineHandle = Unwrap(device_data, pCreateInfos[idx0].basePipelineHandle);
}
return result;
}
+static void PostCallCreateRenderPass(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, VkRenderPass renderPass) {
+ auto &renderpass_state = dev_data->renderpasses_states[renderPass];
+
+ for (uint32_t subpass = 0; subpass < pCreateInfo->subpassCount; ++subpass) {
+ bool uses_color = false;
+ for (uint32_t i = 0; i < pCreateInfo->pSubpasses[subpass].colorAttachmentCount && !uses_color; ++i)
+ if (pCreateInfo->pSubpasses[subpass].pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) uses_color = true;
+
+ bool uses_depthstencil = false;
+ if (pCreateInfo->pSubpasses[subpass].pDepthStencilAttachment)
+ if (pCreateInfo->pSubpasses[subpass].pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
+ uses_depthstencil = true;
+
+ if (uses_color) renderpass_state.subpasses_using_color_attachment.insert(subpass);
+ if (uses_depthstencil) renderpass_state.subpasses_using_depthstencil_attachment.insert(subpass);
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
+ if (VK_SUCCESS == result) {
+ std::lock_guard<std::mutex> lock(global_lock);
+
+ PostCallCreateRenderPass(dev_data, pCreateInfo, *pRenderPass);
+
+ *pRenderPass = WrapNew(dev_data, *pRenderPass);
+ }
+ return result;
+}
+
+static void PostCallDestroyRenderPass(layer_data *dev_data, VkRenderPass renderPass) {
+ dev_data->renderpasses_states.erase(renderPass);
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ std::unique_lock<std::mutex> lock(global_lock);
+ uint64_t renderPass_id = reinterpret_cast<uint64_t &>(renderPass);
+ renderPass = (VkRenderPass)dev_data->unique_id_mapping[renderPass_id];
+ dev_data->unique_id_mapping.erase(renderPass_id);
+ lock.unlock();
+ dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator);
+
+ lock.lock();
+ PostCallDestroyRenderPass(dev_data, renderPass);
+}
+
VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
layer_data *my_map_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
#include "vulkan/vulkan.h"
+#include <unordered_map>
+#include <unordered_set>
+
#include "vk_layer_data.h"
#include "vk_safe_struct.h"
#include "vk_layer_utils.h"
std::unordered_map<uint64_t, uint64_t> unique_id_mapping; // Map uniqueID to actual object handle
VkPhysicalDevice gpu;
+ struct SubpassesUsageStates {
+ std::unordered_set<uint32_t> subpasses_using_color_attachment;
+ std::unordered_set<uint32_t> subpasses_using_depthstencil_attachment;
+ };
+ // uses unwrapped handles
+ std::unordered_map<VkRenderPass, SubpassesUsageStates> renderpasses_states;
+
layer_data() : wsi_enabled(false), gpu(VK_NULL_HANDLE){};
};
self.StructType = namedtuple('StructType', ['name', 'value'])
self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isstaticarray', 'isconst', 'iscount', 'len', 'extstructs', 'cdecl'])
self.StructMemberData = namedtuple('StructMemberData', ['name', 'members', 'ifdef_protect'])
+
+ self.custom_construct_params = {
+ # safe_VkGraphicsPipelineCreateInfo needs to know if subpass has color and\or depth\stencil attachments to use its pointers
+ 'VkGraphicsPipelineCreateInfo' :
+ ', const bool uses_color_attachment, const bool uses_depthstencil_attachment',
+ # safe_VkPipelineViewportStateCreateInfo needs to know if viewport and scissor is dynamic to use its pointers
+ 'VkPipelineViewportStateCreateInfo' :
+ ', const bool is_dynamic_viewports, const bool is_dynamic_scissors',
+ }
#
# Called once at the beginning of each run
def beginFile(self, genOpts):
safe_struct_header += ' %s* %s;\n' % (member.type, member.name)
else:
safe_struct_header += '%s;\n' % member.cdecl
- safe_struct_header += ' safe_%s(const %s* in_struct);\n' % (item.name, item.name)
- safe_struct_header += ' safe_%s(const safe_%s& src);\n' % (item.name, item.name)
+ safe_struct_header += ' safe_%s(const %s* in_struct%s);\n' % (item.name, item.name, self.custom_construct_params.get(item.name, ''))
+ safe_struct_header += ' safe_%s(const safe_%s& src%s);\n' % (item.name, item.name, self.custom_construct_params.get(item.name, ''))
safe_struct_header += ' safe_%s();\n' % item.name
safe_struct_header += ' ~safe_%s();\n' % item.name
- safe_struct_header += ' void initialize(const %s* in_struct);\n' % item.name
- safe_struct_header += ' void initialize(const safe_%s* src);\n' % item.name
+ safe_struct_header += ' void initialize(const %s* in_struct%s);\n' % (item.name, self.custom_construct_params.get(item.name, ''))
+ safe_struct_header += ' void initialize(const safe_%s* src%s);\n' % (item.name, self.custom_construct_params.get(item.name, ''))
safe_struct_header += ' %s *ptr() { return reinterpret_cast<%s *>(this); }\n' % (item.name, item.name)
safe_struct_header += ' %s const *ptr() const { return reinterpret_cast<%s const *>(this); }\n' % (item.name, item.name)
safe_struct_header += '};\n'
init_func_txt = '' # Txt for initialize() function that takes struct ptr and inits members
construct_txt = '' # Body of constuctor as well as body of initialize() func following init_func_txt
destruct_txt = ''
- # VkWriteDescriptorSet is special case because pointers may be non-null but ignored
- custom_construct_txt = {'VkWriteDescriptorSet' :
- ' switch (descriptorType) {\n'
- ' case VK_DESCRIPTOR_TYPE_SAMPLER:\n'
- ' case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:\n'
- ' case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:\n'
- ' case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:\n'
- ' case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:\n'
- ' if (descriptorCount && in_struct->pImageInfo) {\n'
- ' pImageInfo = new VkDescriptorImageInfo[descriptorCount];\n'
- ' for (uint32_t i=0; i<descriptorCount; ++i) {\n'
- ' pImageInfo[i] = in_struct->pImageInfo[i];\n'
- ' }\n'
- ' }\n'
- ' break;\n'
- ' case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:\n'
- ' case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:\n'
- ' case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:\n'
- ' case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:\n'
- ' if (descriptorCount && in_struct->pBufferInfo) {\n'
- ' pBufferInfo = new VkDescriptorBufferInfo[descriptorCount];\n'
- ' for (uint32_t i=0; i<descriptorCount; ++i) {\n'
- ' pBufferInfo[i] = in_struct->pBufferInfo[i];\n'
- ' }\n'
- ' }\n'
- ' break;\n'
- ' case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:\n'
- ' case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:\n'
- ' if (descriptorCount && in_struct->pTexelBufferView) {\n'
- ' pTexelBufferView = new VkBufferView[descriptorCount];\n'
- ' for (uint32_t i=0; i<descriptorCount; ++i) {\n'
- ' pTexelBufferView[i] = in_struct->pTexelBufferView[i];\n'
- ' }\n'
- ' }\n'
- ' break;\n'
- ' default:\n'
- ' break;\n'
- ' }\n',
- 'VkShaderModuleCreateInfo' :
- ' if (in_struct->pCode) {\n'
- ' pCode = reinterpret_cast<uint32_t *>(new uint8_t[codeSize]);\n'
- ' memcpy((void *)pCode, (void *)in_struct->pCode, codeSize);\n'
- ' }\n'}
+
+ custom_construct_txt = {
+ # VkWriteDescriptorSet is special case because pointers may be non-null but ignored
+ 'VkWriteDescriptorSet' :
+ ' switch (descriptorType) {\n'
+ ' case VK_DESCRIPTOR_TYPE_SAMPLER:\n'
+ ' case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:\n'
+ ' case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:\n'
+ ' case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:\n'
+ ' case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:\n'
+ ' if (descriptorCount && in_struct->pImageInfo) {\n'
+ ' pImageInfo = new VkDescriptorImageInfo[descriptorCount];\n'
+ ' for (uint32_t i=0; i<descriptorCount; ++i) {\n'
+ ' pImageInfo[i] = in_struct->pImageInfo[i];\n'
+ ' }\n'
+ ' }\n'
+ ' break;\n'
+ ' case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:\n'
+ ' case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:\n'
+ ' case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:\n'
+ ' case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:\n'
+ ' if (descriptorCount && in_struct->pBufferInfo) {\n'
+ ' pBufferInfo = new VkDescriptorBufferInfo[descriptorCount];\n'
+ ' for (uint32_t i=0; i<descriptorCount; ++i) {\n'
+ ' pBufferInfo[i] = in_struct->pBufferInfo[i];\n'
+ ' }\n'
+ ' }\n'
+ ' break;\n'
+ ' case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:\n'
+ ' case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:\n'
+ ' if (descriptorCount && in_struct->pTexelBufferView) {\n'
+ ' pTexelBufferView = new VkBufferView[descriptorCount];\n'
+ ' for (uint32_t i=0; i<descriptorCount; ++i) {\n'
+ ' pTexelBufferView[i] = in_struct->pTexelBufferView[i];\n'
+ ' }\n'
+ ' }\n'
+ ' break;\n'
+ ' default:\n'
+ ' break;\n'
+ ' }\n',
+ 'VkShaderModuleCreateInfo' :
+ ' if (in_struct->pCode) {\n'
+ ' pCode = reinterpret_cast<uint32_t *>(new uint8_t[codeSize]);\n'
+ ' memcpy((void *)pCode, (void *)in_struct->pCode, codeSize);\n'
+ ' }\n',
+ # VkGraphicsPipelineCreateInfo is special case because its pointers may be non-null but ignored
+ 'VkGraphicsPipelineCreateInfo' :
+ ' if (stageCount && in_struct->pStages) {\n'
+ ' pStages = new safe_VkPipelineShaderStageCreateInfo[stageCount];\n'
+ ' for (uint32_t i=0; i<stageCount; ++i) {\n'
+ ' pStages[i].initialize(&in_struct->pStages[i]);\n'
+ ' }\n'
+ ' }\n'
+ ' if (in_struct->pVertexInputState)\n'
+ ' pVertexInputState = new safe_VkPipelineVertexInputStateCreateInfo(in_struct->pVertexInputState);\n'
+ ' else\n'
+ ' pVertexInputState = NULL;\n'
+ ' if (in_struct->pInputAssemblyState)\n'
+ ' pInputAssemblyState = new safe_VkPipelineInputAssemblyStateCreateInfo(in_struct->pInputAssemblyState);\n'
+ ' else\n'
+ ' pInputAssemblyState = NULL;\n'
+ ' bool has_tessellation_stage = false;\n'
+ ' if (stageCount && pStages)\n'
+ ' for (uint32_t i=0; i<stageCount && !has_tessellation_stage; ++i)\n'
+ ' if (pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || pStages[i].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)\n'
+ ' has_tessellation_stage = true;\n'
+ ' if (in_struct->pTessellationState && has_tessellation_stage)\n'
+ ' pTessellationState = new safe_VkPipelineTessellationStateCreateInfo(in_struct->pTessellationState);\n'
+ ' else\n'
+ ' pTessellationState = NULL; // original pTessellationState pointer ignored\n'
+ ' bool has_rasterization = in_struct->pRasterizationState ? !in_struct->pRasterizationState->rasterizerDiscardEnable : false;\n'
+ ' if (in_struct->pViewportState && has_rasterization) {\n'
+ ' bool is_dynamic_viewports = false;\n'
+ ' bool is_dynamic_scissors = false;\n'
+ ' if (in_struct->pDynamicState && in_struct->pDynamicState->pDynamicStates) {\n'
+ ' for (uint32_t i = 0; i < in_struct->pDynamicState->dynamicStateCount && !is_dynamic_viewports; ++i)\n'
+ ' if (in_struct->pDynamicState->pDynamicStates[i] == VK_DYNAMIC_STATE_VIEWPORT)\n'
+ ' is_dynamic_viewports = true;\n'
+ ' for (uint32_t i = 0; i < in_struct->pDynamicState->dynamicStateCount && !is_dynamic_scissors; ++i)\n'
+ ' if (in_struct->pDynamicState->pDynamicStates[i] == VK_DYNAMIC_STATE_SCISSOR)\n'
+ ' is_dynamic_scissors = true;\n'
+ ' }\n'
+ ' pViewportState = new safe_VkPipelineViewportStateCreateInfo(in_struct->pViewportState, is_dynamic_viewports, is_dynamic_scissors);\n'
+ ' } else\n'
+ ' pViewportState = NULL; // original pViewportState pointer ignored\n'
+ ' if (in_struct->pRasterizationState)\n'
+ ' pRasterizationState = new safe_VkPipelineRasterizationStateCreateInfo(in_struct->pRasterizationState);\n'
+ ' else\n'
+ ' pRasterizationState = NULL;\n'
+ ' if (in_struct->pMultisampleState && has_rasterization)\n'
+ ' pMultisampleState = new safe_VkPipelineMultisampleStateCreateInfo(in_struct->pMultisampleState);\n'
+ ' else\n'
+ ' pMultisampleState = NULL; // original pMultisampleState pointer ignored\n'
+ ' // needs a tracked subpass state uses_depthstencil_attachment\n'
+ ' if (in_struct->pDepthStencilState && has_rasterization && uses_depthstencil_attachment)\n'
+ ' pDepthStencilState = new safe_VkPipelineDepthStencilStateCreateInfo(in_struct->pDepthStencilState);\n'
+ ' else\n'
+ ' pDepthStencilState = NULL; // original pDepthStencilState pointer ignored\n'
+ ' // needs a tracked subpass state usesColorAttachment\n'
+ ' if (in_struct->pColorBlendState && has_rasterization && uses_color_attachment)\n'
+ ' pColorBlendState = new safe_VkPipelineColorBlendStateCreateInfo(in_struct->pColorBlendState);\n'
+ ' else\n'
+ ' pColorBlendState = NULL; // original pColorBlendState pointer ignored\n'
+ ' if (in_struct->pDynamicState)\n'
+ ' pDynamicState = new safe_VkPipelineDynamicStateCreateInfo(in_struct->pDynamicState);\n'
+ ' else\n'
+ ' pDynamicState = NULL;\n',
+ # VkPipelineViewportStateCreateInfo is special case because its pointers may be non-null but ignored
+ 'VkPipelineViewportStateCreateInfo' :
+ ' if (in_struct->pViewports && !is_dynamic_viewports) {\n'
+ ' pViewports = new VkViewport[in_struct->viewportCount];\n'
+ ' memcpy ((void *)pViewports, (void *)in_struct->pViewports, sizeof(VkViewport)*in_struct->viewportCount);\n'
+ ' }\n'
+ ' else\n'
+ ' pViewports = NULL;\n'
+ ' if (in_struct->pScissors && !is_dynamic_scissors) {\n'
+ ' pScissors = new VkRect2D[in_struct->scissorCount];\n'
+ ' memcpy ((void *)pScissors, (void *)in_struct->pScissors, sizeof(VkRect2D)*in_struct->scissorCount);\n'
+ ' }\n'
+ ' else\n'
+ ' pScissors = NULL;\n',
+ }
+
custom_destruct_txt = {'VkShaderModuleCreateInfo' :
' if (pCode)\n'
' delete[] reinterpret_cast<const uint8_t *>(pCode);\n' }
construct_txt = custom_construct_txt[item.name]
if item.name in custom_destruct_txt:
destruct_txt = custom_destruct_txt[item.name]
- safe_struct_body.append("\n%s::%s(const %s* in_struct) :%s\n{\n%s}" % (ss_name, ss_name, item.name, init_list, construct_txt))
+ safe_struct_body.append("\n%s::%s(const %s* in_struct%s) :%s\n{\n%s}" % (ss_name, ss_name, item.name, self.custom_construct_params.get(item.name, ''), init_list, construct_txt))
if '' != default_init_list:
default_init_list = " :%s" % (default_init_list[:-1])
safe_struct_body.append("\n%s::%s()%s\n{}" % (ss_name, ss_name, default_init_list))
copy_construct_txt = construct_txt.replace(' (in_struct->', ' (src.') # Exclude 'if' blocks from next line
copy_construct_txt = copy_construct_txt.replace('(in_struct->', '(*src.') # Pass object to copy constructors
copy_construct_txt = copy_construct_txt.replace('in_struct->', 'src.') # Modify remaining struct refs for src object
- safe_struct_body.append("\n%s::%s(const %s& src)\n{\n%s%s}" % (ss_name, ss_name, ss_name, copy_construct_init, copy_construct_txt)) # Copy constructor
+ safe_struct_body.append("\n%s::%s(const %s& src%s)\n{\n%s%s}" % (ss_name, ss_name, ss_name, self.custom_construct_params.get(item.name, ''), copy_construct_init, copy_construct_txt)) # Copy constructor
safe_struct_body.append("\n%s::~%s()\n{\n%s}" % (ss_name, ss_name, destruct_txt))
- safe_struct_body.append("\nvoid %s::initialize(const %s* in_struct)\n{\n%s%s}" % (ss_name, item.name, init_func_txt, construct_txt))
+ safe_struct_body.append("\nvoid %s::initialize(const %s* in_struct%s)\n{\n%s%s}" % (ss_name, item.name, self.custom_construct_params.get(item.name, ''), init_func_txt, construct_txt))
# Copy initializer uses same txt as copy constructor but has a ptr and not a reference
init_copy = copy_construct_init.replace('src.', 'src->')
init_construct = copy_construct_txt.replace('src.', 'src->')
- safe_struct_body.append("\nvoid %s::initialize(const %s* src)\n{\n%s%s}" % (ss_name, ss_name, init_copy, init_construct))
+ safe_struct_body.append("\nvoid %s::initialize(const %s* src%s)\n{\n%s%s}" % (ss_name, ss_name, self.custom_construct_params.get(item.name, ''), init_copy, init_construct))
if item.ifdef_protect != None:
safe_struct_body.append("#endif // %s\n" % item.ifdef_protect)
return "\n".join(safe_struct_body)
'vkCreateDebugReportCallbackEXT',
'vkDestroyDebugReportCallbackEXT',
'vkCreateCommandPool',
+ 'vkCreateRenderPass',
+ 'vkDestroyRenderPass',
]
# Structure fields to ignore
self.structMemberBlacklist = { 'VkWriteDescriptorSet' : ['dstSet'] }
'vkGetPhysicalDeviceDisplayProperties2KHR',
'vkGetPhysicalDeviceDisplayPlaneProperties2KHR',
'vkGetDisplayModeProperties2KHR',
+ 'vkCreateRenderPass',
+ 'vkDestroyRenderPass',
]
# Commands shadowed by interface functions and are not implemented
self.interface_functions = [