Author SHA1 Message Date
Emil Shanaty a701036dc8 does not work 2025-03-27 15:07:08 +03:00
Emil Shanaty 7cde1b9218 new commit 2025-03-22 12:18:33 +03:00
3 changed files with 428 additions and 367 deletions
-1
View File
@@ -1,7 +1,6 @@
#version 450
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
+16 -20
View File
@@ -1,30 +1,26 @@
#version 450
<<<<<<< Updated upstream
=======
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 proj;
} ubo;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inUV;
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 projection;
} ubo;
>>>>>>> Stashed changes
layout(location = 0) out vec3 fragColor;
vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);
vec3 colors[3] = vec3[] (
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
void main() {
gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPosition, 1.0);
fragColor = clamp(inNormal, vec3(0.0), vec3(1.0));
<<<<<<< Updated upstream
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
=======
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
fragColor = inNormal * 0.5 + 0.5;
>>>>>>> Stashed changes
}
+412 -346
View File
@@ -18,7 +18,6 @@
#include <filesystem>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "tiny_gltf.h"
using namespace tinygltf;
@@ -28,12 +27,79 @@ struct Vertex {
glm::vec3 normal;
glm::vec2 uv;
};
<<<<<<< Updated upstream
std::vector<Vertex> vertices;
std::vector<uint32_t> indices;
VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory;
VkBuffer indexBuffer;
VkDeviceMemory indexBufferMemory;
Model model;
void loadModel() {
TinyGLTF loader;
std::string err;
std::string warn;
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, "C:/Users/emil2/OneDrive/Desktop/Coding/Study/CGDG/vulkan_tweaking/models/Models/BrainStem/glTF/BrainStem.gltf");
if (!warn.empty()) {
std::cout << "GLTF warning: " << warn << std::endl;
}
if (!err.empty()) {
std::cerr << "GLTF error: " << err << std::endl;
}
if (!ret) {
throw std::runtime_error("Failed to load GLTF: " + err);
}
// Ïîëó÷åíèå äàííûõ âåðøèí è èíäåêñîâ
for (const auto& mesh : model.meshes) {
for (const auto& primitive : mesh.primitives) {
// Âåðøèíû
const auto& positionAccessor = model.accessors[primitive.attributes.at("POSITION")];
const auto& positionView = model.bufferViews[positionAccessor.bufferView];
const auto& positionBuffer = model.buffers[positionView.buffer];
const float* positions = reinterpret_cast<const float*>(&positionBuffer.data[positionView.byteOffset + positionAccessor.byteOffset]);
// Íîðìàëè (åñëè åñòü)
const auto& normalAccessor = model.accessors[primitive.attributes.at("NORMAL")];
const auto& normalView = model.bufferViews[normalAccessor.bufferView];
const auto& normalBuffer = model.buffers[normalView.buffer];
const float* normals = reinterpret_cast<const float*>(&normalBuffer.data[normalView.byteOffset + normalAccessor.byteOffset]);
// Èíäåêñû
const auto& indexAccessor = model.accessors[primitive.indices];
const auto& indexView = model.bufferViews[indexAccessor.bufferView];
const auto& indexBuffer = model.buffers[indexView.buffer];
const uint16_t* indicesSrc = reinterpret_cast<const uint16_t*>(&indexBuffer.data[indexView.byteOffset + indexAccessor.byteOffset]);
// Çàïîëíåíèå âåêòîðîâ
for (size_t i = 0; i < positionAccessor.count; i++) {
Vertex vertex{};
vertex.pos = glm::vec3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
vertex.normal = glm::vec3(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]);
vertices.push_back(vertex);
}
for (size_t i = 0; i < indexAccessor.count; i++) {
indices.push_back(indicesSrc[i]);
}
}
}
}
=======
struct UniformBufferObject {
glm::mat4 model;
glm::mat4 view;
glm::mat4 proj;
alignas(16) glm::mat4 model;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj;
};
>>>>>>> Stashed changes
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
@@ -145,32 +211,35 @@ class HelloTriangleApplication {
private:
const int WIDTH = 800;
const int HEIGHT = 600;
const std::string appName = "Vulkan on MacOS";
const std::string appName = "Vulkan on Windows";
const std::string engineName = "The Best Engine";
const std::vector<const char*> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
"VK_KHR_portability_subset",
};
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
std::vector<std::vector<Vertex>> vertices;
std::vector<std::vector<uint32_t>> indices;
std::vector<glm::mat4x4> worldMatrices;
glm::mat4x4 viewMatrix;
glm::mat4x4 projectionMatrix;
std::vector<VkBuffer> vertexBuffer;
std::vector<VkDeviceMemory> vertexBufferMemory;
std::vector<VkBuffer> indexBuffer;
std::vector<VkDeviceMemory> indexBufferMemory;
std::vector<Vertex> vertices;
std::vector<uint32_t> indices;
<<<<<<< Updated upstream
VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory;
=======
VkBuffer vertexBuffer = VK_NULL_HANDLE;
VkDeviceMemory vertexBufferMemory = VK_NULL_HANDLE;
VkBuffer indexBuffer = VK_NULL_HANDLE;
VkDeviceMemory indexBufferMemory = VK_NULL_HANDLE;
>>>>>>> Stashed changes
Model model;
// Â êëàññå HelloTriangleApplication
std::vector<VkBuffer> uniformBuffers;
std::vector<VkDeviceMemory> uniformBuffersMemory;
std::vector<void*> uniformBuffersMapped;
VkDescriptorSetLayout descriptorSetLayout;
VkDescriptorPool descriptorPool;
std::vector<VkDescriptorSet> descriptorSets;
#ifdef NDEBUG
const bool enableValidationLayers = false;
@@ -193,9 +262,6 @@ private:
VkExtent2D swapChainExtent = {};
std::vector<VkImageView> swapChainImageViews;
VkRenderPass renderPass = VK_NULL_HANDLE;
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
std::vector<VkDescriptorSet> descriptorSets;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
VkPipeline graphicsPipeline = VK_NULL_HANDLE;
std::vector<VkFramebuffer> swapChainFramebuffers;
@@ -233,17 +299,23 @@ private:
createSurface();
pickPhysicalDevice();
createLogicalDevice();
loadModel(); // createVertexBuffer()
createVertexBuffer();
<<<<<<< Updated upstream
loadModel();
=======
loadModel(); // Äîëæåí áûòü âûçâàí ïåðåä createVertexBuffer()
createIndexBuffer();
createUniformBuffers();
createSwapChain();
createImageViews();
createRenderPass();
createUniformBuffers(); // Äîáàâèòü ýòó ñòðîêó
createDescriptorSetLayout();
createUniformBuffers();
createDescriptorPool();
createDescriptorSets();
createGraphicsPipeline();
>>>>>>> Stashed changes
createVertexBuffer();
createIndexBuffer();
createSwapChain();
createImageViews();
createRenderPass();
createFramebuffers();
createCommandPool();
createCommandBuffer();
@@ -271,86 +343,99 @@ private:
return true;
}
private:
void processNodes(const std::vector<int> &nodes, glm::mat4x4 globalTransform){
for (const auto& node_id : nodes) {
auto node = model.nodes[node_id];
<<<<<<< Updated upstream
<<<<<<< Updated upstream
=======
=======
void createDescriptorPool() {
VkDescriptorPoolSize poolSize{};
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize.descriptorCount = static_cast<uint32_t>(swapChainImages.size());
glm::mat4x4 localTransform(1);
if (node.translation.size() == 3) {
localTransform = glm::translate(localTransform, glm::vec3(glm::make_vec3(node.translation.data())));
}
if (node.rotation.size() == 4) {
glm::quat q = glm::make_quat(node.rotation.data());
localTransform *= glm::mat4(q);
}
if (node.scale.size() == 3) {
localTransform = glm::scale(localTransform, glm::vec3(glm::make_vec3(node.scale.data())));
}
if (node.matrix.size() == 16) {
localTransform = glm::make_mat4x4(node.matrix.data());
};
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = 1;
poolInfo.pPoolSizes = &poolSize;
poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());
auto transform = globalTransform*localTransform;
if (node.mesh > -1) {
loadMesh(model.meshes[node.mesh]);
worldMatrices.push_back(transform);
}
if (node.camera == 0) {
viewMatrix = glm::inverse(transform);
}
processNodes(node.children, transform);
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor pool!");
}
};
void loadMesh(const Mesh& mesh) {
std::cout << "Load mesh\n";
std::vector <Vertex> vb;
std::vector<uint32_t> ib;
for (const auto& primitive : mesh.primitives) {
//
const auto& positionAccessor = model.accessors[primitive.attributes.at("POSITION")];
const auto& positionView = model.bufferViews[positionAccessor.bufferView];
const auto& positionBuffer = model.buffers[positionView.buffer];
const float* positions = reinterpret_cast<const float*>(&positionBuffer.data[positionView.byteOffset + positionAccessor.byteOffset]);
// ( )
const auto& normalAccessor = model.accessors[primitive.attributes.at("NORMAL")];
const auto& normalView = model.bufferViews[normalAccessor.bufferView];
const auto& normalBuffer = model.buffers[normalView.buffer];
const float* normals = reinterpret_cast<const float*>(&normalBuffer.data[normalView.byteOffset + normalAccessor.byteOffset]);
//
const auto& indexAccessor = model.accessors[primitive.indices];
const auto& indexView = model.bufferViews[indexAccessor.bufferView];
const auto& indexBuffer = model.buffers[indexView.buffer];
const uint16_t* indicesSrc = reinterpret_cast<const uint16_t*>(&indexBuffer.data[indexView.byteOffset + indexAccessor.byteOffset]);
//
for (size_t i = 0; i < positionAccessor.count; i++) {
Vertex vertex{};
vertex.pos = glm::vec3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
vertex.normal = glm::vec3(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]);
vb.push_back(vertex);
}
for (size_t i = 0; i < indexAccessor.count; i++) {
ib.push_back(indicesSrc[i]);
}
}
vertices.push_back(vb);
indices.push_back(ib);
}
void createDescriptorSets() {
std::vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
allocInfo.pSetLayouts = layouts.data();
descriptorSets.resize(swapChainImages.size());
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!");
}
for (size_t i = 0; i < swapChainImages.size(); i++) {
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UniformBufferObject);
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSets[i];
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
}
}
void createDescriptorSetLayout() {
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = 1;
layoutInfo.pBindings = &uboLayoutBinding;
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor set layout!");
}
}
void createUniformBuffers() {
VkDeviceSize bufferSize = sizeof(UniformBufferObject);
uniformBuffers.resize(swapChainImages.size());
uniformBuffersMemory.resize(swapChainImages.size());
uniformBuffersMapped.resize(swapChainImages.size());
for (size_t i = 0; i < swapChainImages.size(); i++) {
createBuffer(
bufferSize,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
uniformBuffers[i],
uniformBuffersMemory[i]
);
vkMapMemory(device, uniformBuffersMemory[i], 0, bufferSize, 0, &uniformBuffersMapped[i]);
}
}
>>>>>>> Stashed changes
void loadModel() {
TinyGLTF loader;
std::string err;
std::string warn;
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, "models/Models/BrainStem/glTF/BrainStem.gltf");
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, "C:/Users/emil2/OneDrive/Desktop/Coding/Study/CGDG/vulkan_tweaking/models/Models/BrainStem/glTF/BrainStem.gltf");
if (!warn.empty()) {
std::cout << "GLTF warning: " << warn << std::endl;
@@ -364,76 +449,180 @@ private:
throw std::runtime_error("Failed to load GLTF: " + err);
}
viewMatrix = glm::mat4x4(1);
projectionMatrix = glm::mat4x4(1);
//glm::perspectiveFovLH(60.f, static_cast<float>(WIDTH), static_cast<float>(HEIGHT), 0.001f, 1000.f);
if (model.cameras.size() > 0)
{
const auto& camera = model.cameras[0];
if (camera.type == "perspective")
{
projectionMatrix = glm::perspectiveRH(camera.perspective.yfov, camera.perspective.aspectRatio, camera.perspective.znear, camera.perspective.zfar);
}
if (camera.type == "orthographic")
{
auto right = camera.orthographic.xmag / 2.f;
auto left = - right;
auto top = camera.orthographic.ymag / 2.f;
auto bottom = - top;
projectionMatrix = glm::orthoRH(left, right, bottom, top, camera.orthographic.znear, camera.orthographic.zfar);
// Î÷èñòèì ïðåäûäóùèå äàííûå
vertices.clear();
indices.clear();
for (const auto& mesh : model.meshes) {
for (const auto& primitive : mesh.primitives) {
// Ñíà÷àëà îáðàáîòàåì POSITION, ÷òîáû ñîçäàòü vertices
for (const auto& attribute : primitive.attributes) {
if (attribute.first == "POSITION") {
const tinygltf::Accessor& accessor = model.accessors[attribute.second];
const tinygltf::BufferView& bufferView = model.bufferViews[accessor.bufferView];
const tinygltf::Buffer& buffer = model.buffers[bufferView.buffer];
const float* vertexData = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
<<<<<<< Updated upstream
// Çàïîëíÿåì vertices
vertices.resize(accessor.count); // Âàæíî: çàäàåì ðàçìåð çàðàíåå
for (size_t i = 0; i < accessor.count; ++i) {
vertices[i].pos = glm::vec3(
vertexData[i * 3 + 0],
vertexData[i * 3 + 1],
vertexData[i * 3 + 2]
);
}
break; // Âûõîäèì ïîñëå îáðàáîòêè POSITION
}
}
// Çàòåì îáðàáàòûâàåì îñòàëüíûå àòðèáóòû (NORMAL, TEXCOORD_0)
for (const auto& attribute : primitive.attributes) {
if (attribute.first == "NORMAL") {
const tinygltf::Accessor& accessor = model.accessors[attribute.second];
const tinygltf::BufferView& bufferView = model.bufferViews[accessor.bufferView];
const tinygltf::Buffer& buffer = model.buffers[bufferView.buffer];
const float* normalData = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
// Ïðîâåðÿåì, ÷òî vertices èìååò äîñòàòî÷íûé ðàçìåð
if (vertices.size() < accessor.count) {
throw std::runtime_error("Mismatch between POSITION and NORMAL counts");
}
for (size_t i = 0; i < accessor.count; ++i) {
vertices[i].normal = glm::vec3(
normalData[i * 3 + 0],
normalData[i * 3 + 1],
normalData[i * 3 + 2]
);
}
}
else if (attribute.first == "TEXCOORD_0") {
const tinygltf::Accessor& accessor = model.accessors[attribute.second];
const tinygltf::BufferView& bufferView = model.bufferViews[accessor.bufferView];
const tinygltf::Buffer& buffer = model.buffers[bufferView.buffer];
const float* uvData = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
for (size_t i = 0; i < accessor.count; ++i) {
vertices[i].uv = glm::vec2(
uvData[i * 2 + 0],
uvData[i * 2 + 1]
);
}
}
=======
// Íîðìàëè (åñëè åñòü)
const auto& normalAccessor = model.accessors[primitive.attributes.at("NORMAL")];
const auto& normalView = model.bufferViews[normalAccessor.bufferView];
const auto& normalBuffer = model.buffers[normalView.buffer];
const float* normals = reinterpret_cast<const float*>(&normalBuffer.data[normalView.byteOffset + normalAccessor.byteOffset]);
// Èíäåêñû
/*
const auto& indexAccessor = model.accessors[primitive.indices];
const auto& indexView = model.bufferViews[indexAccessor.bufferView];
const auto& indexBuffer = model.buffers[indexView.buffer];
const uint16_t* indicesSrc = reinterpret_cast<const uint16_t*>(&indexBuffer.data[indexView.byteOffset + indexAccessor.byteOffset]);
*/
const auto& indexAccessor = model.accessors[primitive.indices];
const auto& indexView = model.bufferViews[indexAccessor.bufferView];
const auto& indexBuffer = model.buffers[indexView.buffer];
// Check component type
if (indexAccessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
const uint16_t* indicesSrc = reinterpret_cast<const uint16_t*>(&indexBuffer.data[indexView.byteOffset + indexAccessor.byteOffset]);
for (size_t i = 0; i < indexAccessor.count; i++) {
indices.push_back(indicesSrc[i]);
}
}
else if (indexAccessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) {
const uint32_t* indicesSrc = reinterpret_cast<const uint32_t*>(&indexBuffer.data[indexView.byteOffset + indexAccessor.byteOffset]);
for (size_t i = 0; i < indexAccessor.count; i++) {
indices.push_back(indicesSrc[i]);
}
}
else {
throw std::runtime_error("Unsupported index type");
}
// Çàïîëíåíèå âåêòîðîâ
for (size_t i = 0; i < positionAccessor.count; i++) {
Vertex vertex{};
vertex.pos = glm::vec3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
vertex.normal = glm::vec3(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]);
vertices.push_back(vertex);
}
/*
for (size_t i = 0; i < indexAccessor.count; i++) {
indices.push_back(indicesSrc[i]);
>>>>>>> Stashed changes
}
*/
// Check if "NORMAL" exists
if (primitive.attributes.find("NORMAL") == primitive.attributes.end()) {
throw std::runtime_error("Model missing NORMAL attribute");
}
// Similarly for "TEXCOORD_0" if using UVs
// Determine index type
VkIndexType indexType = (model.accessors[model.meshes[0].primitives[0].indices].componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
? VK_INDEX_TYPE_UINT16
: VK_INDEX_TYPE_UINT32;
// Update the binding call
//vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, indexType);
}
}
projectionMatrix[1][1] *= -1.0f;
processNodes(model.scenes[0].nodes, glm::mat4x4(1));
<<<<<<< Updated upstream
=======
std::cout << "Loaded " << vertices.size() << " vertices, "
<< indices.size() << " indices" << std::endl;
>>>>>>> Stashed changes
}
>>>>>>> Stashed changes
void createVertexBuffer() {
if (vertices.empty()) {
throw std::runtime_error("No vertices loaded!");
}
vertexBuffer.resize(vertices.size());
vertexBufferMemory.resize(vertices.size());
VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(vertices[0]) * vertices.size();
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
for (size_t i = 0; i < vertices.size(); i++)
{
auto vb = vertices[i];
std::cout << "Vertex buffer: " << vb.size() << "\n";
VkDeviceSize bufferSize = sizeof(Vertex) * vb.size();
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = bufferSize;
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
// this->, device
if (vkCreateBuffer(device, &bufferInfo, nullptr, &vertexBuffer[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to create vertex buffer!");
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, vertexBuffer[i], &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if (vkAllocateMemory(device, &allocInfo, nullptr, &vertexBufferMemory[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate vertex buffer memory!");
}
vkBindBufferMemory(device, vertexBuffer[i], vertexBufferMemory[i], 0);
void* data;
vkMapMemory(device, vertexBufferMemory[i], 0, bufferInfo.size, 0, &data);
memcpy(data, vb.data(), bufferInfo.size);
vkUnmapMemory(device, vertexBufferMemory[i]);
// Óáðàòü this->, òàê êàê device óæå ÷ëåí êëàññà
if (vkCreateBuffer(device, &bufferInfo, nullptr, &vertexBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create vertex buffer!");
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, vertexBuffer, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if (vkAllocateMemory(device, &allocInfo, nullptr, &vertexBufferMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate vertex buffer memory!");
}
vkBindBufferMemory(device, vertexBuffer, vertexBufferMemory, 0);
void* data;
vkMapMemory(device, vertexBufferMemory, 0, bufferInfo.size, 0, &data);
memcpy(data, vertices.data(), bufferInfo.size);
vkUnmapMemory(device, vertexBufferMemory);
}
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
VkPhysicalDeviceMemoryProperties memProperties;
@@ -685,11 +874,6 @@ private:
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
createInfo.enabledLayerCount = 0;
VkPhysicalDeviceSynchronization2Features syncFeatures{};
syncFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES;
syncFeatures.synchronization2 = true;
createInfo.pNext = &syncFeatures;
if (enableValidationLayers) {
createInfo.enabledLayerCount = validationLayers.size();
createInfo.ppEnabledLayerNames = validationLayers.data();
@@ -706,133 +890,36 @@ private:
throw std::runtime_error("No indices loaded!");
}
indexBuffer.resize(indices.size());
indexBufferMemory.resize(indices.size());
for (size_t i=0; i<indices.size(); i++)
{
auto ib = indices[i];
VkDeviceSize bufferSize = sizeof(uint32_t) * ib.size();
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = bufferSize;
bufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(device, &bufferInfo, nullptr, &indexBuffer[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to create index buffer!");
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, indexBuffer[i], &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if (vkAllocateMemory(device, &allocInfo, nullptr, &indexBufferMemory[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate index buffer memory!");
}
vkBindBufferMemory(device, indexBuffer[i], indexBufferMemory[i], 0);
void* data;
vkMapMemory(device, indexBufferMemory[i], 0, bufferInfo.size, 0, &data);
memcpy(data, ib.data(), bufferInfo.size);
vkUnmapMemory(device, indexBufferMemory[i]);
}
}
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = usage;
bufferInfo.size = sizeof(indices[0]) * indices.size();
bufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create buffer!");
if (vkCreateBuffer(device, &bufferInfo, nullptr, &indexBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create index buffer!");
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
vkGetBufferMemoryRequirements(device, indexBuffer, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate buffer memory!");
}
vkBindBufferMemory(device, buffer, bufferMemory, 0);
}
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
void createUniformBuffers() {
VkDeviceSize bufferSize = sizeof(UniformBufferObject);
uniformBuffers.resize(indices.size());
uniformBuffersMemory.resize(indices.size());
uniformBuffersMapped.resize(indices.size());
for (size_t i = 0; i < indices.size(); i++) {
createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]);
vkMapMemory(device, uniformBuffersMemory[i], 0, bufferSize, 0, &uniformBuffersMapped[i]);
}
}
void createDescriptorPool() {
VkDescriptorPoolSize poolSize{};
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize.descriptorCount = 1;
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = 1;
poolInfo.pPoolSizes = &poolSize;
poolInfo.maxSets = 1;
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor pool!");
}
}
void createDescriptorSets() {
std::cout << "createDescriptorSets: " << indices.size() << "\n";
std::vector<VkDescriptorSetLayout> layouts(indices.size(), descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = indices.size();
allocInfo.pSetLayouts = layouts.data();
descriptorSets.resize(indices.size());
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!");
if (vkAllocateMemory(device, &allocInfo, nullptr, &indexBufferMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate index buffer memory!");
}
for (size_t i = 0; i < indices.size(); i++) {
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UniformBufferObject);
vkBindBufferMemory(device, indexBuffer, indexBufferMemory, 0);
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSets[i];
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
}
void* data;
vkMapMemory(device, indexBufferMemory, 0, bufferInfo.size, 0, &data);
memcpy(data, indices.data(), bufferInfo.size);
vkUnmapMemory(device, indexBufferMemory);
}
void createSwapChain() {
@@ -957,24 +1044,6 @@ private:
}
}
void createDescriptorSetLayout() {
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr;
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = 1;
layoutInfo.pBindings = &uboLayoutBinding;
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor set layout!");
}
}
void createGraphicsPipeline() {
auto vertShaderCode = readFile("shaders/vert.spv");
auto fragShaderCode = readFile("shaders/frag.spv");
@@ -982,6 +1051,11 @@ private:
VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout; // Äîáàâèòü
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
@@ -1045,7 +1119,7 @@ private:
rasterizerState.polygonMode = VK_POLYGON_MODE_FILL;
rasterizerState.lineWidth = 1.0f;
rasterizerState.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizerState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; //
rasterizerState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; // Èñïðàâëåíî íà ïðàâèëüíîå íàïðàâëåíèå
rasterizerState.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisamplingState{};
@@ -1078,8 +1152,7 @@ private:
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
pipelineLayoutInfo.setLayoutCount = 0;
pipelineLayoutInfo.pushConstantRangeCount = 0;
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
@@ -1090,7 +1163,7 @@ private:
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = shaderStages.size();
pipelineInfo.pStages = shaderStages.data();
pipelineInfo.pVertexInputState = &vertexInputInfo; // vertex input
pipelineInfo.pVertexInputState = &vertexInputInfo; // Èñïðàâëåííûé vertex input
pipelineInfo.pInputAssemblyState = &inputAssemblyState;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizerState;
@@ -1182,6 +1255,13 @@ private:
throw std::runtime_error("failed to begin recording command buffer!");
}
vkCmdBindDescriptorSets(
commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout,
0, 1, &descriptorSets[imageIndex], 0, nullptr
);
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass;
@@ -1195,6 +1275,12 @@ private:
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
VkBuffer vertexBuffers[] = { vertexBuffer };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16);
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
@@ -1209,16 +1295,7 @@ private:
scissor.extent = swapChainExtent;
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
// TODO: Add VertexBUffer binding
for (size_t i=0; i<indices.size(); i++)
{
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer[i], offsets);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer[i], 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[i], 0, nullptr);
vkCmdDraw(commandBuffer, indices[i].size(), 1, 0, 0);
}
vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
vkCmdEndRenderPass(commandBuffer);
@@ -1227,18 +1304,6 @@ private:
}
}
void updateUniformBuffer() {
for (size_t i=0; i<indices.size(); i++)
{
UniformBufferObject ubo{};
ubo.model = worldMatrices[i];
ubo.view = viewMatrix;
ubo.proj = projectionMatrix;
memcpy(uniformBuffersMapped[i], &ubo, sizeof(ubo));
}
}
void drawFrame() {
vkWaitForFences(device, 1, &inFlightFence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &inFlightFence);
@@ -1246,8 +1311,6 @@ private:
uint32_t imageIndex;
vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
updateUniformBuffer();
vkResetCommandBuffer(commandBuffer, 0);
recordCommandBuffer(commandBuffer, imageIndex);
@@ -1281,6 +1344,18 @@ private:
presentInfo.pSwapchains = swapChains.data();
presentInfo.pImageIndices = &imageIndex;
static auto startTime = std::chrono::high_resolution_clock::now();
auto currentTime = std::chrono::high_resolution_clock::now();
float time = std::chrono::duration<float>(currentTime - startTime).count();
UniformBufferObject ubo{};
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float)swapChainExtent.height, 0.1f, 10.0f);
ubo.proj[1][1] *= -1; // GLM uses OpenGL's clip space, so flip Y
memcpy(uniformBuffersMapped[imageIndex], &ubo, sizeof(ubo));
vkQueuePresentKHR(presentQueue, &presentInfo);
}
@@ -1292,22 +1367,10 @@ private:
}
void cleanup() {
for (auto vb : vertexBuffer)
{
vkDestroyBuffer(device, vb, nullptr);
}
for (auto vbm : vertexBufferMemory)
{
vkFreeMemory(device, vbm, nullptr);
}
for (auto ib : indexBuffer)
{
vkDestroyBuffer(device, ib, nullptr);
}
for (auto ibm : indexBufferMemory)
{
vkFreeMemory(device, ibm, nullptr);
}
vkDestroyBuffer(device, vertexBuffer, nullptr);
vkFreeMemory(device, vertexBufferMemory, nullptr);
vkDestroyBuffer(device, indexBuffer, nullptr);
vkFreeMemory(device, indexBufferMemory, nullptr);
vkDeviceWaitIdle(device);
vkDestroySemaphore(device, imageAvailableSemaphore, nullptr);
vkDestroySemaphore(device, renderFinishedSemaphore, nullptr);
@@ -1318,15 +1381,6 @@ private:
}
vkDestroyPipeline(device, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
for (size_t i = 0; i < indices.size(); i++) {
vkDestroyBuffer(device, uniformBuffers[i], nullptr);
vkFreeMemory(device, uniformBuffersMemory[i], nullptr);
}
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
vkDestroyRenderPass(device, renderPass, nullptr);
for (auto imageView : swapChainImageViews) {
vkDestroyImageView(device, imageView, nullptr);
@@ -1337,10 +1391,22 @@ private:
if (enableValidationLayers) {
DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
}
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
for (size_t i = 0; i < swapChainImages.size(); i++) {
vkDestroyBuffer(device, uniformBuffers[i], nullptr);
vkFreeMemory(device, uniformBuffersMemory[i], nullptr);
}
vkDestroySurfaceKHR(instance, surface, nullptr);
vkDestroyInstance(instance, nullptr);
if (vertexBuffer != VK_NULL_HANDLE) {
vkDestroyBuffer(device, vertexBuffer, nullptr);
vkFreeMemory(device, vertexBufferMemory, nullptr);
}
if (indexBuffer != VK_NULL_HANDLE) {
vkDestroyBuffer(device, indexBuffer, nullptr);
vkFreeMemory(device, indexBufferMemory, nullptr);
}
glfwDestroyWindow(window);
glfwTerminate();