Link

Copiando dados de uma imagem para um staging buffer

Da mesma forma que fizemos anteriormente com o buffer de vértice, vamos primeiro criar um staging buffer na memória visível pela CPU para que possamos usar vkMapMemory e copiar os pixels para ele. Embora seja possível criar uma imagem de staging para essa finalidade, o Vulkan também permite que copiemos pixels de um objeto VkBuffer para um objeto VkImage, e a API para isso é mais rápida em alguns hardwares (HEBERT, 2016). Adicionamos as variáveis para este buffer temporário na função addTextureImage:

VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;

Para a criação do staging buffer utilizamos nossa função auxiliar createBuffer. O buffer deve estar na memória visível do host para que possamos mapeá-lo e ele deve ser usado como uma fonte de transferência para que possamos copiá-lo para uma imagem mais tarde, para isso, usamos os sinalizadores VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT e VK_BUFFER_USAGE_TRANSFER_SRC_BIT, respectivamente:

createBuffer(
	imageSize,
	VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
	VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
		| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
	stagingBuffer,
	stagingBufferMemory
);

Também utilizamos aqui o sinalizador VK_MEMORY_PROPERTY_HOST_COHERENT_BIT para solicitar que as gravações na memória pelo host sejam visíveis para o dispositivo (e vice-versa) sem a necessidade de liberar os caches de memória.

Podemos então copiar diretamente os valores de pixels que recebemos do objeto QImage para o buffer, da mesma forma que fizemos para o buffer de vértice:

void *data;
VkDevice device = m_window->device();
m_deviceFunctions->vkMapMemory(
	device,
	stagingBufferMemory,
	0,
	imageSize,
	0,
	&data
);
memcpy(data, image.constBits(), static_cast<size_t>(imageSize));
m_deviceFunctions->vkUnmapMemory(device, stagingBufferMemory);


Anterior Próximo