From 0263d8a6adf94df19d4941d1b5d15840eee2ae80 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Fri, 1 Apr 2016 13:51:33 -0600 Subject: [PATCH] layers: Clean up PIPELINE_NODE using safe_struct PIPELINE_NODE was storing ptrs from the app and has some ugly initialization code for the gfx pipeline create struct. This commit switches pipeline node to use safe_struct wrappers for Gfx and Compute create info. There were also some bugs found in the safe_struct wrappers making this migration so those are cleaned up in this commit as well. --- buildAndroid/jni/Android.mk | 1 + layers/CMakeLists.txt | 2 +- layers/core_validation.cpp | 182 ++++++++---------------------------- layers/core_validation.h | 100 +++++++++++++++----- vk_helper.py | 29 +++++- 5 files changed, 145 insertions(+), 169 deletions(-) diff --git a/buildAndroid/jni/Android.mk b/buildAndroid/jni/Android.mk index 334c0f74..6015b076 100644 --- a/buildAndroid/jni/Android.mk +++ b/buildAndroid/jni/Android.mk @@ -31,6 +31,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := VkLayer_core_validation LOCAL_SRC_FILES += $(SRC_DIR)/layers/core_validation.cpp LOCAL_SRC_FILES += $(SRC_DIR)/layers/vk_layer_table.cpp +LOCAL_SRC_FILES += $(MY_PATH)/../generated/vk_safe_struct.cpp LOCAL_C_INCLUDES += $(SRC_DIR)/include \ $(MY_PATH)/../generated \ $(SRC_DIR)/loader \ diff --git a/layers/CMakeLists.txt b/layers/CMakeLists.txt index d23cbad7..82e1495a 100644 --- a/layers/CMakeLists.txt +++ b/layers/CMakeLists.txt @@ -145,7 +145,7 @@ if (WIN32) else() install(TARGETS layer_utils DESTINATION ${PROJECT_BINARY_DIR}/install_staging) endif() -add_vk_layer(core_validation core_validation.cpp vk_layer_table.cpp) +add_vk_layer(core_validation core_validation.cpp vk_layer_table.cpp vk_safe_struct.cpp) add_vk_layer(device_limits device_limits.cpp vk_layer_table.cpp vk_layer_utils.cpp) add_vk_layer(image image.cpp vk_layer_table.cpp) add_vk_layer(swapchain swapchain.cpp vk_layer_table.cpp) diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 7cc7979c..f8ed342a 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2136,12 +2136,13 @@ static VkBool32 validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE * "Dynamic viewport state not set for this command buffer"); result |= validate_status(dev_data, pCB, CBSTATUS_SCISSOR_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_SCISSOR_NOT_BOUND, "Dynamic scissor state not set for this command buffer"); - if ((pPipe->iaStateCI.topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) || - (pPipe->iaStateCI.topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP)) { + if (pPipe->graphicsPipelineCI.pInputAssemblyState && + ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) || + (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) { result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_LINE_WIDTH_NOT_BOUND, "Dynamic line width state not set for this command buffer"); } - if (pPipe->rsStateCI.depthBiasEnable) { + if (pPipe->graphicsPipelineCI.pRasterizationState && pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable) { result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_DEPTH_BIAS_NOT_BOUND, "Dynamic depth bias state not set for this command buffer"); } @@ -2149,11 +2150,11 @@ static VkBool32 validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE * result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_BLEND_NOT_BOUND, "Dynamic blend constants state not set for this command buffer"); } - if (pPipe->dsStateCI.depthBoundsTestEnable) { + if (pPipe->graphicsPipelineCI.pDepthStencilState && pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable) { result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND, "Dynamic depth bounds state not set for this command buffer"); } - if (pPipe->dsStateCI.stencilTestEnable) { + if (pPipe->graphicsPipelineCI.pDepthStencilState && pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable) { result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil read mask state not set for this command buffer"); result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, @@ -2679,7 +2680,7 @@ static VkBool32 validate_pipeline_shader_stage(layer_data *dev_data, // Validate that the shaders used by the given pipeline and store the active_slots // that are actually used by the pipeline into pPipeline->active_slots static VkBool32 validate_and_capture_pipeline_shader_state(layer_data *my_data, PIPELINE_NODE *pPipeline) { - VkGraphicsPipelineCreateInfo const *pCreateInfo = &pPipeline->graphicsPipelineCI; + auto pCreateInfo = reinterpret_cast(&pPipeline->graphicsPipelineCI); int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT); @@ -2693,7 +2694,8 @@ static VkBool32 validate_and_capture_pipeline_shader_state(layer_data *my_data, auto pipelineLayout = pCreateInfo->layout != VK_NULL_HANDLE ? &my_data->pipelineLayoutMap[pCreateInfo->layout] : nullptr; for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { - VkPipelineShaderStageCreateInfo const *pStage = &pCreateInfo->pStages[i]; + VkPipelineShaderStageCreateInfo const *pStage = + reinterpret_cast(&pCreateInfo->pStages[i]); auto stage_id = get_shader_stage_id(pStage->stage); pass &= validate_pipeline_shader_stage(my_data, pStage, pPipeline, pipelineLayout, &shaders[stage_id], &entrypoints[stage_id]); @@ -2739,7 +2741,7 @@ static VkBool32 validate_and_capture_pipeline_shader_state(layer_data *my_data, } static VkBool32 validate_compute_pipeline(layer_data *my_data, PIPELINE_NODE *pPipeline) { - VkComputePipelineCreateInfo const *pCreateInfo = &pPipeline->computePipelineCI; + auto pCreateInfo = reinterpret_cast(&pPipeline->computePipelineCI); auto pipelineLayout = pCreateInfo->layout != VK_NULL_HANDLE ? &my_data->pipelineLayoutMap[pCreateInfo->layout] : nullptr; @@ -3139,26 +3141,35 @@ static VkBool32 verifyPipelineCreateState(layer_data *my_data, const VkDevice de // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines. // Mismatching primitive topology and tessellation fails graphics pipeline creation. if (pPipeline->active_shaders & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) && - (pPipeline->iaStateCI.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) { + (!pPipeline->graphicsPipelineCI.pInputAssemblyState || + pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: " "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA " "topology for tessellation pipelines"); } - if (pPipeline->iaStateCI.topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) { + if (pPipeline->graphicsPipelineCI.pInputAssemblyState && + pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) { if (~pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: " "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " "topology is only valid for tessellation pipelines"); } - if (!pPipeline->tessStateCI.patchControlPoints || (pPipeline->tessStateCI.patchControlPoints > 32)) { + if (!pPipeline->graphicsPipelineCI.pTessellationState) { + skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", + "Invalid Pipeline CreateInfo State: " + "pTessellationState is NULL when VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " + "topology used. pTessellationState must not be NULL in this case."); + } else if (!pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints || + (pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints > 32)) { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: " "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " "topology used with patchControlPoints value %u." " patchControlPoints should be >0 and <=32.", - pPipeline->tessStateCI.patchControlPoints); + pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints); } } // Viewport state must be included if rasterization is enabled. @@ -3176,7 +3187,8 @@ static VkBool32 verifyPipelineCreateState(layer_data *my_data, const VkDevice de skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "Gfx Pipeline viewport count (%u) must match scissor count (%u).", - pPipeline->vpStateCI.viewportCount, pPipeline->vpStateCI.scissorCount); + pPipeline->graphicsPipelineCI.pViewportState->viewportCount, + pPipeline->graphicsPipelineCI.pViewportState->scissorCount); } else { // If viewport or scissor are not dynamic, then verify that data is appropriate for count VkBool32 dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT); @@ -3208,130 +3220,12 @@ static VkBool32 verifyPipelineCreateState(layer_data *my_data, const VkDevice de return skipCall; } -// Init the pipeline mapping info based on pipeline create info LL tree -// Threading note : Calls to this function should wrapped in mutex -// TODO : this should really just be in the constructor for PIPELINE_NODE -static PIPELINE_NODE *initGraphicsPipeline(layer_data *dev_data, const VkGraphicsPipelineCreateInfo *pCreateInfo) { - PIPELINE_NODE *pPipeline = new PIPELINE_NODE; - - // First init create info - memcpy(&pPipeline->graphicsPipelineCI, pCreateInfo, sizeof(VkGraphicsPipelineCreateInfo)); - - size_t bufferSize = 0; - const VkPipelineVertexInputStateCreateInfo *pVICI = NULL; - const VkPipelineColorBlendStateCreateInfo *pCBCI = NULL; - - for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { - const VkPipelineShaderStageCreateInfo *pPSSCI = &pCreateInfo->pStages[i]; - - switch (pPSSCI->stage) { - case VK_SHADER_STAGE_VERTEX_BIT: - memcpy(&pPipeline->vsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo)); - pPipeline->active_shaders |= VK_SHADER_STAGE_VERTEX_BIT; - break; - case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: - memcpy(&pPipeline->tcsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo)); - pPipeline->active_shaders |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - break; - case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: - memcpy(&pPipeline->tesCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo)); - pPipeline->active_shaders |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - break; - case VK_SHADER_STAGE_GEOMETRY_BIT: - memcpy(&pPipeline->gsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo)); - pPipeline->active_shaders |= VK_SHADER_STAGE_GEOMETRY_BIT; - break; - case VK_SHADER_STAGE_FRAGMENT_BIT: - memcpy(&pPipeline->fsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo)); - pPipeline->active_shaders |= VK_SHADER_STAGE_FRAGMENT_BIT; - break; - case VK_SHADER_STAGE_COMPUTE_BIT: - // TODO : Flag error, CS is specified through VkComputePipelineCreateInfo - pPipeline->active_shaders |= VK_SHADER_STAGE_COMPUTE_BIT; - break; - default: - // TODO : Flag error - break; - } - } - // Copy over GraphicsPipelineCreateInfo structure embedded pointers - if (pCreateInfo->stageCount != 0) { - pPipeline->graphicsPipelineCI.pStages = new VkPipelineShaderStageCreateInfo[pCreateInfo->stageCount]; - bufferSize = pCreateInfo->stageCount * sizeof(VkPipelineShaderStageCreateInfo); - memcpy((void *)pPipeline->graphicsPipelineCI.pStages, pCreateInfo->pStages, bufferSize); - } - if (pCreateInfo->pVertexInputState != NULL) { - pPipeline->vertexInputCI = *pCreateInfo->pVertexInputState; - // Copy embedded ptrs - pVICI = pCreateInfo->pVertexInputState; - if (pVICI->vertexBindingDescriptionCount) { - pPipeline->vertexBindingDescriptions = std::vector( - pVICI->pVertexBindingDescriptions, pVICI->pVertexBindingDescriptions + pVICI->vertexBindingDescriptionCount); - } - if (pVICI->vertexAttributeDescriptionCount) { - pPipeline->vertexAttributeDescriptions = std::vector( - pVICI->pVertexAttributeDescriptions, pVICI->pVertexAttributeDescriptions + pVICI->vertexAttributeDescriptionCount); - } - pPipeline->graphicsPipelineCI.pVertexInputState = &pPipeline->vertexInputCI; - } - if (pCreateInfo->pInputAssemblyState != NULL) { - pPipeline->iaStateCI = *pCreateInfo->pInputAssemblyState; - pPipeline->graphicsPipelineCI.pInputAssemblyState = &pPipeline->iaStateCI; - } - if (pCreateInfo->pTessellationState != NULL) { - pPipeline->tessStateCI = *pCreateInfo->pTessellationState; - pPipeline->graphicsPipelineCI.pTessellationState = &pPipeline->tessStateCI; - } - if (pCreateInfo->pViewportState != NULL) { - pPipeline->vpStateCI = *pCreateInfo->pViewportState; - pPipeline->graphicsPipelineCI.pViewportState = &pPipeline->vpStateCI; - } - if (pCreateInfo->pRasterizationState != NULL) { - pPipeline->rsStateCI = *pCreateInfo->pRasterizationState; - pPipeline->graphicsPipelineCI.pRasterizationState = &pPipeline->rsStateCI; - } - if (pCreateInfo->pMultisampleState != NULL) { - pPipeline->msStateCI = *pCreateInfo->pMultisampleState; - pPipeline->graphicsPipelineCI.pMultisampleState = &pPipeline->msStateCI; - } - if (pCreateInfo->pDepthStencilState != NULL) { - pPipeline->dsStateCI = *pCreateInfo->pDepthStencilState; - pPipeline->graphicsPipelineCI.pDepthStencilState = &pPipeline->dsStateCI; - } - if (pCreateInfo->pColorBlendState != NULL) { - pPipeline->cbStateCI = *pCreateInfo->pColorBlendState; - // Copy embedded ptrs - pCBCI = pCreateInfo->pColorBlendState; - if (pCBCI->attachmentCount) { - pPipeline->attachments = std::vector( - pCBCI->pAttachments, pCBCI->pAttachments + pCBCI->attachmentCount); - } - pPipeline->graphicsPipelineCI.pColorBlendState = &pPipeline->cbStateCI; - } - if (pCreateInfo->pDynamicState != NULL) { - pPipeline->dynStateCI = *pCreateInfo->pDynamicState; - if (pPipeline->dynStateCI.dynamicStateCount) { - pPipeline->dynStateCI.pDynamicStates = new VkDynamicState[pPipeline->dynStateCI.dynamicStateCount]; - bufferSize = pPipeline->dynStateCI.dynamicStateCount * sizeof(VkDynamicState); - memcpy((void *)pPipeline->dynStateCI.pDynamicStates, pCreateInfo->pDynamicState->pDynamicStates, bufferSize); - } - pPipeline->graphicsPipelineCI.pDynamicState = &pPipeline->dynStateCI; - } - return pPipeline; -} - // Free the Pipeline nodes static void deletePipelines(layer_data *my_data) { if (my_data->pipelineMap.size() <= 0) return; - for (auto ii = my_data->pipelineMap.begin(); ii != my_data->pipelineMap.end(); ++ii) { - if ((*ii).second->graphicsPipelineCI.stageCount != 0) { - delete[](*ii).second->graphicsPipelineCI.pStages; - } - if ((*ii).second->dynStateCI.dynamicStateCount != 0) { - delete[](*ii).second->dynStateCI.pDynamicStates; - } - delete (*ii).second; + for (auto &pipe_map_pair : my_data->pipelineMap) { + delete pipe_map_pair.second; } my_data->pipelineMap.clear(); } @@ -3339,8 +3233,9 @@ static void deletePipelines(layer_data *my_data) { // For given pipeline, return number of MSAA samples, or one if MSAA disabled static VkSampleCountFlagBits getNumSamples(layer_data *my_data, const VkPipeline pipeline) { PIPELINE_NODE *pPipe = my_data->pipelineMap[pipeline]; - if (VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pPipe->msStateCI.sType) { - return pPipe->msStateCI.rasterizationSamples; + if (pPipe->graphicsPipelineCI.pMultisampleState && + (VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pPipe->graphicsPipelineCI.pMultisampleState->sType)) { + return pPipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples; } return VK_SAMPLE_COUNT_1_BIT; } @@ -4543,15 +4438,16 @@ static void resetCB(layer_data *my_data, const VkCommandBuffer cb) { // Set PSO-related status bits for CB, including dynamic state set via PSO static void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_NODE *pPipe) { // Account for any dynamic state not set via this PSO - if (!pPipe->dynStateCI.dynamicStateCount) { // All state is static + if (!pPipe->graphicsPipelineCI.pDynamicState || + !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) { // All state is static pCB->status = CBSTATUS_ALL; } else { // First consider all state on // Then unset any state that's noted as dynamic in PSO // Finally OR that into CB statemask CBStatusFlags psoDynStateMask = CBSTATUS_ALL; - for (uint32_t i = 0; i < pPipe->dynStateCI.dynamicStateCount; i++) { - switch (pPipe->dynStateCI.pDynamicStates[i]) { + for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { + switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) { case VK_DYNAMIC_STATE_VIEWPORT: psoDynStateMask &= ~CBSTATUS_VIEWPORT_SET; break; @@ -4599,7 +4495,9 @@ static VkBool32 printPipeline(layer_data *my_data, const VkCommandBuffer cb) { } else { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_NONE, "DS", "%s", - vk_print_vkgraphicspipelinecreateinfo(&pPipeTrav->graphicsPipelineCI, "{DS}").c_str()); + vk_print_vkgraphicspipelinecreateinfo( + reinterpret_cast(&pPipeTrav->graphicsPipelineCI), "{DS}") + .c_str()); } } return skipCall; @@ -6604,7 +6502,8 @@ vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32 loader_platform_thread_lock_mutex(&globalLock); for (i = 0; i < count; i++) { - pPipeNode[i] = initGraphicsPipeline(dev_data, &pCreateInfos[i]); + pPipeNode[i] = new PIPELINE_NODE; + pPipeNode[i]->initGraphicsPipeline(&pCreateInfos[i]); skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode, i); } @@ -6646,7 +6545,8 @@ vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_ // Create and initialize internal tracking data structure pPipeNode[i] = new PIPELINE_NODE; - memcpy(&pPipeNode[i]->computePipelineCI, (const void *)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo)); + pPipeNode[i]->initComputePipeline(&pCreateInfos[i]); + // memcpy(&pPipeNode[i]->computePipelineCI, (const void *)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo)); // TODO: Add Compute Pipeline Verification // skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]); diff --git a/layers/core_validation.h b/layers/core_validation.h index 88300976..866eeaf4 100644 --- a/layers/core_validation.h +++ b/layers/core_validation.h @@ -53,6 +53,7 @@ #define MTMERGE 1 #pragma once +#include "vk_safe_struct.h" #include "vulkan/vk_layer.h" #include #include @@ -437,25 +438,11 @@ typedef struct _GENERIC_HEADER { const void *pNext; } GENERIC_HEADER; -typedef struct _PIPELINE_NODE { +class PIPELINE_NODE { + public: VkPipeline pipeline; - VkGraphicsPipelineCreateInfo graphicsPipelineCI; - VkPipelineVertexInputStateCreateInfo vertexInputCI; - VkPipelineInputAssemblyStateCreateInfo iaStateCI; - VkPipelineTessellationStateCreateInfo tessStateCI; - VkPipelineViewportStateCreateInfo vpStateCI; - VkPipelineRasterizationStateCreateInfo rsStateCI; - VkPipelineMultisampleStateCreateInfo msStateCI; - VkPipelineColorBlendStateCreateInfo cbStateCI; - VkPipelineDepthStencilStateCreateInfo dsStateCI; - VkPipelineDynamicStateCreateInfo dynStateCI; - VkPipelineShaderStageCreateInfo vsCI; - VkPipelineShaderStageCreateInfo tcsCI; - VkPipelineShaderStageCreateInfo tesCI; - VkPipelineShaderStageCreateInfo gsCI; - VkPipelineShaderStageCreateInfo fsCI; - // Compute shader is include in VkComputePipelineCreateInfo - VkComputePipelineCreateInfo computePipelineCI; + safe_VkGraphicsPipelineCreateInfo graphicsPipelineCI; + safe_VkComputePipelineCreateInfo computePipelineCI; // Flag of which shader stages are active for this pipeline uint32_t active_shaders; // Capture which slots (set#->bindings) are actually used by the shaders of this pipeline @@ -466,11 +453,78 @@ typedef struct _PIPELINE_NODE { std::vector attachments; bool blendConstantsEnabled; // Blend constants enabled for any attachments // Default constructor - _PIPELINE_NODE() - : pipeline{}, graphicsPipelineCI{}, vertexInputCI{}, iaStateCI{}, tessStateCI{}, vpStateCI{}, rsStateCI{}, msStateCI{}, - cbStateCI{}, dsStateCI{}, dynStateCI{}, vsCI{}, tcsCI{}, tesCI{}, gsCI{}, fsCI{}, computePipelineCI{}, active_shaders(0), - active_slots(), vertexBindingDescriptions(), vertexAttributeDescriptions(), attachments(), blendConstantsEnabled(false) {} -} PIPELINE_NODE; + PIPELINE_NODE() + : pipeline{}, graphicsPipelineCI{}, computePipelineCI{}, active_shaders(0), active_slots(), vertexBindingDescriptions(), + vertexAttributeDescriptions(), attachments(), blendConstantsEnabled(false) {} + + void initGraphicsPipeline(const VkGraphicsPipelineCreateInfo *pCreateInfo) { + graphicsPipelineCI.initialize(pCreateInfo); + // Make sure compute pipeline is null + VkComputePipelineCreateInfo emptyComputeCI = {}; + computePipelineCI.initialize(&emptyComputeCI); + for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { + const VkPipelineShaderStageCreateInfo *pPSSCI = &pCreateInfo->pStages[i]; + + switch (pPSSCI->stage) { + case VK_SHADER_STAGE_VERTEX_BIT: + this->active_shaders |= VK_SHADER_STAGE_VERTEX_BIT; + break; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + this->active_shaders |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + break; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + this->active_shaders |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + break; + case VK_SHADER_STAGE_GEOMETRY_BIT: + this->active_shaders |= VK_SHADER_STAGE_GEOMETRY_BIT; + break; + case VK_SHADER_STAGE_FRAGMENT_BIT: + this->active_shaders |= VK_SHADER_STAGE_FRAGMENT_BIT; + break; + case VK_SHADER_STAGE_COMPUTE_BIT: + // TODO : Flag error, CS is specified through VkComputePipelineCreateInfo + this->active_shaders |= VK_SHADER_STAGE_COMPUTE_BIT; + break; + default: + // TODO : Flag error + break; + } + } + if (pCreateInfo->pVertexInputState) { + const VkPipelineVertexInputStateCreateInfo *pVICI = pCreateInfo->pVertexInputState; + if (pVICI->vertexBindingDescriptionCount) { + this->vertexBindingDescriptions = std::vector( + pVICI->pVertexBindingDescriptions, pVICI->pVertexBindingDescriptions + pVICI->vertexBindingDescriptionCount); + } + if (pVICI->vertexAttributeDescriptionCount) { + this->vertexAttributeDescriptions = std::vector( + pVICI->pVertexAttributeDescriptions, + pVICI->pVertexAttributeDescriptions + pVICI->vertexAttributeDescriptionCount); + } + } + if (pCreateInfo->pColorBlendState) { + const VkPipelineColorBlendStateCreateInfo *pCBCI = pCreateInfo->pColorBlendState; + if (pCBCI->attachmentCount) { + this->attachments = std::vector(pCBCI->pAttachments, + pCBCI->pAttachments + pCBCI->attachmentCount); + } + } + } + void initComputePipeline(const VkComputePipelineCreateInfo *pCreateInfo) { + computePipelineCI.initialize(pCreateInfo); + // Make sure gfx pipeline is null + VkGraphicsPipelineCreateInfo emptyGraphicsCI = {}; + graphicsPipelineCI.initialize(&emptyGraphicsCI); + switch (computePipelineCI.stage.stage) { + case VK_SHADER_STAGE_COMPUTE_BIT: + this->active_shaders |= VK_SHADER_STAGE_COMPUTE_BIT; + break; + default: + // TODO : Flag error + break; + } + } +}; class BASE_NODE { public: diff --git a/vk_helper.py b/vk_helper.py index 88f1fa20..a976f24e 100755 --- a/vk_helper.py +++ b/vk_helper.py @@ -1637,7 +1637,7 @@ class StructWrapperGen: def _generateSafeStructSourceHeader(self): header = [] header.append("//#includes, #defines, globals and such...\n") - header.append('#include "vk_safe_struct.h"') + header.append('#include "vk_safe_struct.h"\n#include \n\n') return "".join(header) def _generateSafeStructSource(self): @@ -1650,7 +1650,7 @@ class StructWrapperGen: ss_name = self._getSafeStructName(s) init_list = '' # list of members in struct constructor initializer init_func_txt = '' # Txt for initialize() function that takes struct ptr and inits members - construct_txt = '' + 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 # TODO : This is ugly, figure out better way to do this @@ -1697,8 +1697,29 @@ class StructWrapperGen: if is_type(m_type, 'struct') and self._hasSafeStruct(m_type): m_type = self._getSafeStructName(m_type) if self.struct_dict[s][m]['ptr'] and 'safe_' not in m_type and not self._typeHasObject(m_type, vulkan.object_non_dispatch_list):# in ['char', 'float', 'uint32_t', 'void', 'VkPhysicalDeviceFeatures']) or 'pp' == self.struct_dict[s][m]['name'][0:1]: - init_list += '\n\t%s(pInStruct->%s),' % (m_name, m_name) - init_func_txt += ' %s = pInStruct->%s;\n' % (m_name, m_name) + # Ptr types w/o a safe_struct, for non-null case need to allocate new ptr and copy data in + if 'KHR' in ss_name or m_type in ['void', 'char']: + # For these exceptions just copy initial value over for now + init_list += '\n\t%s(pInStruct->%s),' % (m_name, m_name) + init_func_txt += ' %s = pInStruct->%s;\n' % (m_name, m_name) + else: + init_list += '\n\t%s(nullptr),' % (m_name) + init_func_txt += ' %s = nullptr;\n' % (m_name) + if 'pNext' != m_name and 'void' not in m_type: + if not self.struct_dict[s][m]['array']: + construct_txt += ' if (pInStruct->%s) {\n' % (m_name) + construct_txt += ' %s = new %s(*pInStruct->%s);\n' % (m_name, m_type, m_name) + construct_txt += ' }\n' + destruct_txt += ' if (%s)\n' % (m_name) + destruct_txt += ' delete %s;\n' % (m_name) + else: # new array and then init each element + construct_txt += ' if (pInStruct->%s) {\n' % (m_name) + construct_txt += ' %s = new %s[pInStruct->%s];\n' % (m_name, m_type, self.struct_dict[s][m]['array_size']) + #construct_txt += ' std::copy (pInStruct->%s, pInStruct->%s+pInStruct->%s, %s);\n' % (m_name, m_name, self.struct_dict[s][m]['array_size'], m_name) + construct_txt += ' memcpy ((void *)%s, (void *)pInStruct->%s, sizeof(%s)*pInStruct->%s);\n' % (m_name, m_name, m_type, self.struct_dict[s][m]['array_size']) + construct_txt += ' }\n' + destruct_txt += ' if (%s)\n' % (m_name) + destruct_txt += ' delete[] %s;\n' % (m_name) elif self.struct_dict[s][m]['array']: # Init array ptr to NULL init_list += '\n\t%s(NULL),' % (m_name) -- 2.34.1