0

I'm trying to create a pipeline for a compute shader.

The program crashes at the "vkCreateComputePipelines" line without anything in the validation layers.

Here's the code :

/* Pipeline layout */
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = descriptorSetLayout;
pipelineLayoutInfo.pushConstantRangeCount = 0;

if (vkCreatePipelineLayout(vk->getDevice(), &pipelineLayoutInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS)
    throw std::runtime_error("Error : pipeline layout creation");

/* Shader */
std::vector<char> computeShaderCode = readFile(computeShader);
VkShaderModule computeShaderModule = createShaderModule(computeShaderCode, vk->getDevice());

VkPipelineShaderStageCreateInfo compShaderStageInfo = {};
compShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
compShaderStageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
compShaderStageInfo.module = computeShaderModule;
compShaderStageInfo.pName = "main";

/* Pipeline */
VkComputePipelineCreateInfo pipelineInfo;
pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
pipelineInfo.stage = compShaderStageInfo;
pipelineInfo.layout = m_pipelineLayout;

if (vkCreateComputePipelines(vk->getDevice(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_computePipeline) != VK_SUCCESS)
    throw std::runtime_error("Error : compute pipeline creation");

The description set layout is created here :

VkDescriptorSetLayoutBinding inputImageLayoutBinding = {};
inputImageLayoutBinding.binding = 0;
inputImageLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
inputImageLayoutBinding.descriptorCount = 1;
inputImageLayoutBinding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
inputImageLayoutBinding.pImmutableSamplers = nullptr;

VkDescriptorSetLayoutBinding outputImageLayoutBinding = {};
outputImageLayoutBinding.binding = 1;
outputImageLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
outputImageLayoutBinding.descriptorCount = 1;
outputImageLayoutBinding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
outputImageLayoutBinding.pImmutableSamplers = nullptr;

std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayouts = { inputImageLayoutBinding, outputImageLayoutBinding };

VkDescriptorSetLayoutCreateInfo layoutInfo = {};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = static_cast<uint32_t>(descriptorSetLayouts.size());
layoutInfo.pBindings = descriptorSetLayouts.data();

VkDescriptorSetLayout descriptorSetLayout;
if (vkCreateDescriptorSetLayout(vk->getDevice(), &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS)
    throw std::runtime_error("Erreur : descriptor set layout");

The compute shader code :

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout (local_size_x = 16, local_size_y = 16) in;

layout (binding = 0, rgba8) uniform readonly image2D inputImage;
layout (binding = 1, rgba8) uniform image2D resultImage;

void main()
{   
    float blurImpact = 1.0;

    ivec2 offsets[9] = ivec2[](
        ivec2(-1, 1), // top-left
        ivec2(0, 1), // top-center
        ivec2(1, 1), // top-right
        ivec2(-1, 0),   // center-left
        ivec2(0, 0),   // center-center
        ivec2(1, 0),   // center-right
        ivec2(-1, -1), // bottom-left
        ivec2(0, -1), // bottom-center
        ivec2(0, -1)  // bottom-right    
    );
    float kernel[9] = float[](
        blurImpact, 2.0 * blurImpact, blurImpact,
        2.0 * blurImpact,  4.0, 2.0 * blurImpact,
        blurImpact, 2.0 * blurImpact, blurImpact
    );
    float sum = 12.0 * blurImpact + 4.0;

    vec3 resultColor = vec3(0.0);

    for(int i = 0; i < 9; ++i)
    {
        resultColor += imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x + offsets[i].x, gl_GlobalInvocationID.y + offsets[i].y)).rgb * (kernel[i] / sum);
    }

    imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(resultColor, 1.0));
}

I've tried to add a pipeline cache but that doesn't fix the problem. From the specification (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCreateComputePipelines.html), I think this parameter is optionnal.

Thanks !

6
  • The Chronos documentation mentions that vkCreateComputePipelines returns either success or one of three error codes that indicate an out of memory situation or an invalid shader handle. You could log the return result code or add it to your exception message. I'm not sure if the Vulkan API has a getLastError function that could give you more info, however, the documentation mentions that the Vulkan API does not capture error information about API misuse (e.g. wrong parameters). Commented Sep 17, 2019 at 17:27
  • The function makes an exception (read access violation) before returning a result Commented Sep 17, 2019 at 17:35
  • So I guess you might be passing in a bad pointer. How is m_computePipeline set up? Is it properly initialized? Commented Sep 17, 2019 at 17:44
  • The "vkCreateComputePipelines" function need to initialize "m_computePipeline". Specs say : "pPipelines is a pointer to an array of VkPipeline handles in which the resulting compute pipeline objects are returned." Commented Sep 17, 2019 at 17:48
  • vkCreateComputePipelines populates that array, but it does not initialize it. You need to initialize it beforehand and it has to have the right size. From the documentation: "pPipelines must be a valid pointer to an array of createInfoCount VkPipeline handles". Commented Sep 17, 2019 at 17:52

1 Answer 1

2

Your VkComputePipelineCreateInfo pipelineInfo; is not zeroed. Therefore pNext can be garbage. Therefore it may cause dereferencing of garbage pointer by the driver or layers.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your response ! I added pipelineInfo.pNext = nullptr; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; and it works now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.