问题描述
我目前正在学习Vulkan,并且试图编写一个可以并排绘制场景和场景深度缓冲区的应用程序。
起初,我考虑过使用单个子通道渲染范围为Object.keys(selectedFilters).forEach(k=> {
// properties[k] if exists -> will give you required data
})
的框架,然后使用(width/2) x height
两次将生成的框架及其深度图像复制到交换链,但是我很快发现了交换链图片不一定支持vkCmdBlitimage
。
我当前的策略是在单个渲染过程中使用两个子过程。 第一个子通道使用视口将结果帧渲染到屏幕的左侧,第二个子通道将第一个子通道的深度附件作为输入附件,并将其渲染到屏幕的右侧。
我的第一个问题是,该策略似乎非常浪费,因为我必须使用深度为VK_IMAEG_USAGE_TRANSFER_DST_BIT
(而不是width x height
)的深度图像,因此如果由您自己决定,您将如何实施这个应用程序?
我的第二个问题是深度图像根本没有显示!
颜色附件在左边显示得很好(如果在视口之间切换,它也可以在右边显示得很好),但是在右边(应该是深度图像),我得到了(width/2) x height
-彩色的屏幕。
深度缓冲区本身工作正常(屏幕上的对象以正确的顺序呈现),并且看起来片段着色器工作正常(我尝试在不使用输入附件的情况下编写不同的颜色,并且工作正常)。>
我用尽了所有可能出现问题的想法,我认为这与subpass依赖关系有关,因为看起来深度值未写入缓冲区(或在写入之前已被访问)。
相关代码:
clearValue
我试图尽可能地削减代码,因此/***************/
/* Render pass */
/***************/
{
const VkAttachmentDescription attachments[] = {
// Color attachment
{
.flags = 0,.format = swapchain->format,.samples = VK_SAMPLE_COUNT_1_BIT,.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,.storeOp = VK_ATTACHMENT_STORE_OP_STORE,//.stencilLoadOp = <uninitialized>,//.stencilstoreOp = <uninitialized>,.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,},// Depth attachment / Input attachment
{
.flags = 0,.format = VK_FORMAT_D32_SFLOAT,.samples = VK_SAMPLE_COUNT_1_BIT,.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,.stencilstoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,};
const VkSubpassDescription subpasses[] = {
// First subpass - Render "regular" frame
{
.flags = 0,.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,.inputAttachmentCount = 0,//.pInputAttachments = <uninitialized>,.colorAttachmentCount = 1,.pColorAttachments = (VkAttachmentReference[]) {
{ 0,VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL },.pResolveAttachments = NULL,.pDepthStencilAttachment = (VkAttachmentReference[]) {
{ 1,VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL },.preserveAttachmentCount = 0,//.pPreserveAttachments = <uninitialized>,// Second subpass - Render depth image
{
.flags = 0,.inputAttachmentCount = 1,.pInputAttachments = (VkAttachmentReference[]) {
{ 1,VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL },.pDepthStencilAttachment = NULL,};
const VkSubpassDependency dependencies[] = {
{
.srcSubpass = VK_SUBPASS_EXTERNAL,.dstSubpass = 0,.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,.srcAccessMask = 0,.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,{
.srcSubpass = 0,.dstSubpass = 1,.srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,};
const VkRenderPassCreateInfo create_info = {
.flags = 0,.attachmentCount = sizeof(attachments) / sizeof(attachments[0]),.pAttachments = attachments,.subpassCount = sizeof(subpasses) / sizeof(subpasses[0]),.pSubpasses = subpasses,.dependencyCount = sizeof(dependencies) / sizeof(dependencies[0]),.pDependencies = dependencies,};
vulkan_result = vkCreateRenderPass(device,&create_info,NULL,&swapchain->renderPass);
assert(vulkan_result == VK_SUCCESS);
}
/**************************/
/* Descriptor set layouts */
/**************************/
{
// MVP matrices
VkDescriptorSetLayoutCreateInfo create_info = {
.flags = 0,.bindingCount = 1,.pBindings = (VkDescriptorSetLayoutBinding[]) {
{
.binding = 0,.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,.descriptorCount = 1,.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,.pImmutableSamplers = NULL,}
},};
vulkan_result = vkCreateDescriptorSetLayout(device,&renderer->setLayouts.color);
assert(vulkan_result == VK_SUCCESS);
// Input attachment for depth image
create_info.pBindings = (VkDescriptorSetLayoutBinding[]) {
{
.binding = 0,.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,}
};
vulkan_result = vkCreateDescriptorSetLayout(device,&renderer->setLayouts.depth);
assert(vulkan_result == VK_SUCCESS);
}
/********************/
/* Pipeline layouts */
/********************/
{
VkPipelineLayoutCreateInfo create_info = {
.flags = 0,.setLayoutCount = 1,.pSetLayouts = &renderer->setLayouts.color,.pushConstantRangeCount = 0,//.pPushConstantRanges = <uninitialized>,};
vulkan_result = vkCreatePipelineLayout(device,&renderer->pipelineLayouts.color);
assert(vulkan_result == VK_SUCCESS);
create_info.pSetLayouts = &renderer->setLayouts.depth;
vulkan_result = vkCreatePipelineLayout(device,&renderer->pipelineLayouts.depth);
assert(vulkan_result == VK_SUCCESS);
}
/*************/
/* Pipelines */
/*************/
{
size_t code_size;
uint32_t *code;
code = read_file("shaders/color_vert.spv",&code_size);
VkShaderModuleCreateInfo shader_module_create_info = {
.flags = 0,.codeSize = code_size,.pCode = code,};
VkShaderModule vertex_module;
vulkan_result = vkCreateShaderModule(device,&shader_module_create_info,&vertex_module);
free(code);
assert(vulkan_result == VK_SUCCESS);
code = read_file("shaders/color_frag.spv",&code_size);
if (code == NULL) {
vkDestroyShaderModule(device,vertex_module,NULL);
}
shader_module_create_info.codeSize = code_size;
shader_module_create_info.pCode = code;
VkShaderModule fragment_module;
vulkan_result = vkCreateShaderModule(device,&fragment_module);
assert(vulkan_result == VK_SUCCESS);
free(code);
VkPipelineshaderStageCreateInfo stages[] = {
{
.flags = 0,.stage = VK_SHADER_STAGE_VERTEX_BIT,.module = vertex_module,.pName = "main",.pSpecializationInfo = NULL,{
.flags = 0,.stage = VK_SHADER_STAGE_FRAGMENT_BIT,.module = fragment_module,}
};
const VkVertexInputBindingDescription vertex_binding_description = {
.binding = 0,.stride = sizeof(struct Vertex),.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,};
const VkVertexInputAttributeDescription vertex_attribute_description[] = {
// Position
{
.location = 0,.binding = 0,.format = VK_FORMAT_R32G32B32_SFLOAT,.offset = offsetof(struct Vertex,position),// Color
{
.location = 1,color),}
};
VkPipelineVertexInputStateCreateInfo vertex_input_state = {
.flags = 0,.vertexBindingDescriptionCount = 1,.pVertexBindingDescriptions = &vertex_binding_description,.vertexAttributeDescriptionCount = sizeof(vertex_attribute_description) / sizeof(vertex_attribute_description[0]),.pVertexAttributeDescriptions = vertex_attribute_description,};
VkPipelineInputAssemblyStateCreateInfo input_assembly_state = {
.flags = 0,.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,.primitiveRestartEnable = VK_FALSE,};
VkPipelineViewportStateCreateInfo viewport_state = {
.flags = 0,.viewportCount = 1,.pViewports = (VkViewport[]) {
{
.x = 0.0f,.y = 0.0f,.width = (float) extent.width / 2,.height = (float) extent.height,.minDepth = 0.0f,.maxDepth = 1.0f,.scissorCount = 1,.pScissors = (VkRect2D[]) {
{
.offset = { 0,0 },.extent = { extent.width / 2,extent.height },};
VkPipelineRasterizationStateCreateInfo rasterization_state = {
.flags = 0,.depthClampEnable = VK_FALSE,.rasterizerdiscardEnable = VK_FALSE,.polygonMode = VK_polyGON_MODE_FILL,.cullMode = VK_CULL_MODE_BACK_BIT,.frontFace = VK_FRONT_FACE_COUNTER_Clockwise,.depthBiasEnable = VK_FALSE,//.depthBiasConstantFactor =,//.depthBiasClamp =,//.depthBiasSlopeFactor =,.linewidth = 1.0f,};
const VkPipelineMultisampleStateCreateInfo multisample_state = {
.flags = 0,.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,.sampleShadingEnable = VK_FALSE,.minSampleShading = 1.0f,.pSampleMask = NULL,.alphaToCoverageEnable = VK_FALSE,.alphaToOneEnable = VK_FALSE,};
VkPipelineDepthstencilstateCreateInfo depth_stencil_state = {
.flags = 0,.depthTestEnable = VK_TRUE,.depthWriteEnable = VK_TRUE,.depthCompareOp = VK_COMPARE_OP_LESS,.depthBoundsTestEnable = VK_FALSE,.stencilTestEnable = VK_FALSE,//.front = <uninitialized>,//.back = <uninitialized>,//.minDepthBounds = <uninitialized>,//.maxDepthBounds = <uninitialized>,};
const VkPipelineColorBlendAttachmentState attachments[] = {
{
.blendEnable = VK_FALSE,//.srcColorBlendFactor = <uninitialized>,//.dstColorBlendFactor = <uninitialized>,//.colorBlendOp = <uninitialized>,//.srcAlphaBlendFactor = <uninitialized>,//.dstAlphaBlendFactor = <uninitialized>,//.alphaBlendOp = <uninitialized>,.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,}
};
const VkPipelineColorBlendStateCreateInfo color_blend_state = {
.flags = 0,.logicopEnable = VK_FALSE,//.logicop = <uninitialized>,.attachmentCount = sizeof(attachments) / sizeof(attachments[0]),.pAttachments = attachments,//.blendConstants[4] = <uninitialized>,};
VkGraphicsPipelineCreateInfo create_info = {
.flags = 0,.stageCount = sizeof(stages) / sizeof(stages[0]),.pStages = stages,.pVertexInputState = &vertex_input_state,.pInputAssemblyState = &input_assembly_state,.ptessellationState = NULL,.pViewportState = &viewport_state,.pRasterizationState = &rasterization_state,.pMultisampleState = &multisample_state,.pDepthstencilstate = &depth_stencil_state,.pColorBlendState = &color_blend_state,.pDynamicState = NULL,.layout = renderer->pipelineLayouts.color,.renderPass = render_pass,.subpass = 0,//.basePipelineHandle =,//.basePipelineIndex =,};
vulkan_result = vkCreateGraphicsPipelines(device,1,&renderer->pipelines.color);
assert(vulkan_result == VK_SUCCESS);
vkDestroyShaderModule(device,fragment_module,NULL);
vkDestroyShaderModule(device,NULL);
code = read_file("shaders/depth_vert.spv",&code_size);
assert(code != NULL);
shader_module_create_info.codeSize = code_size;
shader_module_create_info.pCode = code;
vulkan_result = vkCreateShaderModule(device,&vertex_module);
assert(vulkan_result == VK_SUCCESS);
free(code);
code = read_file("shaders/depth_frag.spv",&fragment_module);
assert(vulkan_result == VK_SUCCESS);
free(code);
stages[0].module = vertex_module;
stages[1].module = fragment_module;
vertex_input_state.vertexBindingDescriptionCount = 0;
vertex_input_state.vertexAttributeDescriptionCount = 0;
viewport_state.pViewports = (VkViewport[]) {
{
.x = (float) extent.width / 2,};
viewport_state.pScissors = (VkRect2D[]) {
{
.offset = { extent.width / 2,}
};
rasterization_state.cullMode = VK_CULL_MODE_NONE;
create_info.pDepthstencilstate = NULL;
create_info.layout = renderer->pipelineLayouts.depth;
create_info.subpass = 1;
vulkan_result = vkCreateGraphicsPipelines(device,&renderer->pipelines.depth);
vkDestroyShaderModule(device,NULL);
assert(vulkan_result == VK_SUCCESS);
}
/****************/
/* Depth images */
/****************/
{
// renderer->depthImages is a wrapper around VkImage and VkImageView
// renderer->depthImages.images is a VkImage array with image_count elements
// renderer->depthImages.imagesViews are the views of the respective images
wn_images_init(renderer->device /* also includes physical device for memory allocation */,image_count,VK_FORMAT_D32_SFLOAT,VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,extent,&renderer->depthImages);
}
/****************/
/* Framebuffers */
/****************/
{
renderer->framebuffers = calloc(sizeof(VkFramebuffer),renderer->imageCount);
assert(renderer->framebuffers != NULL);
if (renderer->framebuffers == NULL) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
for (uint32_t i = 0; i < renderer->imageCount; i++) {
const VkImageView attachments[] = {
render_targets[i],renderer->depthImages.imagesViews[i],};
const VkFramebufferCreateInfo create_info = {
.flags = 0,.renderPass = render_pass,.pAttachments = attachments,.width = extent.width,.height = extent.height,.layers = 1,};
vulkan_result = vkCreateFramebuffer(device,renderer->framebuffers + i);
assert(vulkan_result == VK_SUCCESS);
}
}
/******************/
/* Uniform buffers */
/******************/
{
wn_buffer_init(renderer->device,sizeof(struct UniformBufferObject) * renderer->imageCount,VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,&renderer->uniformBuffer.buffers);
}
/*******************/
/* Descriptor pool */
/*******************/
{
const VkDescriptorPoolSize pool_sizes[] = {
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,renderer->imageCount },{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,};
const VkDescriptorPoolCreateInfo create_info = {
.flags = 0,.maxSets = renderer->imageCount * 2,.poolSizeCount = sizeof(pool_sizes) / sizeof(pool_sizes[0]),.pPoolSizes = pool_sizes,};
assert(vkCreateDescriptorPool(device,&renderer->descriptorPool) == VK_SUCCESS);
}
/*******************/
/* Descriptor sets */
/*******************/
{
VkDescriptorSetLayout layouts[renderer->imageCount];
for (uint32_t i = 0; i < renderer->imageCount; i++) {
layouts[i] = renderer->setLayouts.color;
}
VkDescriptorSetAllocateInfo allocate_info = {
.descriptorPool = renderer->descriptorPool,.descriptorSetCount = renderer->imageCount,.pSetLayouts = layouts,};
renderer->sets.color = calloc(renderer->imageCount,sizeof(VkDescriptorSet));
assert(renderer->sets.color != NULL);
vulkan_result = vkAllocateDescriptorSets(device,&allocate_info,renderer->sets.color);
assert(vulkan_result == VK_SUCCESS);
for (uint32_t i = 0; i < renderer->imageCount; i++) {
layouts[i] = renderer->setLayouts.depth;
}
renderer->sets.depth = calloc(renderer->imageCount,sizeof(VkDescriptorSet));
assert(renderer->sets.depth != NULL);
vulkan_result = vkAllocateDescriptorSets(device,renderer->sets.depth);
assert(vulkan_result == VK_SUCCESS);
for (uint32_t i = 0; i < renderer->imageCount; i++) {
const VkDescriptorBufferInfo buffer_info = {
.buffer = renderer->uniformBuffer.buffers.buffer,.offset = sizeof(struct UniformBufferObject) * i,.range = sizeof(struct UniformBufferObject),};
const VkDescriptorImageInfo image_info = {
.sampler = VK_NULL_HANDLE,.imageView = renderer->depthImages.imagesViews[i],.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,};
const VkWriteDescriptorSet writes[] = {
{
.dstSet = renderer->sets.color[i],.dstBinding = 0,//.dstArrayElement = <uninitialized>,//.pImageInfo = <uninitialized>,.pBufferInfo = &buffer_info,//.pTexelBufferView = <uninitialized>,{
.dstSet = renderer->sets.depth[i],.pImageInfo = &image_info,//.pBufferInfo = <uninitialized>,};
vkUpdateDescriptorSets(device,sizeof(writes) / sizeof(writes[0]),writes,NULL);
}
}
/*******************/
/* Command buffers */
/*******************/
{
renderer->commandBuffers = calloc(renderer->imageCount,sizeof(VkCommandBuffer));
if (renderer->commandBuffers == NULL)
return VK_ERROR_OUT_OF_HOST_MEMORY;
const VkCommandBufferAllocateInfo allocate_info = {
.commandPool = renderer->graphicsCommandPool,.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,.commandBufferCount = renderer->imageCount,};
vkAllocateCommandBuffers(device,renderer->commandBuffers);
const VkCommandBufferBeginInfo begin_info = {
.flags = 0
//.pInheritanceInfo = <uninitialized>,};
for (uint32_t i = 0; i < renderer->imageCount; i++) {
vkBeginCommandBuffer(renderer->commandBuffers[i],&begin_info);
const VkRenderPassBeginInfo render_pass_begin_info = {
.renderPass = render_pass,.framebuffer = renderer->framebuffers[i],.renderArea = {
.offset = { 0,.extent = { extent.width,.clearValueCount = 2,.pClearValues = (VkClearValue[]) {
{ { { 0.2f,0.2f,1.0f } } },// Grey background
{ { { 1.0f,/*<uninitialized>*/ } } },};
vkCmdBeginRenderPass(renderer->commandBuffers[i],&render_pass_begin_info,VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(renderer->commandBuffers[i],VK_PIPELINE_BIND_POINT_GRAPHICS,renderer->pipelines.color);
// Vertex and index buffers are in one VkBuffer. First the vertices and then the indices
vkCmdBindVertexBuffers(renderer->commandBuffers[i],&renderer->vertexIndexBuffer.buffer,(VkDeviceSize[]) { 0 });
vkCmdBindindexBuffer(renderer->commandBuffers[i],renderer->vertexIndexBuffer.buffer,sizeof(vertices),VK_INDEX_TYPE_UINT16);
vkCmdBindDescriptorSets(renderer->commandBuffers[i],renderer->pipelineLayouts.color,renderer->sets.color + i,NULL);
vkCmdDrawIndexed(renderer->commandBuffers[i],sizeof(indices) / sizeof(indices[0]),0);
vkCmdNextSubpass(renderer->commandBuffers[i],renderer->pipelines.depth);
vkCmdBindDescriptorSets(renderer->commandBuffers[i],renderer->pipelineLayouts.depth,renderer->sets.depth + i,NULL);
vkCmdDraw(renderer->commandBuffers[i],3,0);
vkCmdEndRenderPass(renderer->commandBuffers[i]);
vkEndCommandBuffer(renderer->commandBuffers[i]);
}
}
和sType
应该都被认为是正确的。
depth_vert.spv:
pNext
depth_frag.spv:
#version 450
void main()
{
gl_Position = vec4(vec2((gl_VertexIndex << 1) & 2,gl_VertexIndex & 2) * 2.0f - 1.0f,0.0f,1.0f);
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)