Link

Copiando o buffer para a imagem

Antes de voltarmos na função addTextureImage, vamos escrever mais uma função auxiliar chamada copyBufferToImage que irá copiar os dados de um buffer para um objeto de imagem:

void Renderer::copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height) {
	VkCommandBuffer commandBuffer = beginSingleTimeCommands();

	endSingleTimeCommands(commandBuffer);
}

De forma semelhante às copias de buffers, precisamos especificar qual parte do buffer será copiada para qual parte da imagem. Isso é feito por meio da estrutura VkBufferImageCopy:

VkBufferImageCopy region = {};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;

O campo bufferOffset dessa estrutura especifica o deslocamento desde o início da memória de um buffer a partir da qual os dados devem ser copiados. Os campos bufferRowLenght e bufferImageHeight definem, respectivamente, o comprimento de dados que representa uma única linha no buffer e a altura da imagem imaginária armazenada no buffer. Por exemplo, podemos ter alguns bytes de preenchimento entre as linhas da imagem. Se bufferRowLength for zero, presume-se que a imagem esteja compactada no buffer e, portanto, igual a largura da imagem de destino. Da mesma forma, se bufferImageHeight for zero, o número de linhas na imagem de origem será igual à altura da extensão da imagem. Especificar 0 para ambos indica que os pixels são simplesmente compactados, como são no nosso caso.

region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;

As partes da imagem que queremos modificar são especificadas no campo imageSubresource. Este é uma instância da estrutura VkImageSubresourceLayers. O campo aspectMask dessa estrutura contém o aspecto ou aspectos que são o destino da cópia da imagem. Normalmente, isso será um único bit da enumeração VkImageAspectFlagBits. Se a imagem de destino for uma imagem colorida, como no nosso caso, isso deve ser definido simplesmente como VK_IMAGE_ASPECT_COLOR_BIT.

region.imageSubresource.mipLevel = 0;

O nível do mapeamento MIP de destino é especificado no campo mipLevel de VkImageSubresourceLayers. Não utilizaremos mapeamento MIP, portando definimos esse campo como 0.

region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;

Se a imagem de destino for uma imagem de array, podemos especificar a camada inicial e o número de camadas para a cópia de imagem em baseArrayLayer e layerCount, respectivamente. Se a imagem não for uma imagem de array, como no nosso caso, esses campos deverão ser definidos como 0 e 1.

region.imageOffset.x = 0;
region.imageOffset.y = 0;
region.imageOffset.z = 0;
region.imageExtent.width = width;
region.imageExtent.height = height;
region.imageExtent.depth = 1;

Cada região pode segmentar uma imagem inteira ou uma janela menor dentro da imagem. O deslocamento da janela é especificado em imageOffset e o tamanho da janela é especificado em imageExtent. Queremos sobrescrever toda a imagem, portando, é definido imageOffset.x, imageOffset.y e imageOffset.z como 0, e configurado imageExtent.width e imageExtent.height para o tamanho da imagem. Como estamos tratando de imagens 2D, imageExtent.depth é definido como 1.

Como mencionado anteriormente para copiar dados de um buffer para uma imagem, precisamos executar o comando vkCmdCopyBufferToImage:

m_deviceFunctions->vkCmdCopyBufferToImage(
	commandBuffer,
	buffer,
	image,
	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
	1,
	&region
);

Os três primeiros parâmetros são auto-explicativos. O quarto parâmetro especifica o layout da imagem de destino das cópias, espera-se que isso seja VK_IMAGE_LAYOUT_GENERAL ou VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. Estamos assumindo aqui que a imagem já foi transferida para o layout ideal para copiar pixels, através do sinalizador VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. Os dois últimos parâmetros especificam, respectivamente, o número de regiões a serem atualizadas e um ponteiro para um array de estruturas VkBufferImageCopy, cada uma definindo uma região da imagem para copiar os dados. Isso significa que é possível executar várias cópias diferentes desse buffer para a imagem em uma única operação.


Anterior Próximo