XCamReturn VKComputePipeline::ensure_pipeline () { XCAM_FAIL_RETURN ( ERROR, XCAM_IS_VALID_VK_ID (_desc_layout) && XCAM_IS_VALID_VK_ID (_pipe_layout), XCAM_RETURN_ERROR_PARAM, "vk compute ensure pipeline failed. need ensure desc_layout and pipe_layout first"); XCAM_FAIL_RETURN ( ERROR, !_shaders.empty (), XCAM_RETURN_ERROR_PARAM, "vk compute ensure pipeline failed, shader was empty"); VkComputePipelineCreateInfo pipeline_create_info = get_compute_create_info (_shaders[0], _pipe_layout); VkPipeline pipe_id; XCAM_VK_CHECK_RETURN ( ERROR, vkCreateComputePipelines ( _dev->get_dev_id (), 0, 1, &pipeline_create_info, 0, &pipe_id), XCAM_RETURN_ERROR_VULKAN, "VK create compute pipeline failed."); XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pipe_id)); _pipe_id = pipe_id; return XCAM_RETURN_NO_ERROR; }
void Copy_To_Swapchain::create() { set_layout = Descriptor_Set_Layout() .sampler (0, VK_SHADER_STAGE_COMPUTE_BIT) .sampled_image (1, VK_SHADER_STAGE_COMPUTE_BIT) .storage_image (2, VK_SHADER_STAGE_COMPUTE_BIT) .create ("copy_to_swapchain_set_layout"); // pipeline layout { VkPushConstantRange range; range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; range.offset = 0; range.size = 8; // uint32 width + uint32 height VkPipelineLayoutCreateInfo create_info { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; create_info.setLayoutCount = 1; create_info.pSetLayouts = &set_layout; create_info.pushConstantRangeCount = 1; create_info.pPushConstantRanges = ⦥ VK_CHECK(vkCreatePipelineLayout(vk.device, &create_info, nullptr, &pipeline_layout)); } // pipeline { VkShaderModule copy_shader = vk_load_spirv("spirv/copy_to_swapchain.comp.spv"); VkPipelineShaderStageCreateInfo compute_stage { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; compute_stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; compute_stage.module = copy_shader; compute_stage.pName = "main"; VkComputePipelineCreateInfo create_info{ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; create_info.stage = compute_stage; create_info.layout = pipeline_layout; VK_CHECK(vkCreateComputePipelines(vk.device, VK_NULL_HANDLE, 1, &create_info, nullptr, &pipeline)); vkDestroyShaderModule(vk.device, copy_shader, nullptr); } // point sampler { VkSamplerCreateInfo create_info { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; VK_CHECK(vkCreateSampler(vk.device, &create_info, nullptr, &point_sampler)); vk_set_debug_name(point_sampler, "point_sampler"); } }
//============================================================================== void PipelineImpl::initCompute(const PipelineInitInfo& init) { VkComputePipelineCreateInfo ci; ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; ci.pNext = nullptr; ci.layout = getGrManagerImpl().m_globalPipelineLayout; ci.basePipelineHandle = VK_NULL_HANDLE; VkPipelineShaderStageCreateInfo& stage = ci.stage; stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stage.pNext = nullptr; stage.flags = 0; stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; stage.module = init.m_shaders[ShaderType::COMPUTE]->getImplementation().m_handle; stage.pName = "main"; stage.pSpecializationInfo = nullptr; ANKI_VK_CHECK(vkCreateComputePipelines( getDevice(), nullptr, 1, &ci, nullptr, &m_handle)); }
void prepareCompute() { // Create compute pipeline // Compute pipelines are created separate from graphics pipelines // even if they use the same queue std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = { // Binding 0 : Particle position storage buffer vkTools::initializers::descriptorSetLayoutBinding( VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 0), // Binding 1 : Uniform buffer vkTools::initializers::descriptorSetLayoutBinding( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 1), }; VkDescriptorSetLayoutCreateInfo descriptorLayout = vkTools::initializers::descriptorSetLayoutCreateInfo( setLayoutBindings.data(), setLayoutBindings.size()); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &computeDescriptorSetLayout)); VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vkTools::initializers::pipelineLayoutCreateInfo( &computeDescriptorSetLayout, 1); VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &computePipelineLayout)); VkDescriptorSetAllocateInfo allocInfo = vkTools::initializers::descriptorSetAllocateInfo( descriptorPool, &computeDescriptorSetLayout, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &computeDescriptorSet)); std::vector<VkWriteDescriptorSet> computeWriteDescriptorSets = { // Binding 0 : Particle position storage buffer vkTools::initializers::writeDescriptorSet( computeDescriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &computeStorageBuffer.descriptor), // Binding 1 : Uniform buffer vkTools::initializers::writeDescriptorSet( computeDescriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, &uniformData.computeShader.ubo.descriptor) }; vkUpdateDescriptorSets(device, computeWriteDescriptorSets.size(), computeWriteDescriptorSets.data(), 0, NULL); // Create pipeline VkComputePipelineCreateInfo computePipelineCreateInfo = vkTools::initializers::computePipelineCreateInfo( computePipelineLayout, 0); computePipelineCreateInfo.stage = loadShader(getAssetPath() + "shaders/computeparticles/particle.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT); VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipelines.compute)); }
void VulkanComputePipelineState::initialize() { ComputePipelineState::initialize(); // This might happen fairly often if shaders with unsupported languages are loaded, in which case the pipeline // will never get used, and its fine not to initialize it. if (!mProgram->isCompiled()) return; VulkanGpuProgram* vkProgram = static_cast<VulkanGpuProgram*>(mProgram.get()); VkPipelineShaderStageCreateInfo stageCI; stageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stageCI.pNext = nullptr; stageCI.flags = 0; stageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; stageCI.module = VK_NULL_HANDLE; stageCI.pName = vkProgram->getProperties().getEntryPoint().c_str(); stageCI.pSpecializationInfo = nullptr; VkComputePipelineCreateInfo pipelineCI; pipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; pipelineCI.pNext = nullptr; pipelineCI.flags = 0; pipelineCI.stage = stageCI; pipelineCI.basePipelineHandle = VK_NULL_HANDLE; pipelineCI.basePipelineIndex = -1; VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance()); VulkanDevice* devices[BS_MAX_DEVICES]; VulkanUtility::getDevices(rapi, mDeviceMask, devices); for (UINT32 i = 0; i < BS_MAX_DEVICES; i++) { if (devices[i] == nullptr) continue; mPerDeviceData[i].device = devices[i]; VulkanDescriptorManager& descManager = devices[i]->getDescriptorManager(); VulkanResourceManager& rescManager = devices[i]->getResourceManager(); VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo); UINT32 numLayouts = vkParamInfo.getNumSets(); VulkanDescriptorLayout** layouts = (VulkanDescriptorLayout**)bs_stack_alloc(sizeof(VulkanDescriptorLayout*) * numLayouts); for (UINT32 j = 0; j < numLayouts; j++) layouts[j] = vkParamInfo.getLayout(i, j); VulkanShaderModule* module = vkProgram->getShaderModule(i); if (module != nullptr) pipelineCI.stage.module = module->getHandle(); else pipelineCI.stage.module = VK_NULL_HANDLE; pipelineCI.layout = descManager.getPipelineLayout(layouts, numLayouts); VkPipeline pipeline; VkResult result = vkCreateComputePipelines(devices[i]->getLogical(), VK_NULL_HANDLE, 1, &pipelineCI, gVulkanAllocator, &pipeline); assert(result == VK_SUCCESS); mPerDeviceData[i].pipeline = rescManager.create<VulkanPipeline>(pipeline); mPerDeviceData[i].pipelineLayout = pipelineCI.layout; bs_stack_free(layouts); } BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineState); }
void BaseImage::ValidateContent(RandomNumberGenerator& rand) { /* dstBuf has following layout: For each of texels to be sampled, [0..valueCount): struct { in uint32_t pixelX; in uint32_t pixelY; out uint32_t pixelColor; } */ const uint32_t valueCount = 128; VkBufferCreateInfo dstBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; dstBufCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; dstBufCreateInfo.size = valueCount * sizeof(uint32_t) * 3; VmaAllocationCreateInfo dstBufAllocCreateInfo = {}; dstBufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; dstBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; VkBuffer dstBuf = nullptr; VmaAllocation dstBufAlloc = nullptr; VmaAllocationInfo dstBufAllocInfo = {}; TEST( vmaCreateBuffer(g_hAllocator, &dstBufCreateInfo, &dstBufAllocCreateInfo, &dstBuf, &dstBufAlloc, &dstBufAllocInfo) == VK_SUCCESS ); // Fill dstBuf input data. { uint32_t* dstBufContent = (uint32_t*)dstBufAllocInfo.pMappedData; for(uint32_t i = 0; i < valueCount; ++i) { const uint32_t x = rand.Generate() % m_CreateInfo.extent.width; const uint32_t y = rand.Generate() % m_CreateInfo.extent.height; dstBufContent[i * 3 ] = x; dstBufContent[i * 3 + 1] = y; dstBufContent[i * 3 + 2] = 0; } } VkSamplerCreateInfo samplerCreateInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; samplerCreateInfo.magFilter = VK_FILTER_NEAREST; samplerCreateInfo.minFilter = VK_FILTER_NEAREST; samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerCreateInfo.unnormalizedCoordinates = VK_TRUE; VkSampler sampler = nullptr; TEST( vkCreateSampler( g_hDevice, &samplerCreateInfo, nullptr, &sampler) == VK_SUCCESS ); VkDescriptorSetLayoutBinding bindings[2] = {}; bindings[0].binding = 0; bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; bindings[0].descriptorCount = 1; bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; bindings[0].pImmutableSamplers = &sampler; bindings[1].binding = 1; bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; bindings[1].descriptorCount = 1; bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; VkDescriptorSetLayoutCreateInfo descSetLayoutCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; descSetLayoutCreateInfo.bindingCount = 2; descSetLayoutCreateInfo.pBindings = bindings; VkDescriptorSetLayout descSetLayout = nullptr; TEST( vkCreateDescriptorSetLayout(g_hDevice, &descSetLayoutCreateInfo, nullptr, &descSetLayout) == VK_SUCCESS ); VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; pipelineLayoutCreateInfo.setLayoutCount = 1; pipelineLayoutCreateInfo.pSetLayouts = &descSetLayout; VkPipelineLayout pipelineLayout = nullptr; TEST( vkCreatePipelineLayout(g_hDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout) == VK_SUCCESS ); std::vector<char> shaderCode; LoadShader(shaderCode, "SparseBindingTest.comp.spv"); VkShaderModuleCreateInfo shaderModuleCreateInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO }; shaderModuleCreateInfo.codeSize = shaderCode.size(); shaderModuleCreateInfo.pCode = (const uint32_t*)shaderCode.data(); VkShaderModule shaderModule = nullptr; TEST( vkCreateShaderModule(g_hDevice, &shaderModuleCreateInfo, nullptr, &shaderModule) == VK_SUCCESS ); VkComputePipelineCreateInfo pipelineCreateInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; pipelineCreateInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; pipelineCreateInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; pipelineCreateInfo.stage.module = shaderModule; pipelineCreateInfo.stage.pName = "main"; pipelineCreateInfo.layout = pipelineLayout; VkPipeline pipeline = nullptr; TEST( vkCreateComputePipelines(g_hDevice, nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline) == VK_SUCCESS ); VkDescriptorPoolSize poolSizes[2] = {}; poolSizes[0].type = bindings[0].descriptorType; poolSizes[0].descriptorCount = bindings[0].descriptorCount; poolSizes[1].type = bindings[1].descriptorType; poolSizes[1].descriptorCount = bindings[1].descriptorCount; VkDescriptorPoolCreateInfo descPoolCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; descPoolCreateInfo.maxSets = 1; descPoolCreateInfo.poolSizeCount = 2; descPoolCreateInfo.pPoolSizes = poolSizes; VkDescriptorPool descPool = nullptr; TEST( vkCreateDescriptorPool(g_hDevice, &descPoolCreateInfo, nullptr, &descPool) == VK_SUCCESS ); VkDescriptorSetAllocateInfo descSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; descSetAllocInfo.descriptorPool = descPool; descSetAllocInfo.descriptorSetCount = 1; descSetAllocInfo.pSetLayouts = &descSetLayout; VkDescriptorSet descSet = nullptr; TEST( vkAllocateDescriptorSets(g_hDevice, &descSetAllocInfo, &descSet) == VK_SUCCESS ); VkImageViewCreateInfo imageViewCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; imageViewCreateInfo.image = m_Image; imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewCreateInfo.format = m_CreateInfo.format; imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageViewCreateInfo.subresourceRange.layerCount = 1; imageViewCreateInfo.subresourceRange.levelCount = 1; VkImageView imageView = nullptr; TEST( vkCreateImageView(g_hDevice, &imageViewCreateInfo, nullptr, &imageView) == VK_SUCCESS ); VkDescriptorImageInfo descImageInfo = {}; descImageInfo.imageView = imageView; descImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkDescriptorBufferInfo descBufferInfo = {}; descBufferInfo.buffer = dstBuf; descBufferInfo.offset = 0; descBufferInfo.range = VK_WHOLE_SIZE; VkWriteDescriptorSet descWrites[2] = {}; descWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descWrites[0].dstSet = descSet; descWrites[0].dstBinding = bindings[0].binding; descWrites[0].dstArrayElement = 0; descWrites[0].descriptorCount = 1; descWrites[0].descriptorType = bindings[0].descriptorType; descWrites[0].pImageInfo = &descImageInfo; descWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descWrites[1].dstSet = descSet; descWrites[1].dstBinding = bindings[1].binding; descWrites[1].dstArrayElement = 0; descWrites[1].descriptorCount = 1; descWrites[1].descriptorType = bindings[1].descriptorType; descWrites[1].pBufferInfo = &descBufferInfo; vkUpdateDescriptorSets(g_hDevice, 2, descWrites, 0, nullptr); BeginSingleTimeCommands(); vkCmdBindPipeline(g_hTemporaryCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); vkCmdBindDescriptorSets(g_hTemporaryCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, &descSet, 0, nullptr); vkCmdDispatch(g_hTemporaryCommandBuffer, valueCount, 1, 1); EndSingleTimeCommands(); // Validate dstBuf output data. { const uint32_t* dstBufContent = (const uint32_t*)dstBufAllocInfo.pMappedData; for(uint32_t i = 0; i < valueCount; ++i) { const uint32_t x = dstBufContent[i * 3 ]; const uint32_t y = dstBufContent[i * 3 + 1]; const uint32_t color = dstBufContent[i * 3 + 2]; const uint8_t a = (uint8_t)(color >> 24); const uint8_t b = (uint8_t)(color >> 16); const uint8_t g = (uint8_t)(color >> 8); const uint8_t r = (uint8_t)color; TEST(r == (uint8_t)x && g == (uint8_t)y && b == 13 && a == 25); } } vkDestroyImageView(g_hDevice, imageView, nullptr); vkDestroyDescriptorPool(g_hDevice, descPool, nullptr); vmaDestroyBuffer(g_hAllocator, dstBuf, dstBufAlloc); vkDestroyPipeline(g_hDevice, pipeline, nullptr); vkDestroyShaderModule(g_hDevice, shaderModule, nullptr); vkDestroyPipelineLayout(g_hDevice, pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(g_hDevice, descSetLayout, nullptr); vkDestroySampler(g_hDevice, sampler, nullptr); }