struct render_pass;
struct layer_data {
- debug_report_data *report_data;
+ debug_report_data* report_data;
// TODO: put instance data here
std::vector<VkDbgMsgCallback> logging_callback;
VkLayerDispatchTable* device_dispatch_table;
unordered_map<VkCommandPool, list<VkCommandBuffer>> commandPoolMap;
unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE*> descriptorPoolMap;
unordered_map<VkDescriptorSet, SET_NODE*> setMap;
- unordered_map<VkDescriptorSetLayout, LAYOUT_NODE*> layoutMap;
+ unordered_map<VkDescriptorSetLayout, LAYOUT_NODE*> descriptorSetLayoutMap;
unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap;
unordered_map<VkDeviceMemory, VkImage> memImageMap;
// Map for layout chains
unordered_map<VkFramebuffer, VkFramebufferCreateInfo*> frameBufferMap;
unordered_map<VkImage, IMAGE_NODE*> imageLayoutMap;
unordered_map<VkRenderPass, RENDER_PASS_NODE*> renderPassMap;
- // Data structs from shaderChecker TODO : Merge 3 duplicate maps with one above
- unordered_map<VkShaderModule, shader_module *> shader_module_map;
- unordered_map<VkDescriptorSetLayout, std::unordered_set<uint32_t>*> descriptor_set_layout_map;
- unordered_map<VkPipelineLayout, std::vector<std::unordered_set<uint32_t>*>*> pipeline_layout_map;
- unordered_map<VkRenderPass, render_pass *> render_pass_map;
+ unordered_map<VkShaderModule, shader_module*> shaderModuleMap;
// Current render pass
VkRenderPassBeginInfo renderPassBeginInfo;
uint32_t currentSubpass;
}
};
-struct render_pass {
- vector<std::vector<VkFormat>> subpass_color_formats;
-
- render_pass(VkRenderPassCreateInfo const *pCreateInfo)
- {
- uint32_t i;
-
- subpass_color_formats.reserve(pCreateInfo->subpassCount);
- for (i = 0; i < pCreateInfo->subpassCount; i++) {
- const VkSubpassDescription *subpass = &pCreateInfo->pSubpasses[i];
- vector<VkFormat> color_formats;
- uint32_t j;
-
- color_formats.reserve(subpass->colorAttachmentCount);
- for (j = 0; j < subpass->colorAttachmentCount; j++) {
- const uint32_t att = subpass->pColorAttachments[j].attachment;
- const VkFormat format = pCreateInfo->pAttachments[att].format;
-
- color_formats.push_back(pCreateInfo->pAttachments[att].format);
- }
-
- subpass_color_formats.push_back(color_formats);
- }
- }
-};
-
// TODO : Do we need to guard access to layer_data_map w/ lock?
-static unordered_map<void *, layer_data *> layer_data_map;
+static unordered_map<void*, layer_data*> layer_data_map;
static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(g_initOnce);
// TODO : This can be much smarter, using separate locks for separate global data
}
static bool
-validate_fs_outputs_against_render_pass(layer_data *my_data, VkDevice dev, shader_module const *fs, render_pass const *rp, uint32_t subpass)
+validate_fs_outputs_against_render_pass(layer_data *my_data, VkDevice dev, shader_module const *fs, RENDER_PASS_NODE const *rp, uint32_t subpass)
{
- const std::vector<VkFormat> &color_formats = rp->subpass_color_formats[subpass];
+ const std::vector<VkFormat> &color_formats = rp->subpassColorFormats[subpass];
std::map<uint32_t, interface_var> outputs;
std::map<uint32_t, interface_var> builtin_outputs;
bool pass = true;
{ "fragment shader", false },
};
-
+// For given pipelineLayout verify that the setLayout at slot.first
+// has the requested binding at slot.second
static bool
-has_descriptor_binding(std::vector<std::unordered_set<uint32_t>*>* layout,
+has_descriptor_binding(layer_data* my_data,
+ vector<VkDescriptorSetLayout>* pipelineLayout,
std::pair<unsigned, unsigned> slot)
{
- if (!layout)
+ if (!pipelineLayout)
return false;
- if (slot.first >= layout->size())
+ if (slot.first >= pipelineLayout->size())
return false;
- auto set = (*layout)[slot.first];
+ auto set = my_data->descriptorSetLayoutMap[(*pipelineLayout)[slot.first]]->bindings;
- return (set->find(slot.second) != set->end());
+ return (set.find(slot.second) != set.end());
}
static uint32_t get_shader_stage_id(VkShaderStageFlagBits stage)
return false;
}
// Get the specific setLayout from PipelineLayout that overlaps this set
- LAYOUT_NODE* pLayoutNode = my_data->layoutMap[pl.descriptorSetLayouts[layoutIndex]];
+ LAYOUT_NODE* pLayoutNode = my_data->descriptorSetLayoutMap[pl.descriptorSetLayouts[layoutIndex]];
if (pLayoutNode->layout == pSet->pLayout->layout) { // trivial pass case
return true;
}
// // Now check each matching layout to confirm compatibility
// LAYOUT_NODE *pPSOLayout, *pDSLayout;
// for (uint32_t i=0; i<numDescriptorSets; ++i) {
-// pPSOLayout = my_data->layoutMap[psoPL.descriptorSetLayouts[i]];
-// pDSLayout = my_data->layoutMap[dsPL.descriptorSetLayouts[i]];
+// pPSOLayout = my_data->descriptorSetLayoutMap[psoPL.descriptorSetLayouts[i]];
+// pDSLayout = my_data->descriptorSetLayoutMap[dsPL.descriptorSetLayouts[i]];
// if (pPSOLayout == pDSLayout)
// continue;
// if (pPSOLayout->descriptorTypes.size() != pDSLayout->descriptorTypes.size()) {
// return skipCall;
//}
static bool
-validate_graphics_pipeline(layer_data *my_data, VkDevice dev, VkGraphicsPipelineCreateInfo const *pCreateInfo)
+validate_pipeline_shaders(layer_data *my_data, VkDevice dev, VkGraphicsPipelineCreateInfo const *pCreateInfo)
{
/* We seem to allow pipeline stages to be specified out of order, so collect and identify them
* before trying to do anything more: */
shader_module **shaders = new shader_module*[fragment_stage + 1]; /* exclude CS */
memset(shaders, 0, sizeof(shader_module *) * (fragment_stage +1));
- render_pass const *rp = 0;
+ RENDER_PASS_NODE const *rp = 0;
VkPipelineVertexInputStateCreateInfo const *vi = 0;
bool pass = true;
}
}
else {
- shader_module *module = my_data->shader_module_map[pStage->module];
+ shader_module *module = my_data->shaderModuleMap[pStage->module];
shaders[get_shader_stage_id(pStage->stage)] = module;
/* validate descriptor set layout against what the spirv module actually uses */
collect_interface_by_descriptor_slot(my_data, dev, module, spv::StorageClassUniform,
descriptor_uses);
- auto layout = pCreateInfo->layout != VK_NULL_HANDLE ?
- my_data->pipeline_layout_map[pCreateInfo->layout] : nullptr;
+ auto layouts = pCreateInfo->layout != VK_NULL_HANDLE ?
+ &(my_data->pipelineLayoutMap[pCreateInfo->layout].descriptorSetLayouts) : nullptr;
for (auto it = descriptor_uses.begin(); it != descriptor_uses.end(); it++) {
/* find the matching binding */
- auto found = has_descriptor_binding(layout, it->first);
+ auto found = has_descriptor_binding(my_data, layouts, it->first);
if (!found) {
char type_name[1024];
}
if (pCreateInfo->renderPass != VK_NULL_HANDLE)
- rp = my_data->render_pass_map[pCreateInfo->renderPass];
+ rp = my_data->renderPassMap[pCreateInfo->renderPass];
vi = pCreateInfo->pVertexInputState;
static VkBool32 verifyPipelineCreateState(layer_data* my_data, const VkDevice device, const PIPELINE_NODE* pPipeline)
{
VkBool32 skipCall = VK_FALSE;
+ if (!validate_pipeline_shaders(my_data, device, &(pPipeline->graphicsPipelineCI))) {
+ skipCall = VK_TRUE;
+ }
// VS is required
if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) {
skipCall |= log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType) 0, 0, 0, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
// Verify that any MSAA request in PSO matches sample# in bound FB
VkSampleCountFlagBits psoNumSamples = getNumSamples(my_data, pipeline);
if (pCB->activeRenderPass) {
- const VkRenderPassCreateInfo* pRPCI = my_data->renderPassMap[pCB->activeRenderPass]->createInfo;
+ const VkRenderPassCreateInfo* pRPCI = my_data->renderPassMap[pCB->activeRenderPass]->pCreateInfo;
const VkSubpassDescription* pSD = &pRPCI->pSubpasses[pCB->activeSubpass];
VkSampleCountFlagBits subpassNumSamples = (VkSampleCountFlagBits) 0;
uint32_t i;
static LAYOUT_NODE* getLayoutNode(layer_data* my_data, const VkDescriptorSetLayout layout) {
loader_platform_thread_lock_mutex(&globalLock);
- if (my_data->layoutMap.find(layout) == my_data->layoutMap.end()) {
+ if (my_data->descriptorSetLayoutMap.find(layout) == my_data->descriptorSetLayoutMap.end()) {
loader_platform_thread_unlock_mutex(&globalLock);
return NULL;
}
loader_platform_thread_unlock_mutex(&globalLock);
- return my_data->layoutMap[layout];
+ return my_data->descriptorSetLayoutMap[layout];
}
// Return VK_FALSE if update struct is of valid type, otherwise flag error and return code from callback
// NOTE : Calls to this function should be wrapped in mutex
static void deleteLayouts(layer_data* my_data)
{
- if (my_data->layoutMap.size() <= 0)
+ if (my_data->descriptorSetLayoutMap.size() <= 0)
return;
- for (auto ii=my_data->layoutMap.begin(); ii!=my_data->layoutMap.end(); ++ii) {
+ for (auto ii=my_data->descriptorSetLayoutMap.begin(); ii!=my_data->descriptorSetLayoutMap.end(); ++ii) {
LAYOUT_NODE* pLayout = (*ii).second;
if (pLayout->createInfo.pBinding) {
for (uint32_t i=0; i<pLayout->createInfo.bindingCount; i++) {
}
delete pLayout;
}
- my_data->layoutMap.clear();
+ my_data->descriptorSetLayoutMap.clear();
}
// Currently clearing a set is removing all previous updates to that set
uint32_t i=0;
loader_platform_thread_lock_mutex(&globalLock);
- bool pass = true;
for (i=0; i<count; i++) {
pPipeNode[i] = initGraphicsPipeline(dev_data, &pCreateInfos[i], NULL);
- // TODOSC : Merge SC validate* func w/ verifyPipelineCS func
- pass = validate_graphics_pipeline(dev_data, device, &pCreateInfos[i]) && pass;
skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]);
}
loader_platform_thread_unlock_mutex(&globalLock);
- if ((VK_FALSE == skipCall) && pass) {
+ if (VK_FALSE == skipCall) {
result = dev_data->device_dispatch_table->CreateGraphicsPipelines(device,
pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
loader_platform_thread_lock_mutex(&globalLock);
assert(pNewNode->endIndex >= pNewNode->startIndex);
// Put new node at Head of global Layer list
loader_platform_thread_lock_mutex(&globalLock);
- dev_data->layoutMap[*pSetLayout] = pNewNode;
- // TODOSC : Currently duplicating data struct here, need to unify
- auto& bindings = dev_data->descriptor_set_layout_map[*pSetLayout];
- bindings = new std::unordered_set<uint32_t>();
- bindings->reserve(pCreateInfo->bindingCount);
- for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++)
- bindings->insert(pCreateInfo->pBinding[i].binding);
-
+ dev_data->descriptorSetLayoutMap[*pSetLayout] = pNewNode;
loader_platform_thread_unlock_mutex(&globalLock);
}
return result;
for (i=0; i<pCreateInfo->pushConstantRangeCount; ++i) {
plNode.pushConstantRanges[i] = pCreateInfo->pPushConstantRanges[i];
}
- // TODOSC : Code merged from SC duplicates data structs, need to unify
- loader_platform_thread_lock_mutex(&globalLock);
- auto& layouts = dev_data->pipeline_layout_map[*pPipelineLayout];
- layouts = new vector<unordered_set<uint32_t>*>();
- layouts->reserve(pCreateInfo->setLayoutCount);
- for (unsigned i = 0; i < pCreateInfo->setLayoutCount; i++) {
- layouts->push_back(dev_data->descriptor_set_layout_map[pCreateInfo->pSetLayouts[i]]);
- }
- loader_platform_thread_unlock_mutex(&globalLock);
}
return result;
}
// Validate that attachment is in reference list of active subpass
if (pCB->activeRenderPass) {
- const VkRenderPassCreateInfo *pRPCI = dev_data->renderPassMap[pCB->activeRenderPass]->createInfo;
+ const VkRenderPassCreateInfo *pRPCI = dev_data->renderPassMap[pCB->activeRenderPass]->pCreateInfo;
const VkSubpassDescription *pSD = &pRPCI->pSubpasses[pCB->activeSubpass];
for (uint32_t attachment_idx = 0; attachment_idx < attachmentCount; attachment_idx++) {
if (res == VK_SUCCESS) {
loader_platform_thread_lock_mutex(&globalLock);
- my_data->shader_module_map[*pShaderModule] = new shader_module(pCreateInfo);
+ my_data->shaderModuleMap[*pShaderModule] = new shader_module(pCreateInfo);
loader_platform_thread_unlock_mutex(&globalLock);
}
return res;
memcpy((void*)localRPCI->pDependencies, pCreateInfo->pDependencies, localRPCI->dependencyCount*sizeof(VkSubpassDependency));
}
loader_platform_thread_lock_mutex(&globalLock);
- dev_data->renderPassMap[*pRenderPass] = new RENDER_PASS_NODE();
+ dev_data->renderPassMap[*pRenderPass] = new RENDER_PASS_NODE(localRPCI);
dev_data->renderPassMap[*pRenderPass]->hasSelfDependency = has_self_dependency;
- dev_data->renderPassMap[*pRenderPass]->createInfo = localRPCI;
- // TODOSC : Duplicate data struct here, need to unify
- dev_data->render_pass_map[*pRenderPass] = new render_pass(pCreateInfo);
loader_platform_thread_unlock_mutex(&globalLock);
}
return result;
if (my_data->renderPassMap.size() <= 0)
return;
for (auto ii=my_data->renderPassMap.begin(); ii!=my_data->renderPassMap.end(); ++ii) {
- const VkRenderPassCreateInfo* pRenderPassInfo = (*ii).second->createInfo;
+ const VkRenderPassCreateInfo* pRenderPassInfo = (*ii).second->pCreateInfo;
if (pRenderPassInfo->pAttachments) {
delete[] pRenderPassInfo->pAttachments;
}
if (pRenderPassInfo->pDependencies) {
delete[] pRenderPassInfo->pDependencies;
}
+ delete pRenderPassInfo;
delete (*ii).second;
}
my_data->renderPassMap.clear();
bool skip_call = false;
layer_data* dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
GLOBAL_CB_NODE* pCB = getCBNode(dev_data, cmdBuffer);
- const VkRenderPassCreateInfo* pRenderPassInfo = dev_data->renderPassMap[pRenderPassBegin->renderPass]->createInfo;
+ const VkRenderPassCreateInfo* pRenderPassInfo = dev_data->renderPassMap[pRenderPassBegin->renderPass]->pCreateInfo;
const VkFramebufferCreateInfo* pFramebufferInfo = dev_data->frameBufferMap[pRenderPassBegin->framebuffer];
if (pRenderPassInfo->attachmentCount != pFramebufferInfo->attachmentCount) {
skip_call |= log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, DRAWSTATE_INVALID_RENDERPASS, "DS",
if (render_pass_data == dev_data->renderPassMap.end()) {
return;
}
- const VkRenderPassCreateInfo* pRenderPassInfo = render_pass_data->second->createInfo;
+ const VkRenderPassCreateInfo* pRenderPassInfo = render_pass_data->second->pCreateInfo;
auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer);
if (framebuffer_data == dev_data->frameBufferMap.end()) {
return;
if (render_pass_data == dev_data->renderPassMap.end()) {
return;
}
- const VkRenderPassCreateInfo* pRenderPassInfo = render_pass_data->second->createInfo;
+ const VkRenderPassCreateInfo* pRenderPassInfo = render_pass_data->second->pCreateInfo;
auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer);
if (framebuffer_data == dev_data->frameBufferMap.end()) {
return;