Link

Atualizando os descritores

Agora precisamos atualizar os descritores. Para isso, navegamos até a função createDescriptorSetLayout e adicionamos um VkDescriptorSetLayoutBinding para um descritor de uniform buffer. Vamos simplesmente colocá-lo na ligação após o descritor de sampler e imagem combinados:

VkDescriptorSetLayoutBinding uboLayoutBinding = {};
uboLayoutBinding.binding = 1;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr;

std::array<VkDescriptorSetLayoutBinding, 2> bindings =
	{samplerLayoutBinding, uboLayoutBinding};

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

Definimos o campo stageFlags para VK_SHADER_STAGE_VERTEX_BIT indicando que pretendemos usar o descritor de uniform buffer no vertex shader.

Agora, vamos à função createDescriptorPool e modificamos-a para incluir um VkDescriptorPoolSize para esse descritor:

std::array<VkDescriptorPoolSize, 2> poolSizes = {};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[0].descriptorCount = 1;
poolSizes[1].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[1].descriptorCount = 1;

VkDescriptorPoolCreateInfo poolInfo = {};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount =
	static_cast<uint32_t>(poolSizes.size());
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = static_cast<uint32_t>(poolSizes.size());

A etapa final é vincular o recurso do uniform buffer aos descritores no conjunto de descritores. Para isso, modificamos a função createDescriptorSets.

VkDescriptorImageInfo descriptorImageInfo = {};
descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
descriptorImageInfo.imageView = m_object->textureImageView;
descriptorImageInfo.sampler = m_textureSampler;

VkDescriptorBufferInfo bufferInfo = {};
bufferInfo.buffer = m_object->uniformBuffer;
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UniformBufferObject);

O recurso de buffer para um descritor de uniform buffer deve ser especificado em uma estrutura VkDescriptorBufferInfo, assim como os recursos de imagem e sampler são especificados em uma estrutura VkDescriptorImageInfo. É aqui que os objetos do capítulo anterior se reúnem.

std::array<VkWriteDescriptorSet, 2> descriptorWrites = {};

descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = m_object->descriptorSet;
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &descriptorImageInfo;

descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = m_object->descriptorSet;
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pBufferInfo = &bufferInfo;

m_deviceFunctions->vkUpdateDescriptorSets(
	device,
	descriptorWrites.size(),
	descriptorWrites.data(),
	0,
	nullptr
);

Os descritores devem ser atualizados com essas informações do buffer, assim como a imagem. Desta vez, estamos usando o campo pBufferInfo em vez de pImageInfo. Agora os descritores estão prontos para serem usados pelos shaders.

Se executarmos nos programa agora, notaremos que infelizmente nada é visível. O problema é que, devido ao rotação em Y que fizemos na matriz de projeção, os vértices agora estão sendo desenhados no sentido anti-horário, em vez de no sentido horário. Isso faz com que a seleção da face posterior (backface culling) seja ativada e evita que qualquer geometria seja desenhada. Para corrigir isso, devemos ir à função initPipeline e modificar frontFace em VkPipelineRasterizationStateCreateInfo para VK_FRONT_FACE_COUNTER_CLOCKWISE:

rasterizationInfo.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;

Ser executarmos nosso programa novamente, devemos ver o mesmo que mostrado na Figura 9. O retângulo mudou para um quadrado porque a matriz de projeção agora corrige a proporção de tela. A função updateUniformBuffer cuida do redimensionamento da tela, portanto, não precisamos recriar o conjunto de descritor quando o tamanho da janela for alterado.


Figura 9 – Rotação da geometria com textura usando Vulkan


Anterior Próximo