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.
diff --git a/buildAndroid/jni/Android.mk b/buildAndroid/jni/Android.mk
index 334c0f7..6015b07 100644
--- a/buildAndroid/jni/Android.mk
+++ b/buildAndroid/jni/Android.mk
@@ -31,6 +31,7 @@
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 d23cbad..82e1495 100644
--- a/layers/CMakeLists.txt
+++ b/layers/CMakeLists.txt
@@ -145,7 +145,7 @@
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 7cc7979..f8ed342 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -2136,12 +2136,13 @@
"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 @@
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 @@
// 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<VkGraphicsPipelineCreateInfo const *>(&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 @@
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<VkPipelineShaderStageCreateInfo const *>(&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_compute_pipeline(layer_data *my_data, PIPELINE_NODE *pPipeline) {
- VkComputePipelineCreateInfo const *pCreateInfo = &pPipeline->computePipelineCI;
+ auto pCreateInfo = reinterpret_cast<VkComputePipelineCreateInfo const *>(&pPipeline->computePipelineCI);
auto pipelineLayout = pCreateInfo->layout != VK_NULL_HANDLE ? &my_data->pipelineLayoutMap[pCreateInfo->layout] : nullptr;
@@ -3139,26 +3141,35 @@
// 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 @@
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 @@
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<VkVertexInputBindingDescription>(
- pVICI->pVertexBindingDescriptions, pVICI->pVertexBindingDescriptions + pVICI->vertexBindingDescriptionCount);
- }
- if (pVICI->vertexAttributeDescriptionCount) {
- pPipeline->vertexAttributeDescriptions = std::vector<VkVertexInputAttributeDescription>(
- 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<VkPipelineColorBlendAttachmentState>(
- 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 @@
// 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 @@
// 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 @@
} 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<const VkGraphicsPipelineCreateInfo *>(&pPipeTrav->graphicsPipelineCI), "{DS}")
+ .c_str());
}
}
return skipCall;
@@ -6604,7 +6502,8 @@
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 @@
// 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 8830097..866eeaf 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 <atomic>
#include <vector>
@@ -437,25 +438,11 @@
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 @@
std::vector<VkPipelineColorBlendAttachmentState> 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<VkVertexInputBindingDescription>(
+ pVICI->pVertexBindingDescriptions, pVICI->pVertexBindingDescriptions + pVICI->vertexBindingDescriptionCount);
+ }
+ if (pVICI->vertexAttributeDescriptionCount) {
+ this->vertexAttributeDescriptions = std::vector<VkVertexInputAttributeDescription>(
+ pVICI->pVertexAttributeDescriptions,
+ pVICI->pVertexAttributeDescriptions + pVICI->vertexAttributeDescriptionCount);
+ }
+ }
+ if (pCreateInfo->pColorBlendState) {
+ const VkPipelineColorBlendStateCreateInfo *pCBCI = pCreateInfo->pColorBlendState;
+ if (pCBCI->attachmentCount) {
+ this->attachments = std::vector<VkPipelineColorBlendAttachmentState>(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 88f1fa2..a976f24 100755
--- a/vk_helper.py
+++ b/vk_helper.py
@@ -1637,7 +1637,7 @@
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 <string.h>\n\n')
return "".join(header)
def _generateSafeStructSource(self):
@@ -1650,7 +1650,7 @@
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 @@
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)