add vertex buffers
This commit is contained in:
parent
494e455bf4
commit
115e92ec23
2 changed files with 146 additions and 28 deletions
157
main.cpp
157
main.cpp
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue