Hi! I don’t understand this error message :
validation layer: vkCreatePipelineLayout(): pCreateInfo->flags contains flag bits (0xbaadf00d) which are not recognized members of VkPipelineLayoutCreateFlagBits.
The Vulkan spec states: flags must be a valid combination of VkPipelineLayoutCreateFlagBits values (https://vulkan.lunarg.com/doc/view/1.4.309.0/windows/antora/spec/latest/chapters/descriptorsets.html#VUID-VkPipelineLayoutCreateInfo-flags-parameter)
I draw things the same way than I do with opengl :
void PerPixelLinkedListRenderComponent::drawInstances() {
for (unsigned int i = 0; i < Batcher::nbPrimitiveTypes; i++) {
vbBindlessTex[i].clear();
materialDatas[i].clear();
modelDatas[i].clear();
}
std::array<std::vector<DrawArraysIndirectCommand>, Batcher::nbPrimitiveTypes> drawArraysIndirectCommands;
std::array<unsigned int, Batcher::nbPrimitiveTypes> firstIndex, baseInstance;
for (unsigned int i = 0; i < firstIndex.size(); i++) {
firstIndex[i] = 0;
}
for (unsigned int i = 0; i < baseInstance.size(); i++) {
baseInstance[i] = 0;
}
for (unsigned int i = 0; i < m_normals.size(); i++) {
if (m_normals[i].getAllVertices().getVertexCount() > 0) {
DrawArraysIndirectCommand drawArraysIndirectCommand;
//std::cout<<"next frame draw normal"<<std::endl;
if (core::Application::app != nullptr) {
float time = core::Application::getTimeClk().getElapsedTime().asSeconds();
indirectDrawPushConsts.time = time;
}
unsigned int p = m_normals[i].getAllVertices().getPrimitiveType();
/*if (m_normals[i].getVertexArrays()[0]->getEntity()->getRootType() == "E_MONSTER") {
std::cout<<"tex coords : "<<(*m_normals[i].getVertexArrays()[0])[0].texCoords.x<<","<<(*m_normals[i].getVertexArrays()[0])[0].texCoords.y<<std::endl;
}*/
unsigned int vertexCount = 0;
MaterialData material;
material.textureIndex = (m_normals[i].getMaterial().getTexture() != nullptr) ? m_normals[i].getMaterial().getTexture()->getId() : 0;
material.materialType = m_normals[i].getMaterial().getType();
materialDatas[p].push_back(material);
for (unsigned int j = 0; j < m_normals[i].getAllVertices().getVertexCount(); j++) {
vbBindlessTex[p].append(m_normals[i].getAllVertices()[j]);
vertexCount++;
}
TransformMatrix tm;
ModelData modelData;
modelData.worldMat = tm.getMatrix().transpose();
modelDatas[p].push_back(modelData);
drawArraysIndirectCommand.count = vertexCount;
drawArraysIndirectCommand.firstIndex = firstIndex[p];
drawArraysIndirectCommand.baseInstance = baseInstance[p];
drawArraysIndirectCommand.instanceCount = 1;
drawArraysIndirectCommands[p].push_back(drawArraysIndirectCommand);
firstIndex[p] += vertexCount;
baseInstance[p] += 1;
/*for (unsigned int j = 0; j < m_normals[i].getVertexArrays().size(); j++) {
if (m_normals[i].getVertexArrays()[j]->getEntity() != nullptr && m_normals[i].getVertexArrays()[j]->getEntity()->getRootType() == "E_HERO") {
for (unsigned int n = 0; n < m_normals[i].getVertexArrays()[j]->getVertexCount(); n++)
std::cout<<"position hero : "<<(*m_normals[i].getVertexArrays()[j])[n].position.x<<","<<(*m_normals[i].getVertexArrays()[j])[n].position.y<<","<<(*m_normals[i].getVertexArrays()[j])[n].position.z<<std::endl;
}
}*/
}
}
for (unsigned int i = 0; i < m_instances.size(); i++) {
if (m_instances[i].getAllVertices().getVertexCount() > 0) {
DrawArraysIndirectCommand drawArraysIndirectCommand;
unsigned int p = m_instances[i].getAllVertices().getPrimitiveType();
if (core::Application::app != nullptr) {
float time = core::Application::getTimeClk().getElapsedTime().asSeconds();
indirectDrawPushConsts.time = time;
}
std::vector<TransformMatrix*> tm = m_instances[i].getTransforms();
for (unsigned int j = 0; j < tm.size(); j++) {
tm[j]->update();
ModelData modelData;
modelData.worldMat = tm[j]->getMatrix().transpose();
modelDatas[p].push_back(modelData);
}
MaterialData materialData;
materialData.textureIndex = (m_instances[i].getMaterial().getTexture() != nullptr) ? m_instances[i].getMaterial().getTexture()->getId() : 0;
materialData.materialType = m_instances[i].getMaterial().getType();
materialDatas[p].push_back(materialData);
unsigned int vertexCount = 0;
if (m_instances[i].getVertexArrays().size() > 0) {
Entity* entity = m_instances[i].getVertexArrays()[0]->getEntity();
for (unsigned int j = 0; j < m_instances[i].getVertexArrays().size(); j++) {
if (entity == m_instances[i].getVertexArrays()[j]->getEntity()) {
for (unsigned int k = 0; k < m_instances[i].getVertexArrays()[j]->getVertexCount(); k++) {
vertexCount++;
vbBindlessTex[p].append((*m_instances[i].getVertexArrays()[j])[k]);
}
}
}
}
drawArraysIndirectCommand.count = vertexCount;
drawArraysIndirectCommand.firstIndex = firstIndex[p];
drawArraysIndirectCommand.baseInstance = baseInstance[p];
drawArraysIndirectCommand.instanceCount = tm.size();
drawArraysIndirectCommands[p].push_back(drawArraysIndirectCommand);
firstIndex[p] += vertexCount;
baseInstance[p] += tm.size();
//std::cout<<"texture : "<<m_instances[i].getMaterial().getTexture()<<std::endl;
//std::cout<<"entity : "<<m_instances[i].getVertexArrays()[0]->getEntity()->getRootEntity()->getType()<<std::endl;
}
}
RenderStates currentStates;
currentStates.blendMode = sf::BlendNone;
currentStates.shader = &indirectRenderingShader;
currentStates.texture = nullptr;
for (unsigned int p = 0; p < Batcher::nbPrimitiveTypes; p++) {
if (vbBindlessTex[p].getVertexCount() > 0) {
VkDeviceSize bufferSize = sizeof(ModelData) * modelDatas[p].size();
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(vkDevice.getDevice(), stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, modelDatas[p].data(), (size_t)bufferSize);
vkUnmapMemory(vkDevice.getDevice(), stagingBufferMemory);
modelDataShaderStorageBuffers.resize(frameBuffer.getMaxFramesInFlight());
modelDataShaderStorageBuffersMemory.resize(frameBuffer.getMaxFramesInFlight());
for (unsigned int i = 0; i < frameBuffer.getMaxFramesInFlight(); i++) {
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, modelDataShaderStorageBuffers[i], modelDataShaderStorageBuffersMemory[i]);
copyBuffer(stagingBuffer, modelDataShaderStorageBuffers[i], bufferSize);
}
vkDestroyBuffer(vkDevice.getDevice(), stagingBuffer, nullptr);
vkFreeMemory(vkDevice.getDevice(), stagingBufferMemory, nullptr);
bufferSize = sizeof(MaterialData) * materialDatas[p].size();
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
vkMapMemory(vkDevice.getDevice(), stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, materialDatas[p].data(), (size_t)bufferSize);
vkUnmapMemory(vkDevice.getDevice(), stagingBufferMemory);
materialDataShaderStorageBuffers.resize(frameBuffer.getMaxFramesInFlight());
materialDataShaderStorageBuffersMemory.resize(frameBuffer.getMaxFramesInFlight());
for (unsigned int i = 0; i < frameBuffer.getMaxFramesInFlight(); i++) {
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, materialDataShaderStorageBuffers[i], materialDataShaderStorageBuffersMemory[i]);
copyBuffer(stagingBuffer, materialDataShaderStorageBuffers[i], bufferSize);
}
vkDestroyBuffer(vkDevice.getDevice(), stagingBuffer, nullptr);
vkFreeMemory(vkDevice.getDevice(), stagingBufferMemory, nullptr);
bufferSize = sizeof(DrawArraysIndirectCommand) * drawArraysIndirectCommands.size();
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
vkMapMemory(vkDevice.getDevice(), stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, drawArraysIndirectCommands.data(), (size_t)bufferSize);
vkUnmapMemory(vkDevice.getDevice(), stagingBufferMemory);
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vboIndirect, vboIndirectMemory);
copyBuffer(stagingBuffer, vboIndirect, bufferSize);
vkDestroyBuffer(vkDevice.getDevice(), stagingBuffer, nullptr);
vkFreeMemory(vkDevice.getDevice(), stagingBufferMemory, nullptr);
createDescriptorPool();
createDescriptorSetLayout();
createDescriptorSets(p);
frameBuffer.updateDescriptors(descriptorPool, descriptorSetLayout, descriptorSets);
frameBuffer.createGraphicPipeline(vbBindlessTex[p].getPrimitiveType(), currentStates);
createCommandBuffersIndirect(p, currentStates);
vbBindlessTex[p].clear();
}
}
}
And I create the pipeline like this :
void RenderTarget::createGraphicPipeline(sf::PrimitiveType type,
RenderStates states = RenderStates::Default) {
VkShaderModule vertShaderModule;
VkShaderModule fragShaderModule;
if (states.shader == nullptr) {
if (states.texture != nullptr) {
defaultShader.createShaderModules();
vertShaderModule = defaultShader.getVertexShaderModule();
fragShaderModule = defaultShader.getFragmentShaderModule();
} else {
defaultShader2.createShaderModules();
vertShaderModule = defaultShader2.getVertexShaderModule();
fragShaderModule = defaultShader2.getFragmentShaderModule();
}
} else {
Shader* shader = const_cast<Shader*>(states.shader);
shader->createShaderModules();
vertShaderModule = shader->getVertexShaderModule();
fragShaderModule = shader->getFragmentShaderModule();
}
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
auto bindingDescription = Vertex::getBindingDescription();
auto attributeDescriptions = Vertex::getAttributeDescriptions();
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
VkPrimitiveTopology modes[] = {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN};
inputAssembly.topology = modes[type];
inputAssembly.primitiveRestartEnable = VK_FALSE;
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = getSwapchainExtents().width;
viewport.height = getSwapchainExtents().height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor{};
scissor.offset = {0, 0};
scissor.extent = getSwapchainExtents();
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_TRUE;
sf::BlendMode mode = states.blendMode;
colorBlendAttachment.srcColorBlendFactor = factorToVkConstant(mode.colorSrcFactor);
colorBlendAttachment.dstColorBlendFactor = factorToVkConstant(mode.colorDstFactor);
colorBlendAttachment.colorBlendOp = equationToVkConstant(mode.colorEquation);
colorBlendAttachment.srcAlphaBlendFactor = factorToVkConstant(mode.alphaSrcFactor);
colorBlendAttachment.dstAlphaBlendFactor = factorToVkConstant(mode.alphaDstFactor);
colorBlendAttachment.alphaBlendOp = equationToVkConstant(mode.alphaEquation);
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f;
colorBlending.blendConstants[1] = 0.0f;
colorBlending.blendConstants[2] = 0.0f;
colorBlending.blendConstants[3] = 0.0f;
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
if (vkCreatePipelineLayout(vkDevice.getDevice(), &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
throw core::Erreur(0, "failed to create pipeline layout!", 1);
}
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.layout = pipelineLayout;
pipelineInfo.renderPass = getRenderPass();
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
if (vkCreateGraphicsPipelines(vkDevice.getDevice(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
throw core::Erreur(0, "failed to create graphics pipeline!", 1);
}
if (states.shader == nullptr) {
if (states.texture != nullptr)
defaultShader.cleanupShaderModules();
else
defaultShader2.cleanupShaderModules();
} else {
Shader* shader = const_cast<Shader*>(states.shader);
shader->cleanupShaderModules();
}
}
Perhaps a flag is needed with push constants or something else…
Thanks.