add vertex buffers

This commit is contained in:
IlyaShurupov 2024-11-18 12:51:00 +03:00
parent 494e455bf4
commit 115e92ec23
2 changed files with 146 additions and 28 deletions

157
main.cpp
View file

@ -11,6 +11,8 @@
#include <cassert>
#include <chrono>
#include <glm/glm.hpp>
using TimePoint = std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>;
using TimeMs = long;
@ -20,21 +22,32 @@ TimeMs timeDeltaMs(const TimePoint& point) {
return timeDelayMs;
}
const std::vector<const char *> deviceExtensions = {
struct SwapChainSupportDetails {
VkSurfaceCapabilitiesKHR capabilities{};
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
struct Vertex {
glm::vec2 pos;
glm::vec3 color;
};
const std::vector<const char *> gDeviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
const std::vector<const char *> validationLayers = {
const std::vector<const char *> gValidationLayers = {
#ifdef NDEBUG
#else
"VK_LAYER_KHRONOS_validation"
#endif
};
struct SwapChainSupportDetails {
VkSurfaceCapabilitiesKHR capabilities{};
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
const std::vector<Vertex> vertices = {
{{0.f, -0.5f}, {1.f, 0.f, 0.f}},
{{0.5f, 0.5f}, {0.f, 1.f, 0.f}},
{{-0.5f, 0.5f}, {0.f, 0.f, 1.f}},
};
class Application {
@ -92,6 +105,10 @@ private:
createCommandBuffer();
createSynchronizationObjects();
createVertexBuffer();
allocateVertexBufferMemory();
sendVertexBufferData();
}
void mainLoop() {
@ -132,8 +149,8 @@ private:
VkInstanceCreateInfo createInfo{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &appInfo,
.enabledLayerCount = (uint32_t) validationLayers.size(),
.ppEnabledLayerNames = validationLayers.data(),
.enabledLayerCount = (uint32_t) gValidationLayers.size(),
.ppEnabledLayerNames = gValidationLayers.data(),
.enabledExtensionCount = glfwExtensionCount,
.ppEnabledExtensionNames = glfwExtensions,
};
@ -150,7 +167,7 @@ private:
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
for (const auto &requestedLayer: validationLayers) {
for (const auto &requestedLayer: gValidationLayers) {
bool presents = false;
for (auto &layer: availableLayers) {
if (strcmp(requestedLayer, layer.layerName) == 0) {
@ -213,7 +230,7 @@ private:
std::vector<VkExtensionProperties> extensions(extensionsCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionsCount, extensions.data());
for (const auto &requiredExtension: deviceExtensions) {
for (const auto &requiredExtension: gDeviceExtensions) {
bool found = false;
for (const auto &extension: extensions) {
if (strcmp(requiredExtension, extension.extensionName) == 0) {
@ -306,8 +323,8 @@ private:
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = (uint32_t) queues.size(),
.pQueueCreateInfos = queues.data(),
.enabledExtensionCount = (uint32_t) deviceExtensions.size(),
.ppEnabledExtensionNames = deviceExtensions.data(),
.enabledExtensionCount = (uint32_t) gDeviceExtensions.size(),
.ppEnabledExtensionNames = gDeviceExtensions.data(),
.pEnabledFeatures = &features,
};
@ -538,10 +555,15 @@ private:
.pDynamicStates = dynamicStates.data(),
};
auto attributes = getShaderAttributesDescriptors();
auto vertexInput = getShaderVertexInputDescription();
VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = 0,
.vertexAttributeDescriptionCount = 0,
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &vertexInput,
.vertexAttributeDescriptionCount = (uint32_t) attributes.size(),
.pVertexAttributeDescriptions = attributes.data(),
};
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo{
@ -751,6 +773,73 @@ private:
}
}
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags flags) {
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(mPhysicalDevice, &memoryProperties);
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
if (typeFilter & (1 << i) && (memoryProperties.memoryTypes[i].propertyFlags & flags) == flags) {
return i;
}
}
throw std::runtime_error("no suitable memory for vertex buffer found");
return {};
}
void allocateVertexBufferMemory() {
VkMemoryRequirements memoryRequirements;
vkGetBufferMemoryRequirements(mDevice, mVertexBuffer, &memoryRequirements);
// FIXME : use explicit memory flushing instead of coherent_bit
auto memoryFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
VkMemoryAllocateInfo allocateInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = memoryRequirements.size,
.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, memoryFlags),
};
if (vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mVertexBufferMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate vertex buffer memory");
}
vkBindBufferMemory(mDevice, mVertexBuffer, mVertexBufferMemory, 0);
}
void sendVertexBufferData() {
size_t memoryLength = vertices.size() * sizeof(vertices[0]);
void* memory;
if (vkMapMemory(mDevice, mVertexBufferMemory, 0, memoryLength, 0, &memory) != VK_SUCCESS) {
throw std::runtime_error("failed to map memory");
}
memcpy(memory, vertices.data(), memoryLength);
vkUnmapMemory(mDevice, mVertexBufferMemory);
}
void freeVertexBufferMemory() {
vkFreeMemory(mDevice, mVertexBufferMemory, nullptr);
}
void createVertexBuffer() {
VkBufferCreateInfo createInfo {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = vertices.size() * sizeof(vertices[0]),
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
if (vkCreateBuffer(mDevice, &createInfo, nullptr, &mVertexBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create vertex buffer");
}
}
void destroyVertexBuffer() {
vkDestroyBuffer(mDevice, mVertexBuffer, nullptr);
}
void populateGraphicsCommandBuffer(VkCommandBuffer commandBuffer, uint32_t swapChainImageIndex) {
VkCommandBufferBeginInfo commandBufferBeginInfo{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@ -794,7 +883,11 @@ private:
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
VkBuffer vertexBuffers[] = { mVertexBuffer };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdDraw(commandBuffer, vertices.size(), 1, 0, 0);
vkCmdEndRenderPass(commandBuffer);
@ -876,6 +969,34 @@ private:
*/
}
static VkVertexInputBindingDescription getShaderVertexInputDescription() {
return {
.binding = 0,
.stride = sizeof(Vertex),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
};
}
static std::vector<VkVertexInputAttributeDescription> getShaderAttributesDescriptors() {
std::vector<VkVertexInputAttributeDescription> out(2);
out[0] = {
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(Vertex, pos),
};
out[1] = {
.location = 1,
.binding = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(Vertex, color),
};
return out;
}
void destroySynchronizationObjects() {
vkDestroySemaphore(mDevice, mSemaphoreImageAcquired, nullptr);
vkDestroySemaphore(mDevice, mSemaphoreFramebufferDrawn, nullptr);
@ -883,6 +1004,9 @@ private:
}
void cleanup() {
freeVertexBufferMemory();
destroyVertexBuffer();
destroySynchronizationObjects();
destroyCommandPool();
@ -940,6 +1064,9 @@ private:
VkSemaphore mSemaphoreImageAcquired = VK_NULL_HANDLE;
VkSemaphore mSemaphoreFramebufferDrawn = VK_NULL_HANDLE;
VkFence mFenceCanStartNewFrame = VK_NULL_HANDLE;
VkBuffer mVertexBuffer = VK_NULL_HANDLE;
VkDeviceMemory mVertexBufferMemory = VK_NULL_HANDLE;
};
int main() {

View file

@ -1,20 +1,11 @@
#version 450
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)
);
layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 fragColor;
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
gl_Position = vec4(inPosition, 0.0, 1.0);
fragColor = inColor;
}