Ejemplo n.º 1
0
VkCommandPool
VKDevice::create_cmd_pool (VkFlags queue_flag)
{
    XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id));
    XCAM_ASSERT (_instance.ptr ());
    VkCommandPool pool_id = VK_NULL_HANDLE;

    VkCommandPoolCreateInfo create_pool_info = {};
    create_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    create_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;

    if (queue_flag == VK_QUEUE_COMPUTE_BIT)
        create_pool_info.queueFamilyIndex = _instance->get_compute_queue_family_idx ();
    else if (queue_flag == VK_QUEUE_GRAPHICS_BIT)
        create_pool_info.queueFamilyIndex = _instance->get_graphics_queue_family_idx ();
    else {
        XCAM_LOG_WARNING ("VKDevice create command pool failed, queue_flag(%d) not supported.", queue_flag);
        return VK_NULL_HANDLE;
    }

    XCAM_VK_CHECK_RETURN (
        ERROR, vkCreateCommandPool (_dev_id, &create_pool_info,  _allocator.ptr (), &pool_id),
        VK_NULL_HANDLE, "VKDevice create command pool failed.");
    return pool_id;
}
Ejemplo n.º 2
0
void VulkanBase::createCommandPool() {
	VkCommandPoolCreateInfo cmdPoolInfo = {};
	cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	cmdPoolInfo.queueFamilyIndex = swapChain.queueNodeIndex;
	cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
	vkTools::checkResult(vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &cmdPool));
}
Ejemplo n.º 3
0
void VulkanExampleBase::createCommandPool()
{
	VkCommandPoolCreateInfo cmdPoolInfo = {};
	cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	cmdPoolInfo.queueFamilyIndex = swapChain.queueNodeIndex;
	cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
	VkResult vkRes = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &cmdPool);
	assert(!vkRes);
}
Ejemplo n.º 4
0
VkResult create_command_pool(VkDevice device, uint32_t queue_family_idx, VkCommandPool* out_command_pool)
{
    VkCommandPoolCreateInfo command_pool_info = {};
    command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    command_pool_info.pNext = nullptr;
    command_pool_info.queueFamilyIndex = queue_family_idx;
    command_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
    return vkCreateCommandPool(device, &command_pool_info, nullptr, out_command_pool);
}
Ejemplo n.º 5
0
		/** 
		* Create a command pool for allocation command buffers from
		* 
		* @param queueFamilyIndex Family index of the queue to create the command pool for
		* @param createFlags (Optional) Command pool creation flags (Defaults to VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
		*
		* @note Command buffers allocated from the created pool can only be submitted to a queue with the same family index
		*
		* @return A handle to the created command buffer
		*/
		VkCommandPool createCommandPool(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
		{
			VkCommandPoolCreateInfo cmdPoolInfo = {};
			cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
			cmdPoolInfo.queueFamilyIndex = queueFamilyIndex;
			cmdPoolInfo.flags = createFlags;
			VkCommandPool cmdPool;
			VK_CHECK_RESULT(vkCreateCommandPool(logicalDevice, &cmdPoolInfo, nullptr, &cmdPool));
			return cmdPool;
		}
Ejemplo n.º 6
0
CommandPool::CommandPool(Device &device, uint32_t familyIndex) :
    mDevice(device) {
    VkCommandPoolCreateInfo info = {};

    info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
    info.pNext = nullptr;
    info.queueFamilyIndex = familyIndex;

    vulkanCheckError(vkCreateCommandPool(mDevice, &info, nullptr, &mCommandPool));
}
Ejemplo n.º 7
0
void Shadow::SetupCmdBufferPool()
{
	// COMMAND BUFFER (POOL)

	auto cmdPoolCreateInfo = vkstruct<VkCommandPoolCreateInfo>();
	cmdPoolCreateInfo.flags = 0;
	cmdPoolCreateInfo.queueFamilyIndex = 0u;

	gVkLastRes = vkCreateCommandPool(gDevice.VkHandle(), &cmdPoolCreateInfo, nullptr, &mCmdPool);
	VKFN_LAST_RES_SUCCESS_OR_QUIT(vkCreateCommandPool);
}
Ejemplo n.º 8
0
void VkApp::createCommandPool(){
	QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);

	VkCommandPoolCreateInfo poolInfo = {};
	poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;

	if( vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS ){
		throw std::runtime_error("failed to create graphics command pool!");
	}
}
Ejemplo n.º 9
0
			bool VkContext::CreateCommandPool() {
				// Create present command pool
				VkCommandPoolCreateInfo cmdPoolCreateInfo = {};
				cmdPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
				cmdPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
				cmdPoolCreateInfo.queueFamilyIndex = queueIndex;

				CheckVkResult(vkCreateCommandPool(dev, &cmdPoolCreateInfo, nullptr, &cmdPool));

				return true;
			}
  bool Tutorial03::CreateCommandPool( uint32_t queue_family_index, VkCommandPool *pool ) {
    VkCommandPoolCreateInfo cmd_pool_create_info = {
      VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,     // VkStructureType                sType
      nullptr,                                        // const void                    *pNext
      0,                                              // VkCommandPoolCreateFlags       flags
      queue_family_index                              // uint32_t                       queueFamilyIndex
    };

    if( vkCreateCommandPool( GetDevice(), &cmd_pool_create_info, nullptr, pool ) != VK_SUCCESS ) {
      return false;
    }
    return true;
  }
void VulkanWrapper::VWGraphicInstance::CreateCommandPool(VWGraphicAdapter* _adapter)
{
	QueueFamilyIndices queueFamilyIndices = FindQueueFamilies(m_PhysicalDevice, m_Surface);

	VkCommandPoolCreateInfo poolInfo = {};
	poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;

	if (vkCreateCommandPool(m_VulkanDevice, &poolInfo, nullptr, &m_CommandPool) != VK_SUCCESS)
	{
		throw std::runtime_error("failed to create command pool!");
	}
}
Ejemplo n.º 12
0
Error CommandBufferFactory::init(GenericMemoryPoolAllocator<U8> alloc, VkDevice dev, uint32_t queueFamily)
{
	m_alloc = alloc;

	VkCommandPoolCreateInfo ci = {};
	ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
	ci.queueFamilyIndex = queueFamily;

	ANKI_VK_CHECK(vkCreateCommandPool(dev, &ci, nullptr, &m_pool));

	m_dev = dev;
	return ErrorCode::NONE;
}
int sample_main() {
    VkResult U_ASSERT_ONLY res;
    struct sample_info info = {};
    char sample_title[] = "Command Buffer Sample";

    init_global_layer_properties(info);
    init_instance_extension_names(info);
    init_device_extension_names(info);
    init_instance(info, sample_title);
    init_enumerate_device(info);
    init_window_size(info, 500, 500);
    init_connection(info);
    init_window(info);
    init_swapchain_extension(info);
    init_device(info);

    /* VULKAN_KEY_START */

    /* Create a command pool to allocate our command buffer from */
    VkCommandPoolCreateInfo cmd_pool_info = {};
    cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    cmd_pool_info.pNext = NULL;
    cmd_pool_info.queueFamilyIndex = info.graphics_queue_family_index;
    cmd_pool_info.flags = 0;

    res =
        vkCreateCommandPool(info.device, &cmd_pool_info, NULL, &info.cmd_pool);
    assert(res == VK_SUCCESS);

    /* Create the command buffer from the command pool */
    VkCommandBufferAllocateInfo cmd = {};
    cmd.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    cmd.pNext = NULL;
    cmd.commandPool = info.cmd_pool;
    cmd.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    cmd.commandBufferCount = 1;

    res = vkAllocateCommandBuffers(info.device, &cmd, &info.cmd);
    assert(res == VK_SUCCESS);

    /* VULKAN_KEY_END */

    VkCommandBuffer cmd_bufs[1] = {info.cmd};
    vkFreeCommandBuffers(info.device, info.cmd_pool, 1, cmd_bufs);
    vkDestroyCommandPool(info.device, info.cmd_pool, NULL);
    destroy_window(info);
    destroy_device(info);
    destroy_instance(info);
    return 0;
}
Ejemplo n.º 14
0
VulkanRenderManager::VulkanRenderManager(VulkanContext *vulkan) : vulkan_(vulkan), queueRunner_(vulkan) {
	VkSemaphoreCreateInfo semaphoreCreateInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
	semaphoreCreateInfo.flags = 0;
	VkResult res = vkCreateSemaphore(vulkan_->GetDevice(), &semaphoreCreateInfo, nullptr, &acquireSemaphore_);
	assert(res == VK_SUCCESS);
	res = vkCreateSemaphore(vulkan_->GetDevice(), &semaphoreCreateInfo, nullptr, &renderingCompleteSemaphore_);
	assert(res == VK_SUCCESS);

	for (int i = 0; i < vulkan_->GetInflightFrames(); i++) {
		VkCommandPoolCreateInfo cmd_pool_info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
		cmd_pool_info.queueFamilyIndex = vulkan_->GetGraphicsQueueFamilyIndex();
		cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
		VkResult res = vkCreateCommandPool(vulkan_->GetDevice(), &cmd_pool_info, nullptr, &frameData_[i].cmdPoolInit);
		assert(res == VK_SUCCESS);
		res = vkCreateCommandPool(vulkan_->GetDevice(), &cmd_pool_info, nullptr, &frameData_[i].cmdPoolMain);
		assert(res == VK_SUCCESS);

		VkCommandBufferAllocateInfo cmd_alloc = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
		cmd_alloc.commandPool = frameData_[i].cmdPoolInit;
		cmd_alloc.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
		cmd_alloc.commandBufferCount = 1;

		res = vkAllocateCommandBuffers(vulkan_->GetDevice(), &cmd_alloc, &frameData_[i].initCmd);
		assert(res == VK_SUCCESS);
		cmd_alloc.commandPool = frameData_[i].cmdPoolMain;
		res = vkAllocateCommandBuffers(vulkan_->GetDevice(), &cmd_alloc, &frameData_[i].mainCmd);
		assert(res == VK_SUCCESS);
		frameData_[i].fence = vulkan_->CreateFence(true);  // So it can be instantly waited on
	}

	queueRunner_.CreateDeviceObjects();

	// Temporary AMD hack for issue #10097
	if (vulkan_->GetPhysicalDeviceProperties().vendorID == VULKAN_VENDOR_AMD) {
		useThread_ = false;
	}
}
Ejemplo n.º 15
0
void CommandAllocator::Initialize()
{
	VkCommandPoolCreateInfo createInfo = {};
	createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	createInfo.pNext = nullptr;
	createInfo.queueFamilyIndex = m_FamilyIndex;
	createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;

	if (m_Transient)
	{
		createInfo.flags |= VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
	}

	K3D_VK_VERIFY(vkCreateCommandPool(GetRawDevice(), &createInfo, nullptr, &m_Pool));
}
Ejemplo n.º 16
0
	VulkanResult<VkCommandPool> Device::CreateCommandPool( VkCommandPoolCreateFlags flags, uint32 queueFamilyIndex ) {
		VkCommandPoolCreateInfo	createInfo;
		VkCommandPool			pool( VK_NULL_HANDLE );

		createInfo.sType			= VkStructureType::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
		createInfo.pNext			= nullptr;
		createInfo.flags			= flags;
		createInfo.queueFamilyIndex	= queueFamilyIndex;

		const auto	result( vkCreateCommandPool( _device.Get(), &createInfo, _allocator, &pool ) );
		if( result < VkResult::VK_SUCCESS ) {
			return { result };
		}

		return Vulkan::UniquePointer<VkCommandPool>( pool, { _device.Get(), _allocator } );
	}
Ejemplo n.º 17
0
void CommandBuffer::sharedConstructor()
{
    VkCommandPoolCreateInfo commandPoolCreateInfo = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
    commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
    commandPoolCreateInfo.queueFamilyIndex = this->computeQueueFamily;
    if (VK_SUCCESS != vkCreateCommandPool(this->device, &commandPoolCreateInfo, nullptr, &commandPool)) {
        throw ERROR_COMMAND;
    }

    VkCommandBufferAllocateInfo commandBufferAllocateInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
    commandBufferAllocateInfo.commandBufferCount = 1;
    commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    commandBufferAllocateInfo.commandPool = commandPool;
    if (VK_SUCCESS != vkAllocateCommandBuffers(this->device, &commandBufferAllocateInfo, &commandBuffer)) {
        throw ERROR_COMMAND;
    }
}
Ejemplo n.º 18
0
bool CommandBufferManager::CreateCommandPool()
{
  VkCommandPoolCreateInfo info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr,
                                  VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
                                      VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
                                  g_vulkan_context->GetGraphicsQueueFamilyIndex()};

  VkResult res =
      vkCreateCommandPool(g_vulkan_context->GetDevice(), &info, nullptr, &m_command_pool);
  if (res != VK_SUCCESS)
  {
    LOG_VULKAN_ERROR(res, "vkCreateCommandPool failed: ");
    return false;
  }

  return true;
}
bool VulkanWrapper::VWFrameCommandBufferAllocator::Initialize(VWGraphicAdapter* _adapter, VWGraphicInstance* _graphicInstance, uint32_t _totalThreads, uint32_t _bufferingMagnitude)
{
	// Set the total frame magnitude
	m_TotalFrameMagnitude = _bufferingMagnitude;

	// Query the family indices
	VWGraphicInstance::QueueFamilyIndices queueFamilyIndices = _graphicInstance->FindQueueFamilies(_graphicInstance->GetPhysicalDevice(), _graphicInstance->GetSurface());

	// For each thread
	for (int i = 0; i < _totalThreads; i++)
	{
		// The per thread data
		CommandDataPerThread perThreadData = {};

		// Buffer magnitude
		for (int j = 0; j < _bufferingMagnitude; j++)
		{
			CommandPoolAux commandPoolAux = {};
			commandPoolAux.sTargetCommandBuffer = 0;

			VkCommandPoolCreateInfo poolInfo = {};
			poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
			poolInfo.flags = 0;
			poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;

			if (vkCreateCommandPool(_graphicInstance->GetDevice(), &poolInfo, nullptr, &commandPoolAux.sCommandPool) != VK_SUCCESS)
			{
				throw std::runtime_error("failed to create command pool!");
			}
			
			perThreadData.sCommandPoolAux.push_back(commandPoolAux);
		}

		m_ThreadCommandData.push_back(perThreadData);
	}

	// Create all command pools
	// CreateCommandPool(_adapter, _graphicInstance, 0);
	// CreateCommandPool(_adapter, _graphicInstance, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
	// CreateCommandPool(_adapter, _graphicInstance, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT);
	// CreateCommandPool(_adapter, _graphicInstance, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT);

	return true;
}
Ejemplo n.º 20
0
void VkeDrawCall::initCommandPool(){

	VulkanDC *dc = VulkanDC::Get();
	VulkanDC::Device *device = dc->getDefaultDevice();

	VkCommandPoolCreateInfo cmdPoolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
	cmdPoolInfo.queueFamilyIndex = 0;
	cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;

	VKA_CHECK_ERROR(vkCreateCommandPool(device->getVKDevice(), &cmdPoolInfo, NULL, &m_command_pool), "Could not create command pool.\n");

	VkCommandBufferAllocateInfo cmdBufInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
	cmdBufInfo.commandBufferCount = 2;
	cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
	cmdBufInfo.commandPool = m_command_pool;

	VKA_CHECK_ERROR(vkAllocateCommandBuffers(device->getVKDevice(), &cmdBufInfo, m_draw_command), "Could not allocate secondary command buffers.\n");


}
Ejemplo n.º 21
0
ICommandPoolSP VKTS_APIENTRY commandPoolCreate(const VkDevice device, const VkCommandPoolCreateFlags flags, const uint32_t queueFamilyIndex)
{
    if (!device)
    {
        return ICommandPoolSP();
    }

    VkResult result;

    VkCommandPoolCreateInfo commandPoolCreateInfo;

    memset(&commandPoolCreateInfo, 0, sizeof(VkCommandPoolCreateInfo));

    commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;

    commandPoolCreateInfo.flags = flags;
    commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;

    VkCommandPool commandPool;

    result = vkCreateCommandPool(device, &commandPoolCreateInfo, nullptr, &commandPool);

    if (result != VK_SUCCESS)
    {
        logPrint(VKTS_LOG_ERROR, "CommandPool: Could not create command pool.");

        return ICommandPoolSP();
    }

    auto newInstance = new CommandPool(device, queueFamilyIndex, flags, commandPool);

    if (!newInstance)
    {
        vkDestroyCommandPool(device, commandPool, nullptr);

        return ICommandPoolSP();
    }

    return ICommandPoolSP(newInstance);
}
Ejemplo n.º 22
0
bool initCommandBuffers()
{
	std::cout << "creating command buffers...";
	VkCommandPoolCreateInfo cmdPoolInfo = {};
	cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	cmdPoolInfo.pNext = nullptr;
	cmdPoolInfo.queueFamilyIndex = gQueueFamilyIndex;
	cmdPoolInfo.flags = 0;

	VkResult res = vkCreateCommandPool( gDevice, &cmdPoolInfo, nullptr, &gCmdPool );
	if( res != VK_SUCCESS )
	{
		std::cout << "error creating command pool\n";
		return false;
	}
	else
	{
		VkCommandBufferAllocateInfo cmdInfo = {};
		cmdInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
		cmdInfo.pNext = nullptr;
		cmdInfo.commandPool = gCmdPool;
		cmdInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
		cmdInfo.commandBufferCount = 1;

		res = vkAllocateCommandBuffers( gDevice, &cmdInfo, &gCmd );
		if( res != VK_SUCCESS )
		{
			std::cout << "error allocating command buffer\n";
			vkDestroyCommandPool( gDevice, gCmdPool, nullptr );
			return false;
		}
	}

	std::cout << "command buffer created\n";
	return true;
}
Ejemplo n.º 23
0
gboolean
gst_vulkan_device_open (GstVulkanDevice * device, GError ** error)
{
  const char *extension_names[64];
  uint32_t enabled_extension_count = 0;
  uint32_t device_extension_count = 0;
  VkExtensionProperties *device_extensions = NULL;
  uint32_t enabled_layer_count = 0;
  gchar **enabled_layers;
  uint32_t device_layer_count = 0;
  VkLayerProperties *device_layers;
  gboolean have_swapchain_ext;
  VkPhysicalDevice gpu;
  VkResult err;
  guint i;

  g_return_val_if_fail (GST_IS_VULKAN_DEVICE (device), FALSE);

  GST_OBJECT_LOCK (device);

  if (device->priv->opened) {
    GST_OBJECT_UNLOCK (device);
    return TRUE;
  }

  if (!_physical_device_info (device, error))
    goto error;

  gpu = gst_vulkan_device_get_physical_device (device);

  /* Look for validation layers */
  err = vkEnumerateDeviceLayerProperties (gpu, &device_layer_count, NULL);
  if (gst_vulkan_error_to_g_error (err, error,
          "vkEnumerateDeviceLayerProperties") < 0)
    goto error;

  device_layers = g_new0 (VkLayerProperties, device_layer_count);
  err =
      vkEnumerateDeviceLayerProperties (gpu, &device_layer_count,
      device_layers);
  if (gst_vulkan_error_to_g_error (err, error,
          "vkEnumerateDeviceLayerProperties") < 0) {
    g_free (device_layers);
    goto error;
  }

  _check_for_all_layers (G_N_ELEMENTS (device_validation_layers),
      device_validation_layers, device_layer_count, device_layers,
      &enabled_layer_count, &enabled_layers);
  g_free (device_layers);
  device_layers = NULL;

  err =
      vkEnumerateDeviceExtensionProperties (gpu, NULL,
      &device_extension_count, NULL);
  if (gst_vulkan_error_to_g_error (err, error,
          "vkEnumerateDeviceExtensionProperties") < 0) {
    g_strfreev (enabled_layers);
    goto error;
  }
  GST_DEBUG_OBJECT (device, "Found %u extensions", device_extension_count);

  have_swapchain_ext = 0;
  enabled_extension_count = 0;
  memset (extension_names, 0, sizeof (extension_names));
  device_extensions = g_new0 (VkExtensionProperties, device_extension_count);
  err = vkEnumerateDeviceExtensionProperties (gpu, NULL,
      &device_extension_count, device_extensions);
  if (gst_vulkan_error_to_g_error (err, error,
          "vkEnumerateDeviceExtensionProperties") < 0) {
    g_strfreev (enabled_layers);
    g_free (device_extensions);
    goto error;
  }

  for (uint32_t i = 0; i < device_extension_count; i++) {
    GST_TRACE_OBJECT (device, "checking device extension %s",
        device_extensions[i].extensionName);
    if (!strcmp (VK_KHR_SWAPCHAIN_EXTENSION_NAME,
            device_extensions[i].extensionName)) {
      have_swapchain_ext = TRUE;
      extension_names[enabled_extension_count++] =
          (gchar *) VK_KHR_SWAPCHAIN_EXTENSION_NAME;
    }
    g_assert (enabled_extension_count < 64);
  }
  if (!have_swapchain_ext) {
    g_set_error_literal (error, GST_VULKAN_ERROR,
        VK_ERROR_EXTENSION_NOT_PRESENT,
        "Failed to find required extension, \"" VK_KHR_SWAPCHAIN_EXTENSION_NAME
        "\"");
    g_strfreev (enabled_layers);
    goto error;
  }
  g_free (device_extensions);

  vkGetPhysicalDeviceProperties (gpu, &device->gpu_props);
  vkGetPhysicalDeviceMemoryProperties (gpu, &device->memory_properties);
  vkGetPhysicalDeviceFeatures (gpu, &device->gpu_features);

  vkGetPhysicalDeviceQueueFamilyProperties (gpu, &device->n_queue_families,
      NULL);
  g_assert (device->n_queue_families >= 1);

  device->queue_family_props =
      g_new0 (VkQueueFamilyProperties, device->n_queue_families);
  vkGetPhysicalDeviceQueueFamilyProperties (gpu, &device->n_queue_families,
      device->queue_family_props);

  /* FIXME: allow overriding/selecting */
  for (i = 0; i < device->n_queue_families; i++) {
    if (device->queue_family_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
      break;
  }
  if (i >= device->n_queue_families) {
    g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED,
        "Failed to find a compatible queue family");
    g_strfreev (enabled_layers);
    goto error;
  }
  device->queue_family_id = i;
  device->n_queues = 1;

  {
    VkDeviceQueueCreateInfo queue_info = { 0, };
    VkDeviceCreateInfo device_info = { 0, };
    gfloat queue_priority = 0.5;

    queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    queue_info.pNext = NULL;
    queue_info.queueFamilyIndex = device->queue_family_id;
    queue_info.queueCount = device->n_queues;
    queue_info.pQueuePriorities = &queue_priority;

    device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    device_info.pNext = NULL;
    device_info.queueCreateInfoCount = 1;
    device_info.pQueueCreateInfos = &queue_info;
    device_info.enabledLayerCount = enabled_layer_count;
    device_info.ppEnabledLayerNames = (const char *const *) enabled_layers;
    device_info.enabledExtensionCount = enabled_extension_count;
    device_info.ppEnabledExtensionNames = (const char *const *) extension_names;
    device_info.pEnabledFeatures = NULL;

    err = vkCreateDevice (gpu, &device_info, NULL, &device->device);
    if (gst_vulkan_error_to_g_error (err, error, "vkCreateDevice") < 0) {
      g_strfreev (enabled_layers);
      goto error;
    }
  }
  g_strfreev (enabled_layers);

  {
    VkCommandPoolCreateInfo cmd_pool_info = { 0, };

    cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    cmd_pool_info.pNext = NULL;
    cmd_pool_info.queueFamilyIndex = device->queue_family_id;
    cmd_pool_info.flags = 0;

    err =
        vkCreateCommandPool (device->device, &cmd_pool_info, NULL,
        &device->cmd_pool);
    if (gst_vulkan_error_to_g_error (err, error, "vkCreateCommandPool") < 0)
      goto error;
  }

  GST_OBJECT_UNLOCK (device);
  return TRUE;

error:
  {
    GST_OBJECT_UNLOCK (device);
    return FALSE;
  }
}
Ejemplo n.º 24
0
void VulkanBase::createInstance() {
    // Application info init
    const VkApplicationInfo applicationInfo = {
        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
        .pNext = NULL,
        .pApplicationName = name.c_str(),
        .applicationVersion = 1,
        .pEngineName = engineName.c_str(),
        .engineVersion = 1,
        .apiVersion = VK_API_VERSION,       //FIXME  Nvidia driver not updated to latest Vulkan Version
    };


    VkInstanceCreateInfo instanceCreateInfo = {
        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
        .pNext = NULL,
        .flags = VK_FLAGS_NONE,
        .pApplicationInfo = &applicationInfo,
        .enabledLayerCount = 0,
        .ppEnabledLayerNames = NULL,
        .enabledExtensionCount = 0,
        .ppEnabledExtensionNames = NULL,
    };

    std::vector<const char*> enabledExtensions = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME};
    //Check if extensions are present
    vkUtils::checkGlobalExtensionPresent(VK_KHR_SURFACE_EXTENSION_NAME);
    vkUtils::checkGlobalExtensionPresent(VK_KHR_XCB_SURFACE_EXTENSION_NAME);

#ifdef _DEBUG
    if (enableValidation) {
        //Extensions management
        enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
        vkUtils::checkGlobalExtensionPresent(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);

        // Layer management
        instanceCreateInfo.enabledLayerCount = vkDebug::validationLayerCount;
        instanceCreateInfo.ppEnabledLayerNames = vkDebug::validationLayerNames;
        // Check standard debug layers are present
        for(uint32_t i = 0; i < instanceCreateInfo.enabledLayerCount; i++) {
            vkUtils::checkGlobalLayerPresent(vkDebug::validationLayerNames[i]);
        }
    }
#endif // DEBUG

    instanceCreateInfo.ppEnabledExtensionNames = enabledExtensions.data();
    instanceCreateInfo.enabledExtensionCount = (uint32_t) enabledExtensions.size();

    CHECK_RESULT(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
}




void VulkanBase::selectVkPhysicalDevice() {
    uint32_t physicalDeviceCount = 0;
    CHECK_RESULT(vkEnumeratePhysicalDevices(instance,&physicalDeviceCount,nullptr));

    if (physicalDeviceCount<=0) {
        ERROR("No physical device found");
    }

    std::vector<VkPhysicalDevice> physicalDevicesVector(physicalDeviceCount);
    CHECK_RESULT(vkEnumeratePhysicalDevices(instance,&physicalDeviceCount,physicalDevicesVector.data()));

#ifdef _DEBUG
    int deviceIndex = 0;
    for(const auto & phyDev : physicalDevicesVector) {
        VkPhysicalDeviceProperties phyDevProperties;
        vkGetPhysicalDeviceProperties(phyDev, &phyDevProperties);

        std::cout << "--- Physical device: " << phyDevProperties.deviceName << " (index: " << (deviceIndex++) << ")" << std::endl;
        std::cout << "        apiVersion: " << phyDevProperties.apiVersion << std::endl;
        std::cout << "     driverVersion: " << phyDevProperties.driverVersion << std::endl;
        std::cout << "          vendorID: " << phyDevProperties.vendorID << std::endl;
        std::cout << "          deviceID: " << phyDevProperties.deviceID << std::endl;
        std::cout << "        deviceType: ";
        switch(phyDevProperties.deviceType) {
        case VK_PHYSICAL_DEVICE_TYPE_OTHER:
            std::cout << "OTHER";
            break;
        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
            std::cout << "INTEGRATED_GPU";
            break;
        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
            std::cout << "DISCRETE_GPU";
            break;
        case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
            std::cout << "VIRTUAL_GPU";
            break;
        case VK_PHYSICAL_DEVICE_TYPE_CPU:
            std::cout << "CPU";
            break;
        default:
            std::cout << "UNKNOWN!!!";
            break;
        }

        std::cout << std::endl;
    }
#endif // _DEBUG

    physicalDevice = physicalDevicesVector.at(0);

    // Gather Physical Device Memory Properties
    vkGetPhysicalDeviceMemoryProperties(physicalDevice,&physicalDeviceMemoryProperties);

}

void VulkanBase::selectQueue() {
    uint32_t queueFamilyPropertyCount = 0;

    vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice,&queueFamilyPropertyCount,nullptr);
    if (queueFamilyPropertyCount<=0)
        ERROR("Physical device has no queue families");

    std::vector<VkQueueFamilyProperties> queueFamilyPropertiesVector(queueFamilyPropertyCount);
    vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice,&queueFamilyPropertyCount,queueFamilyPropertiesVector.data());

    uint32_t queueFamilyIndex = 0;
    int32_t selectedQueueFamilyIndex = -1;
    VkBool32 presentSupport = VK_FALSE;

#ifdef _DEBUG
    std::cout << std::endl << "--- Number of queue families " << queueFamilyPropertyCount << std::endl;
#endif // _DEBUG

    for(const auto & queueFamProp : queueFamilyPropertiesVector) {
        CHECK_RESULT(vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, swapchain.surface, &presentSupport));
#ifdef _DEBUG
        std::cout << "--- Properties for queue family " << queueFamilyIndex << std::endl;
        std::cout << "                     queueFlags:";

        if(queueFamProp.queueFlags & VK_QUEUE_GRAPHICS_BIT)
            std::cout << " G";
        if(queueFamProp.queueFlags & VK_QUEUE_COMPUTE_BIT)
            std::cout << " C";
        if(queueFamProp.queueFlags & VK_QUEUE_TRANSFER_BIT)
            std::cout << " T";
        if(queueFamProp.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT)
            std::cout << " S";

        std::cout << '\n';
        std::cout << "                     queueCount: " << queueFamProp.queueCount << std::endl;
        std::cout << "             timestampValidBits: " << queueFamProp.timestampValidBits << std::endl;
        std::cout << "    minImageTransferGranularity: " << queueFamProp.minImageTransferGranularity.width
                  << ", " << queueFamProp.minImageTransferGranularity.height
                  << ", " << queueFamProp.minImageTransferGranularity.depth
                  << std::endl;

        std::cout << "       Supports present?: " << std::boolalpha << bool(presentSupport) << std::endl << std::endl;
#endif // _DEBUG

        if (bool(queueFamProp.queueFlags & VK_QUEUE_GRAPHICS_BIT) && presentSupport == VK_TRUE) {
            if (selectedQueueFamilyIndex < 0)
                selectedQueueFamilyIndex = queueFamilyIndex;
        }
        queueFamilyIndex++;
    }

    if (selectedQueueFamilyIndex<0)
        ERROR("No queue with both graphics and present capabilities found");

    // Create device after selecting the queue
    std::array<float,1> queuePriorities = {0.0f};

    VkDeviceQueueCreateInfo queueCreateInfo = {
        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
        .pNext = nullptr,
        .flags = VK_FLAGS_NONE,
        .queueFamilyIndex = (uint32_t) selectedQueueFamilyIndex,
        .queueCount = 1,                            //Number of queues to create
        .pQueuePriorities = queuePriorities.data()
    };

    // Call to createDevice
    createDevice(queueCreateInfo,1);

    //Get a handle to the selected queue
    vkGetDeviceQueue(device, (uint32_t) selectedQueueFamilyIndex, 0, &queue);      //TODO get handle if using multiple queues
    queueFamilyIndex = (uint32_t) selectedQueueFamilyIndex;

}


void VulkanBase::createDevice(VkDeviceQueueCreateInfo requestedQueues, uint32_t requestedQueuesCount) {
    //Check extensions available on the selected physical device before creating it
    // Check swap chain extension
    vkUtils::checkDeviceExtensionPresent(physicalDevice,VK_KHR_SWAPCHAIN_EXTENSION_NAME);
    std::vector<const char*> enabledExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};

    VkDeviceCreateInfo deviceCreateInfo = {
        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
        .pNext = nullptr,
        .flags = VK_FLAGS_NONE,
        .queueCreateInfoCount = requestedQueuesCount,
        .pQueueCreateInfos = &requestedQueues,
        .enabledLayerCount = 0,
        .ppEnabledLayerNames = nullptr,
        .enabledExtensionCount = (uint32_t) enabledExtensions.size(),
        .ppEnabledExtensionNames = enabledExtensions.data(),
        .pEnabledFeatures = NULL
    };

#ifdef _DEBUG
    if (enableValidation) {
        deviceCreateInfo.enabledLayerCount = vkDebug::validationLayerCount;
        deviceCreateInfo.ppEnabledLayerNames = vkDebug::validationLayerNames;
        // Check standard debug layers are present on the device
        for(uint32_t i = 0; i < deviceCreateInfo.enabledLayerCount; i++) {
            vkUtils::checkGlobalLayerPresent(vkDebug::validationLayerNames[i]);
        }
    }
#endif // _DEBUG

    CHECK_RESULT(vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device));
}

void VulkanBase::createCommandPool(const uint32_t queueFamilyIndex, const VkCommandPoolCreateFlagBits createFlagBits) {
    const VkCommandPoolCreateInfo commandPoolCreateInfo= {
        .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
        .pNext = NULL,
        .flags = createFlagBits,
        .queueFamilyIndex = queueFamilyIndex
    };

    CHECK_RESULT(vkCreateCommandPool(device, &commandPoolCreateInfo,nullptr,&commandPool));

#ifdef _DEBUG
    std::cout << "\n+++ Created command pool" << std::endl;
#endif // _DEBUG
}

void VulkanBase::createSynchroItems()
{
    // Semaphores

    VkSemaphoreCreateInfo semaphoreCreateInfo = {
        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
        .pNext = NULL,
        .flags = VK_FLAGS_NONE
    };

    // Semaphore signaled on swapchain image ready to use and wait on the queue before rendering/present
    CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &imageAcquiredSemaphore));

    // Semaphore signaled on queue rendering termination and waited on present operation
    CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderingCompletedSemaphore));

    // Fences

    VkFenceCreateInfo fenceCreateInfo = {
        .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
        .pNext = NULL,
        .flags = VK_FLAGS_NONE
    };

    CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &presentFence));

    #ifdef _DEBUG
    std::cout << "\n+++ Created semaphores and fences\n";
    #endif // _DEBUG
}



void VulkanBase::createCommandBuffers(VkCommandBuffer* cmdBuffer, uint32_t commandBufferCount, VkCommandBufferLevel cmdBufferLevel)
{
    const VkCommandBufferAllocateInfo commandBufferAllocateInfo = {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
        .pNext = NULL,
        .commandPool = commandPool,
        .level = cmdBufferLevel,
        .commandBufferCount = commandBufferCount
    };

    CHECK_RESULT(vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, cmdBuffer));

    #ifdef _DEBUG
    std::cout << "\n+++ Allocated " << commandBufferCount << " command buffers" << std::endl;
    #endif // _DEBUG
}

void VulkanBase::setupInitCommandBuffer()
{
    VkCommandBufferBeginInfo commandBufferBeginInfo = {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
        .pNext = NULL,
        .flags = VK_FLAGS_NONE,
        .pInheritanceInfo = NULL
    };

    CHECK_RESULT(vkBeginCommandBuffer(initCommandBuffer, &commandBufferBeginInfo));

    // Creates an image memory barrier to change the layout for every image on the swapchain
    VkImageMemoryBarrier imageMemoryBarrier = {
        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
        .pNext = NULL,
        .srcAccessMask = VK_FLAGS_NONE,
        .dstAccessMask = VK_FLAGS_NONE,
        .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
        .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
        .image = 0,
        .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}
    };


	// Pipeline Barrier for each swapchain image
    for (const auto& image: swapchain.swapchainImagesVector){
        imageMemoryBarrier.image = image;

        vkCmdPipelineBarrier(initCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, //Put barrier on top of the pipeline
        VK_FLAGS_NONE,
        0, nullptr,                 // memoryBarrier
        0, nullptr,                 // bufferMemoryBarrier
        1, &imageMemoryBarrier);    // imageMemoryBarrier
    }

    CHECK_RESULT(vkEndCommandBuffer(initCommandBuffer));

    #ifdef _DEBUG
    std::cout << "\n+++ Finished recording initCommandBuffer\n";
    #endif // _DEBUG
}

void VulkanBase::setupPresentCommandBuffer(const VkImage currentSwapchainImage, const float* clearColors)
{

 VkCommandBufferBeginInfo commandBufferBeginInfo = {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
        .pNext = NULL,
        .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
        .pInheritanceInfo = NULL
    };

    CHECK_RESULT(vkBeginCommandBuffer(presentCommandBuffer, &commandBufferBeginInfo));

    VkImageMemoryBarrier imageMemoryBarrier = {
        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
        .pNext = NULL,
        .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
        .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
        .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
        .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
        .image = currentSwapchainImage,
        .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}
    };

    //Set barrier on top to change layout and access
    vkCmdPipelineBarrier(presentCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
    VK_FLAGS_NONE, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);

    VkClearColorValue clearColorValue;
    VkImageSubresourceRange imageSubresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};

    clearColorValue.float32[0] = clearColors[0];
    clearColorValue.float32[1] = clearColors[1];
    clearColorValue.float32[2] = clearColors[2];
    clearColorValue.float32[3] = 1.0f;

    // Command to clear the swapchain image
    vkCmdClearColorImage(presentCommandBuffer,currentSwapchainImage,
    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColorValue, 1, &imageSubresourceRange);

    /*
	 * Transition the swapchain image from VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
	 * to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
	 */
	imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
	imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
	imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
	imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;

    // Set barrier end of pipeline
	vkCmdPipelineBarrier(presentCommandBuffer,
		VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
		0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier
	);

    CHECK_RESULT(vkEndCommandBuffer(presentCommandBuffer));

    #ifdef _DEBUG
    //std::cout << "\n+++ Finished recording presentCommandBuffer\n";
    #endif // _DEBUG
}

void VulkanBase::renderFrame(const float* clearColors)
{
    // Wait on previous frame fence (render too fast)
    //CHECK_RESULT(vkWaitForFences(device, 1, &presentFence, VK_TRUE, UINT64_MAX));
    //CHECK_RESULT(vkResetFences(device, 1, &presentFence));

    // Acquire next image on the swapchain
    uint32_t imageIndex = UINT64_MAX;
    CHECK_RESULT(vkAcquireNextImageKHR(device, swapchain.swapchain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE, &imageIndex));

    // Setup the present command buffer
    setupPresentCommandBuffer(swapchain.swapchainImagesVector.at(imageIndex),clearColors);
    // Submit present command buffer to the queue
    // Waits on imageAcquiredSemaphore so it doesnt start rendering until the image from the swapchain is ready and
    // it also signals the renderingCompletedSemaphore used by the later present

    VkPipelineStageFlags pipelineStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    VkSubmitInfo submitInfo = {
        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
        .pNext = NULL,
        .waitSemaphoreCount = 1,
        .pWaitSemaphores = &imageAcquiredSemaphore,
        .pWaitDstStageMask = &pipelineStageFlags,
        .commandBufferCount = 1,
        .pCommandBuffers = &presentCommandBuffer,
        .signalSemaphoreCount = 1,
        .pSignalSemaphores = &renderingCompletedSemaphore
    };

    CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));

    // Present the rendered image
    VkPresentInfoKHR presentInfo = {
        .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
        .pNext = NULL,
        .waitSemaphoreCount = 1,
        .pWaitSemaphores = &renderingCompletedSemaphore,
        .swapchainCount = 1,
        .pSwapchains = &swapchain.swapchain,
        .pImageIndices = &imageIndex,
        .pResults = nullptr
    };

    CHECK_RESULT(vkQueuePresentKHR(queue,&presentInfo));

    CHECK_RESULT(vkQueueWaitIdle(queue)); //TODO Not sure this is the correct way...


}



void VulkanBase::prepare()
{
    //Allocate command Buffers
    createCommandBuffers(&initCommandBuffer, 1, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    createCommandBuffers(&presentCommandBuffer, 1, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    commandBuffersVector.push_back(initCommandBuffer);
    commandBuffersVector.push_back(presentCommandBuffer);
    //Initialize command Buffers
    setupInitCommandBuffer();
    // Submit initialization command buffer to the queue
    VkSubmitInfo submitInfo = {
        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
        .pNext = nullptr,
        .waitSemaphoreCount = 0,
        .pWaitSemaphores = nullptr,
        .pWaitDstStageMask = VK_FLAGS_NONE,
        .commandBufferCount = 1,
        .pCommandBuffers = &initCommandBuffer,
        .signalSemaphoreCount = 0,
        .pSignalSemaphores = nullptr
    };

    CHECK_RESULT(vkQueueSubmit(queue,1,&submitInfo, VK_NULL_HANDLE));

    CHECK_RESULT(vkQueueWaitIdle(queue));

    vkFreeCommandBuffers(device, commandPool, 1, &initCommandBuffer);

#ifdef _DEBUG
    std::cout << "\n+++ initCommandBuffer work complete!\n";
    std::cout << "\n******* Rendering Start ******\n";
#endif // _DEBUG

}
Ejemplo n.º 25
0
int main(){
	printf("This code initializes a Vulkan device");
	/**
	Steps required
	1. Create Vulkan Instance
	2. Enumerate the GPUs
	3. Query Queues on the GPU (Queues represent on what 'channels' will the data process, query the queue
		for COMPUTE type queue or GRAPHICS type queue
	4. Create a queue priority
	5. Create a device with information from 2, 3 and 4
	**/

	/** 1. Create Vulkan Instance **/
	VkApplicationInfo appInfo = {};

	appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
	appInfo.pNext = NULL;
	appInfo.pApplicationName = APP_SHORT_NAME;
	appInfo.applicationVersion = 1;
	appInfo.pEngineName = APP_SHORT_NAME;
	appInfo.engineVersion = 1;
	appInfo.apiVersion = VK_API_VERSION;

	VkInstanceCreateInfo icInfo = {};
	icInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
	icInfo.pNext = NULL;
	icInfo.flags = 0;
	icInfo.pApplicationInfo = & appInfo;
	icInfo.enabledExtensionCount = 0;
	icInfo.ppEnabledExtensionNames = NULL;
	icInfo.enabledLayerCount = 0;
	icInfo.enabledLayerCount = NULL;

	VkInstance instance;
	VkResult res;

	res = vkCreateInstance(&icInfo, NULL, &instance);
	if(res == VK_ERROR_INCOMPATIBLE_DRIVER){
		printf("Cannot find a Vulkan Compatible ICD\n");
		exit(-1);
	} else if(res){
		printf("Some error occured\n");
		exit(-1);
	}
	printf("Yay! Vulkan is initialized\n");

	/** 2. Enumerate the GPUs **/
	uint32_t gpuCount = 0;

	res = vkEnumeratePhysicalDevices(instance, &gpuCount, NULL);
	printf("found %d gpus\n", gpuCount);
	VkPhysicalDevice* gpus = new VkPhysicalDevice[gpuCount];

	printf("Listing gpus...\n", gpuCount);
	res = vkEnumeratePhysicalDevices(instance, &gpuCount, gpus);

	while(++idx < gpuCount){
		VkPhysicalDeviceProperties props= {};
		vkGetPhysicalDeviceProperties(gpus[idx], &props);
		printf("%d-%d-%d-%d-%s\n", props.apiVersion, props.driverVersion, props.vendorID, props.deviceID, props.deviceName);
	}


	/** 3. Query for the supported queues **/

	/** From renderdocs vulkan
	Command buffers are submitted to a VkQueue. 
	The notion of queues are how work becomes serialised to be passed to the GPU. 
	A VkPhysicalDevice (remember way back? The GPU handle) can report a number of queue families with different capabilities. 
	e.g. a graphics queue family and a compute-only queue family. 
	When you create your device you ask for a certain number of queues from each family, and then you can enumerate them 
	from the device after creation with vkGetDeviceQueue().
	**/

	uint32_t queue_count = 0;
	vkGetPhysicalDeviceQueueFamilyProperties(gpus[0], &queue_count, NULL);
	if(queue_count <= 0){
		printf("No Queues found.. aborting\n");
		exit(-1);
	}

	VkQueueFamilyProperties* queue_props = new VkQueueFamilyProperties[queue_count];

	vkGetPhysicalDeviceQueueFamilyProperties(gpus[0], &queue_count, queue_props);

	float queue_priorities[1] = {0.0};		/** 4. Create a queue priority **/
	VkDeviceQueueCreateInfo qi = {};
	qi.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
	qi.pNext = NULL;
	qi.queueCount = 1;
	qi.pQueuePriorities = queue_priorities;

	idx = -1;
	while(++idx < queue_count){
		if(queue_props[idx].queueFlags & VK_QUEUE_GRAPHICS_BIT){	//Look for a queue that has Graphics capabilities
			qi.queueFamilyIndex = idx;
			break;
		}
	}

	/** 5. Create a device with information from 2, 3 and 4 **/

	VkDeviceCreateInfo dci = {};
	dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
	dci.pNext = NULL;
	dci.queueCreateInfoCount = 1;
	dci.pQueueCreateInfos = &qi;
	dci.enabledExtensionCount = 0;
	dci.ppEnabledExtensionNames = NULL;
	dci.enabledLayerCount = 0;
	dci.ppEnabledLayerNames = NULL;
	dci.pEnabledFeatures = NULL;

	VkDevice device;
	res = vkCreateDevice(gpus[0], &dci, NULL, &device);
	if(res){
		printf("There was a problem creating the device");
		exit(-1);
	}

	/** All's great, first thing lets create a command buffer **/

	VkCommandPoolCreateInfo cpci = {};
	cpci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	cpci.pNext = NULL;
	cpci.queueFamilyIndex = qi.queueFamilyIndex;
	cpci.flags = 0;

	VkCommandPool cp;
	res = vkCreateCommandPool(device, &cpci, NULL, &cp);
	if(res){
		printf("There was a problem creating a command pool");
		exit(-1);
	}

	/** Create a command buffer from the command pool **/
	VkCommandBufferAllocateInfo cbai = {};
	cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
	cbai.pNext = NULL;
	cbai.commandPool = cp;
	cbai.commandBufferCount = 1;
	cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;

	VkCommandBuffer* commandBuffer = new VkCommandBuffer[1];	//single command

	res = vkAllocateCommandBuffers(device, &cbai, commandBuffer);

	if(res){
		printf("There was a problem creating a command buffer");
		exit(-1);
	}

	/** no, we never leave the crap behind **/

	vkFreeCommandBuffers(device, cp, 1, commandBuffer);
	vkDestroyCommandPool(device, cp, NULL);
	vkDestroyDevice(device, NULL);
	printf("Device created");
	vkDestroyInstance(instance, NULL);

	delete[] gpus;

	return 0;
}
Ejemplo n.º 26
0
bool CommandBufferManager::CreateCommandBuffers()
{
  VkDevice device = g_vulkan_context->GetDevice();
  VkResult res;

  for (FrameResources& resources : m_frame_resources)
  {
    resources.init_command_buffer_used = false;
    resources.needs_fence_wait = false;

    VkCommandPoolCreateInfo pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0,
                                         g_vulkan_context->GetGraphicsQueueFamilyIndex()};
    res = vkCreateCommandPool(g_vulkan_context->GetDevice(), &pool_info, nullptr,
                              &resources.command_pool);
    if (res != VK_SUCCESS)
    {
      LOG_VULKAN_ERROR(res, "vkCreateCommandPool failed: ");
      return false;
    }

    VkCommandBufferAllocateInfo buffer_info = {
        VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, resources.command_pool,
        VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(resources.command_buffers.size())};

    res = vkAllocateCommandBuffers(device, &buffer_info, resources.command_buffers.data());
    if (res != VK_SUCCESS)
    {
      LOG_VULKAN_ERROR(res, "vkAllocateCommandBuffers failed: ");
      return false;
    }

    VkFenceCreateInfo fence_info = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr,
                                    VK_FENCE_CREATE_SIGNALED_BIT};

    res = vkCreateFence(device, &fence_info, nullptr, &resources.fence);
    if (res != VK_SUCCESS)
    {
      LOG_VULKAN_ERROR(res, "vkCreateFence failed: ");
      return false;
    }

    // TODO: A better way to choose the number of descriptors.
    VkDescriptorPoolSize pool_sizes[] = {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 500000},
                                         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 500000},
                                         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 16},
                                         {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 16384},
                                         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 16384}};

    VkDescriptorPoolCreateInfo pool_create_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
                                                   nullptr,
                                                   0,
                                                   100000,  // tweak this
                                                   static_cast<u32>(ArraySize(pool_sizes)),
                                                   pool_sizes};

    res = vkCreateDescriptorPool(device, &pool_create_info, nullptr, &resources.descriptor_pool);
    if (res != VK_SUCCESS)
    {
      LOG_VULKAN_ERROR(res, "vkCreateDescriptorPool failed: ");
      return false;
    }
  }

  // Activate the first command buffer. ActivateCommandBuffer moves forward, so start with the last
  m_current_frame = m_frame_resources.size() - 1;
  ActivateCommandBuffer();
  return true;
}
Ejemplo n.º 27
0
Context::Context()
{
    if(!loadVulkanLibrary())
    {
        CV_Error(Error::StsError, "loadVulkanLibrary failed");
        return;
    }
    else if (!loadVulkanEntry())
    {
        CV_Error(Error::StsError, "loadVulkanEntry failed");
        return;
    }
    else if (!loadVulkanGlobalFunctions())
    {
        CV_Error(Error::StsError, "loadVulkanGlobalFunctions failed");
        return;
    }

    // create VkInstance, VkPhysicalDevice
    std::vector<const char *> enabledExtensions;
    if (enableValidationLayers)
    {
        uint32_t layerCount;
        vkEnumerateInstanceLayerProperties(&layerCount, NULL);

        std::vector<VkLayerProperties> layerProperties(layerCount);
        vkEnumerateInstanceLayerProperties(&layerCount, layerProperties.data());

        bool foundLayer = false;
        for (VkLayerProperties prop : layerProperties)
        {
            if (strcmp("VK_LAYER_LUNARG_standard_validation", prop.layerName) == 0)
            {
                foundLayer = true;
                break;
            }
        }

        if (!foundLayer)
        {
            throw std::runtime_error("Layer VK_LAYER_LUNARG_standard_validation not supported\n");
        }
        kEnabledLayers.push_back("VK_LAYER_LUNARG_standard_validation");

        uint32_t extensionCount;

        vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, NULL);
        std::vector<VkExtensionProperties> extensionProperties(extensionCount);
        vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensionProperties.data());

        bool foundExtension = false;
        for (VkExtensionProperties prop : extensionProperties)
        {
            if (strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, prop.extensionName) == 0)
            {
                foundExtension = true;
                break;
            }
        }

        if (!foundExtension) {
            throw std::runtime_error("Extension VK_EXT_DEBUG_REPORT_EXTENSION_NAME not supported\n");
        }
        enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
    }

    VkApplicationInfo applicationInfo = {};
    applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    applicationInfo.pApplicationName = "VkCom Library";
    applicationInfo.applicationVersion = 0;
    applicationInfo.pEngineName = "vkcom";
    applicationInfo.engineVersion = 0;
    applicationInfo.apiVersion = VK_API_VERSION_1_0;;

    VkInstanceCreateInfo createInfo = {};
    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    createInfo.flags = 0;
    createInfo.pApplicationInfo = &applicationInfo;

    // Give our desired layers and extensions to vulkan.
    createInfo.enabledLayerCount = kEnabledLayers.size();
    createInfo.ppEnabledLayerNames = kEnabledLayers.data();
    createInfo.enabledExtensionCount = enabledExtensions.size();
    createInfo.ppEnabledExtensionNames = enabledExtensions.data();

    VK_CHECK_RESULT(vkCreateInstance(&createInfo, NULL, &kInstance));

    if (!loadVulkanFunctions(kInstance))
    {
        CV_Error(Error::StsError, "loadVulkanFunctions failed");
        return;
    }

    if (enableValidationLayers && vkCreateDebugReportCallbackEXT)
    {
        VkDebugReportCallbackCreateInfoEXT createInfo = {};
        createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
        createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
                           VK_DEBUG_REPORT_WARNING_BIT_EXT |
                           VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
        createInfo.pfnCallback = &debugReportCallbackFn;

        // Create and register callback.
        VK_CHECK_RESULT(vkCreateDebugReportCallbackEXT(kInstance, &createInfo,
                                                       NULL, &kDebugReportCallback));
    }

    // find physical device
    uint32_t deviceCount;
    vkEnumeratePhysicalDevices(kInstance, &deviceCount, NULL);
    if (deviceCount == 0)
    {
        throw std::runtime_error("could not find a device with vulkan support");
    }

    std::vector<VkPhysicalDevice> devices(deviceCount);
    vkEnumeratePhysicalDevices(kInstance, &deviceCount, devices.data());

    for (VkPhysicalDevice device : devices)
    {
        if (true)
        {
            kPhysicalDevice = device;
            break;
        }
    }

    kQueueFamilyIndex = getComputeQueueFamilyIndex();

    // create device, queue, command pool
    VkDeviceQueueCreateInfo queueCreateInfo = {};
    queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    queueCreateInfo.queueFamilyIndex = kQueueFamilyIndex;
    queueCreateInfo.queueCount = 1; // create one queue in this family. We don't need more.
    float queuePriorities = 1.0;  // we only have one queue, so this is not that imporant.
    queueCreateInfo.pQueuePriorities = &queuePriorities;

    VkDeviceCreateInfo deviceCreateInfo = {};

    // Specify any desired device features here. We do not need any for this application, though.
    VkPhysicalDeviceFeatures deviceFeatures = {};

    deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    deviceCreateInfo.enabledLayerCount = kEnabledLayers.size();
    deviceCreateInfo.ppEnabledLayerNames = kEnabledLayers.data();
    deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
    deviceCreateInfo.queueCreateInfoCount = 1;
    deviceCreateInfo.pEnabledFeatures = &deviceFeatures;

    VK_CHECK_RESULT(vkCreateDevice(kPhysicalDevice, &deviceCreateInfo, NULL, &kDevice));

    // Get a handle to the only member of the queue family.
    vkGetDeviceQueue(kDevice, kQueueFamilyIndex, 0, &kQueue);

    // create command pool
    VkCommandPoolCreateInfo commandPoolCreateInfo = {};
    commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
    // the queue family of this command pool. All command buffers allocated from this command pool,
    // must be submitted to queues of this family ONLY.
    commandPoolCreateInfo.queueFamilyIndex = kQueueFamilyIndex;
    VK_CHECK_RESULT(vkCreateCommandPool(kDevice, &commandPoolCreateInfo, NULL, &kCmdPool));
}
Ejemplo n.º 28
0
void vkeGameRendererDynamic::initRenderer(){
	VulkanDC *dc = VulkanDC::Get();
	VulkanDC::Device *device = dc->getDevice();

	m_instance_count = 128;

	glWaitVkSemaphoreNV = (PFNGLWAITVKSEMAPHORENVPROC)NVPWindow::sysGetProcAddress("glWaitVkSemaphoreNV");
	glSignalVkSemaphoreNV = (PFNGLSIGNALVKSEMAPHORENVPROC)NVPWindow::sysGetProcAddress("glSignalVkSemaphoreNV");
	glSignalVkFenceNV = (PFNGLSIGNALVKFENCENVPROC)NVPWindow::sysGetProcAddress("glSignalVkFenceNV");
	glDrawVkImageNV = (PFNGLDRAWVKIMAGENVPROC)NVPWindow::sysGetProcAddress("glDrawVkImageNV");

	VkSemaphoreCreateInfo semInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
	VkFenceCreateInfo fenceInfo = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};

	VKA_CHECK_ERROR(vkCreateSemaphore(device->getVKDevice(), &semInfo, NULL, &m_present_done[0]), "Could not create present done semaphore.\n");
	VKA_CHECK_ERROR(vkCreateSemaphore(device->getVKDevice(), &semInfo, NULL, &m_render_done[0]), "Could not create render done semaphore.\n");
	VKA_CHECK_ERROR(vkCreateSemaphore(device->getVKDevice(), &semInfo, NULL, &m_present_done[1]), "Could not create present done semaphore.\n");
	VKA_CHECK_ERROR(vkCreateSemaphore(device->getVKDevice(), &semInfo, NULL, &m_render_done[1]), "Could not create render done semaphore.\n");

	VKA_CHECK_ERROR(vkCreateFence(device->getVKDevice(), &fenceInfo, NULL, &m_update_fence[0]), "Could not create update fence.\n");
	fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
	VKA_CHECK_ERROR(vkCreateFence(device->getVKDevice(), &fenceInfo, NULL, &m_update_fence[1]), "Could not create update fence.\n");

	m_terrain_command[0] = VK_NULL_HANDLE;
	m_terrain_command[1] = VK_NULL_HANDLE;
	m_framebuffers[0] = VK_NULL_HANDLE;
	m_framebuffers[1] = VK_NULL_HANDLE;
	m_update_commands[0] = VK_NULL_HANDLE;
	m_update_commands[1] = VK_NULL_HANDLE;

	m_is_first_frame = true;


	nv_math::vec3f table[128][128];

	for (int v = 0; v < 128; ++v){
		for (int u = 0; u < 128; ++u){

			nv_math::vec2f vctr(quickRandomUVD(), quickRandomUVD());
			vctr = nv_math::normalize(vctr);

			table[u][v] = nv_math::vec3f(vctr.x, vctr.y, vctr.x);
		}
	}

	m_cube_textures.newTexture(1)->loadCubeDDS("environ.dds");
	m_screen_quad.initQuadData();
	m_terrain_quad.initQuadData();

	m_textures.newTexture(0)->setFormat(VK_FORMAT_R32G32B32_SFLOAT);
	m_textures.getTexture(0)->loadTextureFloatData((float *)&(table[0][0].x), 128, 128, 3);


	m_flight_paths = (FlightPath**)malloc(sizeof(FlightPath*) * m_instance_count);

	for (uint32_t i = 0; i < m_instance_count; ++i){

		nv_math::vec2f initPos(quickRandomUVD()*100.0, -200 + (quickRandomUVD() * 20));
		nv_math::vec2f endPos(quickRandomUVD()*100.0, 200 + (quickRandomUVD() * 20));
		m_flight_paths[i] = new FlightPath(initPos, endPos, quickRandomUVD() * 0.5 + 0.5, quickRandomUVD() * 4 + 10);

	}

	/*
	Just initialises the draw call objects
	not the threads. They store thread local
	data for the threaded cmd buffer builds.
	*/
	initDrawCalls();


	/*
	Create primary command pool for the
	*/
	VkCommandPoolCreateInfo cmdPoolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
	cmdPoolInfo.queueFamilyIndex = 0;
	cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;

	VKA_CHECK_ERROR(vkCreateCommandPool(device->getVKDevice(), &cmdPoolInfo, NULL, &m_primary_buffer_cmd_pool), "Could not create primary command pool.\n");

	m_primary_commands[0] = VK_NULL_HANDLE;
	m_primary_commands[1] = VK_NULL_HANDLE;

	VkCommandBufferAllocateInfo cmdBufInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
	cmdBufInfo.commandBufferCount = 2;
	cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
	cmdBufInfo.commandPool = m_primary_buffer_cmd_pool;



	VKA_CHECK_ERROR(vkAllocateCommandBuffers(device->getVKDevice(), &cmdBufInfo, m_primary_commands), "Could not allocate primary command buffers.\n");
	VKA_CHECK_ERROR(vkAllocateCommandBuffers(device->getVKDevice(), &cmdBufInfo, m_update_commands), "Could not allocate primary command buffers.\n");

	m_current_buffer_index = 0;

}
Ejemplo n.º 29
0
static void setup_vulkan(GLFWwindow* window)
{
    VkResult err;

    // Create Vulkan Instance
    {
        uint32_t extensions_count;
        const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&extensions_count);

        VkInstanceCreateInfo create_info = {};
        create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        create_info.enabledExtensionCount = extensions_count;
        create_info.ppEnabledExtensionNames = glfw_extensions;

#ifdef IMGUI_VULKAN_DEBUG_REPORT
        // enabling multiple validation layers grouped as lunarg standard validation
        const char* layers[] = {"VK_LAYER_LUNARG_standard_validation"};
        create_info.enabledLayerCount = 1;
        create_info.ppEnabledLayerNames = layers;

        // need additional storage for char pointer to debug report extension
        const char** extensions = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
        for (size_t i = 0; i < extensions_count; i++)
            extensions[i] = glfw_extensions[i];
        extensions[ extensions_count ] = "VK_EXT_debug_report";
        create_info.enabledExtensionCount = extensions_count+1;
        create_info.ppEnabledExtensionNames = extensions;
#endif // IMGUI_VULKAN_DEBUG_REPORT

        err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
        check_vk_result(err);

#ifdef IMGUI_VULKAN_DEBUG_REPORT
        free(extensions);

        // create the debug report callback
        VkDebugReportCallbackCreateInfoEXT debug_report_ci ={};
        debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
        debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
        debug_report_ci.pfnCallback = debug_report;
        debug_report_ci.pUserData = NULL;
        
        // get the proc address of the function pointer, required for used extensions
        PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = 
            (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");

        err = vkCreateDebugReportCallbackEXT( g_Instance, &debug_report_ci, g_Allocator, &g_Debug_Report );
        check_vk_result(err);
#endif // IMGUI_VULKAN_DEBUG_REPORT
    }

    // Create Window Surface
    {
        err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &g_Surface);
        check_vk_result(err);
    }

    // Get GPU
    {
        uint32_t gpu_count;
        err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
        check_vk_result(err);

        VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
        err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
        check_vk_result(err);

        // If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose
        // e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc.
        // for sake of simplicity we'll just take the first one, assuming it has a graphics queue family.
        g_Gpu = gpus[0];
        free(gpus);
    }

    // Get queue
    {
        uint32_t count;
        vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, NULL);
        VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
        vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, queues);
        for (uint32_t i = 0; i < count; i++)
        {
            if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
            {
                g_QueueFamily = i;
                break;
            }
        }
        free(queues);
    }

    // Check for WSI support
    {
        VkBool32 res;
        vkGetPhysicalDeviceSurfaceSupportKHR(g_Gpu, g_QueueFamily, g_Surface, &res);
        if (res != VK_TRUE)
        {
            fprintf(stderr, "Error no WSI support on physical device 0\n");
            exit(-1);
        }
    }

    // Get Surface Format
    {
        // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
        // Assuming that the default behavior is without setting this bit, there is no need for separate Spawchain image and image view format
        // additionally several new color spaces were introduced with Vulkan Spec v1.0.40
        // hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used
        uint32_t count;
        vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, NULL);
        VkSurfaceFormatKHR *formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * count);
        vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, formats);

        // first check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available
        if (count == 1)
        {
            if( formats[0].format == VK_FORMAT_UNDEFINED )
            {
                g_SurfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM;
                g_SurfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
            }
            else
            {   // no point in searching another format
                g_SurfaceFormat = formats[0];
            }
        }
        else
        {
            // request several formats, the first found will be used 
            VkFormat requestSurfaceImageFormat[] = {VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM};
            VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
            bool requestedFound = false;
            for (size_t i = 0; i < sizeof(requestSurfaceImageFormat) / sizeof(requestSurfaceImageFormat[0]); i++)
            {
                if( requestedFound ) {
                    break;
                }
                for (uint32_t j = 0; j < count; j++)
                {
                    if (formats[j].format == requestSurfaceImageFormat[i] && formats[j].colorSpace == requestSurfaceColorSpace)
                    {
                        g_SurfaceFormat = formats[j];
                        requestedFound = true;
                    }
                }
            }

            // if none of the requested image formats could be found, use the first available
            if (!requestedFound)
                g_SurfaceFormat = formats[0];
        }
        free(formats);
    }


    // Get Present Mode
    {
        // Requst a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
#ifdef IMGUI_UNLIMITED_FRAME_RATE
        g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
#else
        g_PresentMode = VK_PRESENT_MODE_FIFO_KHR;
#endif
        uint32_t count = 0;
        vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, nullptr);
        VkPresentModeKHR* presentModes = (VkPresentModeKHR*)malloc(sizeof(VkQueueFamilyProperties) * count);
        vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, presentModes);
        bool presentModeAvailable = false;
        for (size_t i = 0; i < count; i++) 
        {
            if (presentModes[i] == g_PresentMode)
            {
                presentModeAvailable = true;
                break;
            }
        }
        if( !presentModeAvailable )
            g_PresentMode = VK_PRESENT_MODE_FIFO_KHR;   // always available
    }


    // Create Logical Device
    {
        int device_extension_count = 1;
        const char* device_extensions[] = {"VK_KHR_swapchain"};
        const uint32_t queue_index = 0;
        const uint32_t queue_count = 1;
        const float queue_priority[] = {1.0f};
        VkDeviceQueueCreateInfo queue_info[1] = {};
        queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queue_info[0].queueFamilyIndex = g_QueueFamily;
        queue_info[0].queueCount = queue_count;
        queue_info[0].pQueuePriorities = queue_priority;
        VkDeviceCreateInfo create_info = {};
        create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
        create_info.queueCreateInfoCount = sizeof(queue_info)/sizeof(queue_info[0]);
        create_info.pQueueCreateInfos = queue_info;
        create_info.enabledExtensionCount = device_extension_count;
        create_info.ppEnabledExtensionNames = device_extensions;
        err = vkCreateDevice(g_Gpu, &create_info, g_Allocator, &g_Device);
        check_vk_result(err);
        vkGetDeviceQueue(g_Device, g_QueueFamily, queue_index, &g_Queue);
    }

    // Create Framebuffers
    {
        int w, h;
        glfwGetFramebufferSize(window, &w, &h);
        resize_vulkan(window, w, h);
        glfwSetFramebufferSizeCallback(window, resize_vulkan);
    }

    // Create Command Buffers
    for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
    {
        {
            VkCommandPoolCreateInfo info = {};
            info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
            info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
            info.queueFamilyIndex = g_QueueFamily;
            err = vkCreateCommandPool(g_Device, &info, g_Allocator, &g_CommandPool[i]);
            check_vk_result(err);
        }
        {
            VkCommandBufferAllocateInfo info = {};
            info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
            info.commandPool = g_CommandPool[i];
            info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
            info.commandBufferCount = 1;
            err = vkAllocateCommandBuffers(g_Device, &info, &g_CommandBuffer[i]);
            check_vk_result(err);
        }
        {
            VkFenceCreateInfo info = {};
            info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
            info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
            err = vkCreateFence(g_Device, &info, g_Allocator, &g_Fence[i]);
            check_vk_result(err);
        }
        {
            VkSemaphoreCreateInfo info = {};
            info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
            err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_PresentCompleteSemaphore[i]);
            check_vk_result(err);
            err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_RenderCompleteSemaphore[i]);
            check_vk_result(err);
        }
    }

    // Create Descriptor Pool
    {
        VkDescriptorPoolSize pool_size[11] =
        {
            { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
            { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
            { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
            { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
            { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
            { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
            { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
            { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
            { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
            { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
            { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
        };
        VkDescriptorPoolCreateInfo pool_info = {};
        pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
        pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
        pool_info.maxSets = 1000 * 11;
        pool_info.poolSizeCount = 11;
        pool_info.pPoolSizes = pool_size;
        err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
        check_vk_result(err);
    }
}
static void *per_thread_code(void *arg) {
    /* This code should be executed by each of the three threads.  It will  */
    /* create a vertex buffer with position and color per vertex, then load */
    /* commands into the thread's designated command buffer to draw the     */
    /* triangle                                                             */
    VkResult U_ASSERT_ONLY res;
    size_t threadNum = (size_t)arg;
    VkCommandPoolCreateInfo poolInfo;
    poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    poolInfo.pNext = NULL;
    poolInfo.queueFamilyIndex = info.graphics_queue_family_index;
    poolInfo.flags = 0;
    vkCreateCommandPool(info.device, &poolInfo, NULL,
                        &threadCmdPools[threadNum]);

    VkCommandBufferAllocateInfo cmdBufInfo;
    cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    cmdBufInfo.pNext = NULL;
    cmdBufInfo.commandBufferCount = 1;
    cmdBufInfo.commandPool = threadCmdPools[threadNum];
    cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    vkAllocateCommandBuffers(info.device, &cmdBufInfo,
                             &threadCmdBufs[threadNum]);

    VkBufferCreateInfo buf_info = {};
    buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    buf_info.pNext = NULL;
    buf_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
    buf_info.size = 3 * sizeof(triData[0]);
    buf_info.queueFamilyIndexCount = 0;
    buf_info.pQueueFamilyIndices = NULL;
    buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    buf_info.flags = 0;
    res = vkCreateBuffer(info.device, &buf_info, NULL,
                         &vertex_buffer[threadNum].buf);
    assert(res == VK_SUCCESS);

    VkMemoryRequirements mem_reqs;
    vkGetBufferMemoryRequirements(info.device, vertex_buffer[threadNum].buf,
                                  &mem_reqs);

    VkMemoryAllocateInfo alloc_info = {};
    alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
    alloc_info.pNext = NULL;
    alloc_info.memoryTypeIndex = 0;

    alloc_info.allocationSize = mem_reqs.size;
    bool pass;
    pass = memory_type_from_properties(info, mem_reqs.memoryTypeBits,
                                       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
                                       &alloc_info.memoryTypeIndex);
    assert(pass);

    res = vkAllocateMemory(info.device, &alloc_info, NULL,
                           &(vertex_buffer[threadNum].mem));
    assert(res == VK_SUCCESS);

    uint8_t *pData;
    res = vkMapMemory(info.device, vertex_buffer[threadNum].mem, 0,
                      mem_reqs.size, 0, (void **)&pData);
    assert(res == VK_SUCCESS);

    memcpy(pData, &triData[threadNum * 3], 3 * sizeof(triData[0]));

    vkUnmapMemory(info.device, vertex_buffer[threadNum].mem);

    res = vkBindBufferMemory(info.device, vertex_buffer[threadNum].buf,
                             vertex_buffer[threadNum].mem, 0);
    assert(res == VK_SUCCESS);

    VkCommandBufferBeginInfo cmd_buf_info = {};
    cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    cmd_buf_info.pNext = NULL;
    cmd_buf_info.flags = 0;
    cmd_buf_info.pInheritanceInfo = NULL;

    res = vkBeginCommandBuffer(threadCmdBufs[threadNum], &cmd_buf_info);
    assert(res == VK_SUCCESS);

    VkRenderPassBeginInfo rp_begin;
    rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    rp_begin.pNext = NULL;
    rp_begin.renderPass = info.render_pass;
    rp_begin.framebuffer = info.framebuffers[info.current_buffer];
    rp_begin.renderArea.offset.x = 0;
    rp_begin.renderArea.offset.y = 0;
    rp_begin.renderArea.extent.width = info.width;
    rp_begin.renderArea.extent.height = info.height;
    rp_begin.clearValueCount = 0;
    rp_begin.pClearValues = NULL;

    vkCmdBeginRenderPass(threadCmdBufs[threadNum], &rp_begin,
                         VK_SUBPASS_CONTENTS_INLINE);

    vkCmdBindPipeline(threadCmdBufs[threadNum], VK_PIPELINE_BIND_POINT_GRAPHICS,
                      info.pipeline);
    const VkDeviceSize offsets[1] = {0};
    vkCmdBindVertexBuffers(threadCmdBufs[threadNum], 0, 1,
                           &vertex_buffer[threadNum].buf, offsets);

    VkViewport viewport;
    viewport.height = (float)info.height;
    viewport.width = (float)info.width;
    viewport.minDepth = (float)0.0f;
    viewport.maxDepth = (float)1.0f;
    viewport.x = 0;
    viewport.y = 0;
    vkCmdSetViewport(threadCmdBufs[threadNum], 0, NUM_VIEWPORTS, &viewport);

    VkRect2D scissor;
    scissor.extent.width = info.width;
    scissor.extent.height = info.height;
    scissor.offset.x = 0;
    scissor.offset.y = 0;
    vkCmdSetScissor(threadCmdBufs[threadNum], 0, NUM_SCISSORS, &scissor);

    vkCmdDraw(threadCmdBufs[threadNum], 3, 1, 0, 0);
    vkCmdEndRenderPass(threadCmdBufs[threadNum]);

    res = vkEndCommandBuffer(threadCmdBufs[threadNum]);
    assert(res == VK_SUCCESS);

    return NULL;
}