Mesh loading and rendering now properly displaying glTF mesh

Added textures, modified structure to be more in line with glTF layout
Split matrices and material descriptor set
This commit is contained in:
Sascha Willems 2020-04-12 21:24:33 +02:00
parent d50a5d0f40
commit 9f7d13d5e0

View file

@ -38,17 +38,26 @@
#define ENABLE_VALIDATION false #define ENABLE_VALIDATION false
// Contains everything required to render a glTF model in Vulkan
// This class is very simplified but retains the basic glTF structure
class VulkanglTFModel
{
// The vertex layout for the samples' model
struct Vertex {
glm::vec3 pos;
glm::vec3 normal;
glm::vec2 uv;
glm::vec3 color;
};
};
class VulkanExample : public VulkanExampleBase class VulkanExample : public VulkanExampleBase
{ {
public: public:
bool wireframe = false; bool wireframe = false;
struct {
vks::Texture2D colorMap;
} textures;
// Vertex layout used in this example
// This must fit input locations of the vertex shader used to render the model
struct Vertex { struct Vertex {
glm::vec3 pos; glm::vec3 pos;
glm::vec3 normal; glm::vec3 normal;
@ -58,27 +67,42 @@ public:
struct ModelNode; struct ModelNode;
// Represents a single mesh-based node in the glTF scene graph // A primitive contains the data for a single draw call
// This is simplified as much as possible to make this sample easy to understand struct Primitive {
struct ModelNode {
ModelNode* parent;
uint32_t firstIndex; uint32_t firstIndex;
uint32_t indexCount; uint32_t indexCount;
glm::mat4 matrix; int32_t materialIndex;
};
// Contains the node's geometry and can be made up of an arbitrary number of primitives
struct Mesh {
std::vector<Primitive> primitives;
};
// A node represents an object in the glTF scene graph
struct ModelNode {
ModelNode* parent;
std::vector<ModelNode> children; std::vector<ModelNode> children;
Mesh mesh;
glm::mat4 matrix;
}; };
// Represents a glTF material used to access e.g. the texture to choose for a mesh // Represents a glTF material used to access e.g. the texture to choose for a mesh
// Only includes the most basic properties required for this sample
struct ModelMaterial { struct ModelMaterial {
glm::vec4 baseColorFactor = glm::vec4(1.0f); glm::vec4 baseColorFactor = glm::vec4(1.0f);
uint32_t baseColorTextureIndex; uint32_t baseColorTextureIndex;
}; };
// @todo
struct ModelImage {
vks::Texture2D texture;
VkDescriptorSet descriptorSet;
};
// Contains all Vulkan resources required to represent vertex and index buffers for a model // Contains all Vulkan resources required to represent vertex and index buffers for a model
// This is for demonstration and learning purposes, the other examples use a model loader class for easy access // This is for demonstration and learning purposes, the other examples use a model loader class for easy access
struct Model { struct Model {
std::vector<vks::Texture2D> images; std::vector<ModelImage> images;
// Textures in glTF are indices used by material to select an image (and optionally samplers) // Textures in glTF are indices used by material to select an image (and optionally samplers)
std::vector<uint32_t> textures; std::vector<uint32_t> textures;
std::vector<ModelMaterial> materials; std::vector<ModelMaterial> materials;
@ -119,7 +143,11 @@ public:
VkPipelineLayout pipelineLayout; VkPipelineLayout pipelineLayout;
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
VkDescriptorSetLayout descriptorSetLayout;
struct DescriptorSetLayouts {
VkDescriptorSetLayout matrices;
VkDescriptorSetLayout textures;
} descriptorSetLayouts;
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
{ {
@ -128,8 +156,9 @@ public:
rotationSpeed = 0.5f; rotationSpeed = 0.5f;
rotation = { -0.5f, -112.75f, 0.0f }; rotation = { -0.5f, -112.75f, 0.0f };
cameraPos = { 0.1f, 1.1f, 0.0f }; cameraPos = { 0.1f, 1.1f, 0.0f };
title = "Model rendering"; title = "glTF model rendering";
settings.overlay = true; settings.overlay = true;
//@todo: Use camera
} }
~VulkanExample() ~VulkanExample()
@ -142,11 +171,11 @@ public:
} }
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr);
model.destroy(device); model.destroy(device);
textures.colorMap.destroy();
uniformBuffers.scene.destroy(); uniformBuffers.scene.destroy();
} }
@ -175,33 +204,20 @@ public:
renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.clearValueCount = 2;
renderPassBeginInfo.pClearValues = clearValues; renderPassBeginInfo.pClearValues = clearValues;
const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
{ {
// Set target frame buffer
renderPassBeginInfo.framebuffer = frameBuffers[i]; renderPassBeginInfo.framebuffer = frameBuffers[i];
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); // Bind scene matrices descriptor to set 0
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid);
drawglTFModel(drawCmdBuffers[i]); drawglTFModel(drawCmdBuffers[i]);
/*
VkDeviceSize offsets[1] = { 0 };
// Bind mesh vertex buffer
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &model.vertices.buffer, offsets);
// Bind mesh index buffer
vkCmdBindIndexBuffer(drawCmdBuffers[i], model.indices.buffer, 0, VK_INDEX_TYPE_UINT32);
// Render mesh vertex buffer using its indices
vkCmdDrawIndexed(drawCmdBuffers[i], model.indices.count, 1, 0, 0, 0);
*/
drawUI(drawCmdBuffers[i]); drawUI(drawCmdBuffers[i]);
vkCmdEndRenderPass(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]);
VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
@ -210,8 +226,15 @@ public:
void drawglTFNode(VkCommandBuffer commandBuffer, ModelNode node) void drawglTFNode(VkCommandBuffer commandBuffer, ModelNode node)
{ {
if (node.indexCount > 0) { if (node.mesh.primitives.size() > 0) {
vkCmdDrawIndexed(commandBuffer, node.indexCount, 1, node.firstIndex, 0, 0); for (Primitive& primitive : node.mesh.primitives) {
if (primitive.indexCount > 0) {
// @todo: link mat to node
uint32_t texture = model.textures[model.materials[primitive.materialIndex].baseColorTextureIndex];
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &model.images[texture].descriptorSet, 0, nullptr);
vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0);
}
}
} }
for (auto& child : node.children) { for (auto& child : node.children) {
drawglTFNode(commandBuffer, child); drawglTFNode(commandBuffer, child);
@ -262,7 +285,8 @@ public:
buffer = &glTFImage.image[0]; buffer = &glTFImage.image[0];
bufferSize = glTFImage.image.size(); bufferSize = glTFImage.image.size();
} }
model.images[i].fromBuffer(buffer, bufferSize, VK_FORMAT_R8G8B8A8_UNORM, glTFImage.width, glTFImage.height, vulkanDevice, queue); // Load texture from image buffer
model.images[i].texture.fromBuffer(buffer, bufferSize, VK_FORMAT_R8G8B8A8_UNORM, glTFImage.width, glTFImage.height, vulkanDevice, queue);
} }
} }
@ -334,12 +358,12 @@ public:
// In glTF this is done via accessors and buffer views // In glTF this is done via accessors and buffer views
if (glTFNode.mesh > -1) { if (glTFNode.mesh > -1) {
const tinygltf::Mesh mesh = glTFModel.meshes[glTFNode.mesh]; const tinygltf::Mesh mesh = glTFModel.meshes[glTFNode.mesh];
uint32_t indexStart = static_cast<uint32_t>(indexBuffer.size());
uint32_t vertexStart = static_cast<uint32_t>(vertexBuffer.size());
uint32_t indexCount = 0;
// Iterate through all primitives of this node's mesh // Iterate through all primitives of this node's mesh
for (size_t i = 0; i < mesh.primitives.size(); i++) { for (size_t i = 0; i < mesh.primitives.size(); i++) {
const tinygltf::Primitive& primitive = mesh.primitives[i]; const tinygltf::Primitive& glTFPrimitive = mesh.primitives[i];
uint32_t firstIndex = static_cast<uint32_t>(indexBuffer.size());
uint32_t vertexStart = static_cast<uint32_t>(vertexBuffer.size());
uint32_t indexCount = 0;
// Vertices // Vertices
{ {
const float* positionBuffer = nullptr; const float* positionBuffer = nullptr;
@ -348,22 +372,22 @@ public:
size_t vertexCount = 0; size_t vertexCount = 0;
// Get buffer data for vertex normals // Get buffer data for vertex normals
if (primitive.attributes.find("POSITION") != primitive.attributes.end()) { if (glTFPrimitive.attributes.find("POSITION") != glTFPrimitive.attributes.end()) {
const tinygltf::Accessor& accessor = glTFModel.accessors[primitive.attributes.find("POSITION")->second]; const tinygltf::Accessor& accessor = glTFModel.accessors[glTFPrimitive.attributes.find("POSITION")->second];
const tinygltf::BufferView& view = glTFModel.bufferViews[accessor.bufferView]; const tinygltf::BufferView& view = glTFModel.bufferViews[accessor.bufferView];
positionBuffer = reinterpret_cast<const float*>(&(glTFModel.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); positionBuffer = reinterpret_cast<const float*>(&(glTFModel.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
vertexCount = accessor.count; vertexCount = accessor.count;
} }
// Get buffer data for vertex normals // Get buffer data for vertex normals
if (primitive.attributes.find("NORMAL") != primitive.attributes.end()) { if (glTFPrimitive.attributes.find("NORMAL") != glTFPrimitive.attributes.end()) {
const tinygltf::Accessor& accessor = glTFModel.accessors[primitive.attributes.find("NORMAL")->second]; const tinygltf::Accessor& accessor = glTFModel.accessors[glTFPrimitive.attributes.find("NORMAL")->second];
const tinygltf::BufferView& view = glTFModel.bufferViews[accessor.bufferView]; const tinygltf::BufferView& view = glTFModel.bufferViews[accessor.bufferView];
normalsBuffer = reinterpret_cast<const float*>(&(glTFModel.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); normalsBuffer = reinterpret_cast<const float*>(&(glTFModel.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
} }
// Get buffer data for vertex texture coordinates // Get buffer data for vertex texture coordinates
// glTF supports multiple sets, we only load the first one // glTF supports multiple sets, we only load the first one
if (primitive.attributes.find("TEXCOORD_0") != primitive.attributes.end()) { if (glTFPrimitive.attributes.find("TEXCOORD_0") != glTFPrimitive.attributes.end()) {
const tinygltf::Accessor& accessor = glTFModel.accessors[primitive.attributes.find("TEXCOORD_0")->second]; const tinygltf::Accessor& accessor = glTFModel.accessors[glTFPrimitive.attributes.find("TEXCOORD_0")->second];
const tinygltf::BufferView& view = glTFModel.bufferViews[accessor.bufferView]; const tinygltf::BufferView& view = glTFModel.bufferViews[accessor.bufferView];
texCoordsBuffer = reinterpret_cast<const float*>(&(glTFModel.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); texCoordsBuffer = reinterpret_cast<const float*>(&(glTFModel.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
} }
@ -374,17 +398,21 @@ public:
vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f); vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f);
vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f))); vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f)));
vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f); vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f);
vert.color = glm::vec3(1.0f);
// Flip Y-Axis
vert.pos.y *= -1.0f;
vertexBuffer.push_back(vert); vertexBuffer.push_back(vert);
} }
} }
// Indices // Indices
{ {
const tinygltf::Accessor& accessor = glTFModel.accessors[primitive.indices]; const tinygltf::Accessor& accessor = glTFModel.accessors[glTFPrimitive.indices];
const tinygltf::BufferView& bufferView = glTFModel.bufferViews[accessor.bufferView]; const tinygltf::BufferView& bufferView = glTFModel.bufferViews[accessor.bufferView];
const tinygltf::Buffer& buffer = glTFModel.buffers[bufferView.buffer]; const tinygltf::Buffer& buffer = glTFModel.buffers[bufferView.buffer];
indexCount += static_cast<uint32_t>(accessor.count); indexCount += static_cast<uint32_t>(accessor.count);
// glTF supports different component types of indices
switch (accessor.componentType) { switch (accessor.componentType) {
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
uint32_t* buf = new uint32_t[accessor.count]; uint32_t* buf = new uint32_t[accessor.count];
@ -415,9 +443,12 @@ public:
return; return;
} }
} }
Primitive primitive{};
primitive.firstIndex = firstIndex;
primitive.indexCount = indexCount;
primitive.materialIndex = glTFPrimitive.material;
node.mesh.primitives.push_back(primitive);
} }
node.firstIndex = indexStart;
node.indexCount = indexCount;
} }
if (parent) { if (parent) {
@ -548,76 +579,54 @@ public:
void loadAssets() void loadAssets()
{ {
loadglTF(getAssetPath() + "models/voyager/voyager.gltf"); loadglTF(getAssetPath() + "models/voyager/voyager.gltf");
textures.colorMap.loadFromFile(getAssetPath() + "models/voyager/voyager_rgba_unorm.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue);
} }
void setupDescriptorPool() void setupDescriptors()
{ {
// Example uses one ubo and one combined image sampler /*
std::vector<VkDescriptorPoolSize> poolSizes = This sample uses separate descriptor sets (and layouts) for the matrices and materials (textures)
{ */
std::vector<VkDescriptorPoolSize> poolSizes = {
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1), // One combined image sampler per model image/texture
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast<uint32_t>(model.images.size())),
}; };
// One set for matrices and one per model image/texture
VkDescriptorPoolCreateInfo descriptorPoolInfo = const uint32_t maxSetCount = static_cast<uint32_t>(model.images.size()) + 1;
vks::initializers::descriptorPoolCreateInfo( VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount);
static_cast<uint32_t>(poolSizes.size()),
poolSizes.data(),
1);
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
}
void setupDescriptorSetLayout() // Descriptor set layout for passing matrices
{ VkDescriptorSetLayoutBinding setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0);
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(&setLayoutBinding, 1);
{ VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.matrices));
// Binding 0 : Vertex shader uniform buffer // Descriptor set layout for passing material textures
vks::initializers::descriptorSetLayoutBinding( setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0);
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures));
VK_SHADER_STAGE_VERTEX_BIT, // Pipeline layout using both descriptor sets (set 0 = matrices, set 1 = material)
0), std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayouts.matrices, descriptorSetLayouts.textures };
// Binding 1 : Fragment shader combined sampler VkPipelineLayoutCreateInfo pipelineLayoutCI= vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
vks::initializers::descriptorSetLayoutBinding( VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout));
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_SHADER_STAGE_FRAGMENT_BIT,
1),
};
VkDescriptorSetLayoutCreateInfo descriptorLayout = // Descriptor set for scene matrices
vks::initializers::descriptorSetLayoutCreateInfo( VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1);
setLayoutBindings.data(),
static_cast<uint32_t>(setLayoutBindings.size()));
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
vks::initializers::pipelineLayoutCreateInfo(
&descriptorSetLayout,
1);
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout));
}
void setupDescriptorSet()
{
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor);
std::vector<VkWriteDescriptorSet> writeDescriptorSets = { vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
// Binding 0 : Vertex shader uniform buffer // Descriptor sets for materials
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), for (auto& image : model.images) {
// Binding 1 : Color map const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1);
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.colorMap.descriptor) VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet));
}; VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(image.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &image.texture.descriptor);
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
}
} }
void preparePipelines() void preparePipelines()
{ {
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE);
VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE, 0); VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0);
VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE);
VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI); VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentStateCI);
VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL);
@ -717,10 +726,8 @@ public:
VulkanExampleBase::prepare(); VulkanExampleBase::prepare();
loadAssets(); loadAssets();
prepareUniformBuffers(); prepareUniformBuffers();
setupDescriptorSetLayout(); setupDescriptors();
preparePipelines(); preparePipelines();
setupDescriptorPool();
setupDescriptorSet();
buildCommandBuffers(); buildCommandBuffers();
prepared = true; prepared = true;
} }