oracle opaque_transform,vulkan相机投影转换--Apple的学习笔记

在我上一篇博文前练习的都是2D绘图,本章开始学习3D制图。会按时间旋转的3D投影图。

对于变化的shader,UBO不是高效的方法,建议用push constants方法。我当前学习的只是UBO,所以记录下。主要有3个步骤

1.在pipeline中使用descriptor layout

2.为descriptor set 设置descriptor pool

3.在渲染过程中绑定descriptor set

关键语句:descriptorWrite.pBufferInfo = &bufferInfo; //从buffer获取数据

问题

教程中说不需要stage buffer copy到local buffer了,我一开始没有理解,主要是教程中代码也没有改。后来想明白了,其实代码有修改descriptorWrite就是说明绑定的变量从buffer直接过来。而此buffer为Uniform buffer。通过updateUniformBuffer函数实现每一帧的变化。

其实除了UBO类型的描述,教程说还有其他类型描述。搜索了vulkan的spec还真是有好多种,先了解一种吧~

运行效果

3f6f7d99d3e2

GIF 2020-1-22 14-37-13.gif

vert代码

#version 450

#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform UniformBufferObject {

mat4 model;

mat4 view;

mat4 proj;

} ubo;

layout(location = 0) in vec2 inPosition;

layout(location = 1) in vec3 inColor;

layout(location = 0) out vec3 fragColor;

void main() {

gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);

fragColor = inColor;

}

运行代码

#define GLFW_INCLUDE_VULKAN

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define GLM_FORCE_RADIANS

#include

#include

#include

const int WIDTH = 800;

const int HEIGHT = 600;

const int MAX_FRAMES_IN_FLIGHT = 2;

const std::vector validationLayers = {

"VK_LAYER_KHRONOS_validation"

};

const std::vector deviceExtensions = {

VK_KHR_SWAPCHAIN_EXTENSION_NAME

};

struct UniformBufferObject {

alignas(16) glm::mat4 model;

alignas(16) glm::mat4 view;

alignas(16) glm::mat4 proj;

};

struct Vertex {

glm::vec2 pos;

glm::vec3 color;

static VkVertexInputBindingDescription getBindingDescription()

{

VkVertexInputBindingDescription bindingDescription = {};

bindingDescription.binding = 0;

bindingDescription.stride = sizeof(Vertex);

bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

return bindingDescription;

}

static std::array getAttributeDescriptions()

{

std::array attributeDescriptions = {};

// pos,结构体的第一个参数,所以用0

attributeDescriptions[0].binding = 0;

attributeDescriptions[0].location = 0;

attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;

attributeDescriptions[0].offset = offsetof(Vertex, pos);

// color,结构体的第二个参数,所以用1

attributeDescriptions[1].binding = 0;

attributeDescriptions[1].location = 1;

attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;

attributeDescriptions[1].offset = offsetof(Vertex, color);

return attributeDescriptions;

}

};

const std::vector vertices = {

{ { -0.5f, -0.5f },{ 1.0f, 0.0f, 0.0f } },

{ { 0.5f, -0.5f },{ 0.0f, 1.0f, 0.0f } },

{ { 0.5f, 0.5f },{ 0.1f, 0.5f, 0.7f } },

{ { -0.5f, 0.5f },{ 1.0f, 1.0f, 1.0f } }

};

const std::vector indices = {

0, 1, 2, 2, 3, 0

};

#ifdef NDEBUG

const bool enableValidationLayers = false;

#else

const bool enableValidationLayers = true;

#endif

VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {

auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");

if (func != nullptr) {

return func(instance, pCreateInfo, pAllocator, pDebugMessenger);

}

else {

return VK_ERROR_EXTENSION_NOT_PRESENT;

}

}

void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) {

auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");

if (func != nullptr) {

func(instance, debugMessenger, pAllocator);

}

}

struct QueueFamilyIndices {

std::optional graphicsFamily;

std::optional presentFamily;

bool isComplete() {

return graphicsFamily.has_value() && presentFamily.has_value();

}

};

struct SwapChainSupportDetails {

VkSurfaceCapabilitiesKHR capabilities;

std::vector formats;

std::vector presentModes;

};

class HelloTriangleApplication {

public:

void run() {

initWindow();

initVulkan();

mainLoop();

cleanup();

}

private:

GLFWwindow * window;

VkInstance instance;

VkDebugUtilsMessengerEXT debugMessenger;

VkSurfaceKHR surface;

VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;

VkDevice device;

VkQueue graphicsQueue;

VkQueue presentQueue;

VkSwapchainKHR swapChain;

std::vector swapChainImages;

VkFormat swapChainImageFormat;

VkExtent2D swapChainExtent;

std::vector swapChainImageViews;

std::vector swapChainFramebuffers;

VkRenderPass renderPass;

VkPipelineLayout pipelineLayout;

VkDescriptorSetLayout descriptorSetLayout;

VkPipeline graphicsPipeline;

VkCommandPool commandPool;

std::vector commandBuffers;

std::vector imageAvailableSemaphores;

std::vector renderFinishedSemaphores;

std::vector inFlightFences;

std::vector imagesInFlight;

size_t currentFrame = 0;

bool framebufferResized = false;

VkBuffer vertexBuffer;

VkDeviceMemory vertexBufferMemory;

VkBuffer indexBuffer;

VkDeviceMemory indexBufferMemory;

std::vector uniformBuffers;

std::vector uniformBuffersMemory;

VkDescriptorPool descriptorPool;

std::vector descriptorSets;

void initWindow() {

glfwInit();

glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

//glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); 设置可以重置大小

glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); //设置可以重置大小

window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);

glfwSetFramebufferSizeCallback(window,framebufferResizeCallback);

}

static void framebufferResizeCallback(GLFWwindow* window, int width,int height)

{

//auto app = reinterpret_cast(glfwGetWindowUserPointer(window));

//app->framebufferResized = true;

}

void initVulkan() {

createInstance();

setupDebugMessenger();

createSurface();

pickPhysicalDevice();

createLogicalDevice();

createSwapChain();

createImageViews();

createRenderPass();

createDescriptorSetLayout();//new

createGraphicsPipeline();

createFramebuffers();

createCommandPool();

createVertexBuffer();

createIndexBuffer();

createUniformBuffers();//new

createDescriptorPool();//new

createDescriptorSets();//new

createCommandBuffers();

createSyncObjects();

}

void createDescriptorSets() {

std::vector layouts(swapChainImages.size(), descriptorSetLayout);

VkDescriptorSetAllocateInfo allocInfo = {};

allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;

allocInfo.descriptorPool = descriptorPool;

allocInfo.descriptorSetCount = static_cast(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; //从buffer获取数据

descriptorWrite.pImageInfo = nullptr; // Optional

descriptorWrite.pTexelBufferView = nullptr; // Optional

vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);

}

}

void createDescriptorPool() {

VkDescriptorPoolSize poolSize = {};

poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;

poolSize.descriptorCount = static_cast(swapChainImages.size());

VkDescriptorPoolCreateInfo poolInfo = {};

poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;

poolInfo.poolSizeCount = 1;

poolInfo.pPoolSizes = &poolSize;

poolInfo.maxSets = static_cast(swapChainImages.size());

if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {

throw std::runtime_error("failed to create descriptor pool!");

}

}

void updateUniformBuffer(uint32_t currentImage) {

static auto startTime = std::chrono::high_resolution_clock::now();

auto currentTime = std::chrono::high_resolution_clock::now();

float time = std::chrono::duration(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;

void* data;

vkMapMemory(device, uniformBuffersMemory[currentImage], 0, sizeof(ubo), 0, &data);

memcpy(data, &ubo, sizeof(ubo));

vkUnmapMemory(device, uniformBuffersMemory[currentImage]);

}

void createUniformBuffers() {

VkDeviceSize bufferSize = sizeof(UniformBufferObject);

uniformBuffers.resize(swapChainImages.size());

uniformBuffersMemory.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]);

}

}

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; // Optional

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!");

}

}

uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)

{

VkPhysicalDeviceMemoryProperties memProperties;

vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);

for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {

if ((typeFilter & (1 << i)) &&

(memProperties.memoryTypes[i].propertyFlags & properties) ==properties) {

return i;

}

}

}

// new function

void createIndexBuffer() {

VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();

VkBuffer stagingBuffer;

VkDeviceMemory stagingBufferMemory;

createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);

void* data;

vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);

memcpy(data, indices.data(), (size_t)bufferSize);

vkUnmapMemory(device, stagingBufferMemory);

createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);

copyBuffer(stagingBuffer, indexBuffer, bufferSize);

vkDestroyBuffer(device, stagingBuffer, nullptr);

vkFreeMemory(device, stagingBufferMemory, nullptr);

}

void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {

VkCommandBufferAllocateInfo allocInfo = {};

allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;

allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;

allocInfo.commandPool = commandPool;

allocInfo.commandBufferCount = 1;

VkCommandBuffer commandBuffer;

vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);

//recording the command buffer

VkCommandBufferBeginInfo beginInfo = {};

beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;

vkBeginCommandBuffer(commandBuffer, &beginInfo);

//copy command buffer to gpu

VkBufferCopy copyRegion = {};

copyRegion.srcOffset = 0; // Optional

copyRegion.dstOffset = 0; // Optional

copyRegion.size = size;

vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);

vkEndCommandBuffer(commandBuffer);

//execute the command buffer to complete the transfer

VkSubmitInfo submitInfo = {};

submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

submitInfo.commandBufferCount = 1;

submitInfo.pCommandBuffers = &commandBuffer;

vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);

vkQueueWaitIdle(graphicsQueue);

vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);

}

void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {

VkBufferCreateInfo bufferInfo = {};

bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;

bufferInfo.size = size;

bufferInfo.usage = usage;

bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {

throw std::runtime_error("failed to create buffer!");

}

VkMemoryRequirements memRequirements;

vkGetBufferMemoryRequirements(device, buffer, &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);

}

void createVertexBuffer()

{

VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();

VkBuffer stagingBuffer;

VkDeviceMemory stagingBufferMemory;

createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);

void* data;

vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);

// due to both are in cpu.

memcpy(data, vertices.data(), (size_t)bufferSize);

vkUnmapMemory(device, stagingBufferMemory);

createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);

copyBuffer(stagingBuffer, vertexBuffer, bufferSize);

vkDestroyBuffer(device, stagingBuffer, nullptr);

vkFreeMemory(device, stagingBufferMemory, nullptr);

}

void mainLoop() {

while (!glfwWindowShouldClose(window)) {

glfwPollEvents();

drawFrame();

}

vkDeviceWaitIdle(device);

}

// 重绘swapchain前清除

void cleanupSwapChain() {

for (auto framebuffer : swapChainFramebuffers) {

vkDestroyFramebuffer(device, framebuffer, nullptr);

}

vkDestroyPipeline(device, graphicsPipeline, nullptr);

vkDestroyPipelineLayout(device, pipelineLayout, nullptr);

vkDestroyRenderPass(device, renderPass, nullptr);

for (auto imageView : swapChainImageViews) {

vkDestroyImageView(device, imageView, nullptr);

}

for (size_t i = 0; i < swapChainImages.size(); i++) {

vkDestroyBuffer(device, uniformBuffers[i], nullptr);

vkFreeMemory(device, uniformBuffersMemory[i], nullptr);

}

vkDestroyDescriptorPool(device, descriptorPool, nullptr);

vkDestroySwapchainKHR(device, swapChain, nullptr);

}

// 重绘swapchain

void recreateSwapChain() {

int width = 0, height = 0;

while (width == 0 || height == 0) {

glfwGetFramebufferSize(window, &width, &height);

glfwWaitEvents();

}

vkDeviceWaitIdle(device);

cleanupSwapChain();

createSwapChain();

createImageViews();

createRenderPass();

createGraphicsPipeline();

createFramebuffers();

createUniformBuffers();//new

createDescriptorPool();//new

createDescriptorSets();//new

createCommandBuffers();

vkResetFences(device, 1, &inFlightFences[currentFrame]);

VkSubmitInfo submitInfo = {};

if (vkQueueSubmit(graphicsQueue, 1, &submitInfo,inFlightFences[currentFrame]) != VK_SUCCESS) {

throw std::runtime_error("failed to submit draw command buffer!");

}

}

void cleanup() {

cleanupSwapChain();

vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);

vkDestroyBuffer(device, vertexBuffer, nullptr);

vkFreeMemory(device, vertexBufferMemory, nullptr);

vkDestroyBuffer(device, indexBuffer, nullptr);

vkFreeMemory(device, indexBufferMemory, nullptr);

for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {

vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);

vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);

vkDestroyFence(device, inFlightFences[i], nullptr);

}

vkDestroyCommandPool(device, commandPool, nullptr);

vkDestroyDevice(device, nullptr);

if (enableValidationLayers) {

DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);

}

vkDestroySurfaceKHR(instance, surface, nullptr);

vkDestroyInstance(instance, nullptr);

glfwDestroyWindow(window);

glfwTerminate();

}

void createInstance() {

if (enableValidationLayers && !checkValidationLayerSupport()) {

throw std::runtime_error("validation layers requested, but not available!");

}

VkApplicationInfo appInfo = {};

appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;

appInfo.pApplicationName = "Hello Triangle";

appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);

appInfo.pEngineName = "No Engine";

appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);

appInfo.apiVersion = VK_API_VERSION_1_0;

VkInstanceCreateInfo createInfo = {};

createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;

createInfo.pApplicationInfo = &appInfo;

auto extensions = getRequiredExtensions();

createInfo.enabledExtensionCount = static_cast(extensions.size());

createInfo.ppEnabledExtensionNames = extensions.data();

VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;

if (enableValidationLayers) {

createInfo.enabledLayerCount = static_cast(validationLayers.size());

createInfo.ppEnabledLayerNames = validationLayers.data();

populateDebugMessengerCreateInfo(debugCreateInfo);

createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;

}

else {

createInfo.enabledLayerCount = 0;

createInfo.pNext = nullptr;

}

if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {

throw std::runtime_error("failed to create instance!");

}

}

void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {

createInfo = {};

createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;

createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;

createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;

createInfo.pfnUserCallback = debugCallback;

}

void setupDebugMessenger() {

if (!enableValidationLayers) return;

VkDebugUtilsMessengerCreateInfoEXT createInfo;

populateDebugMessengerCreateInfo(createInfo);

if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {

throw std::runtime_error("failed to set up debug messenger!");

}

}

void createSurface() {

if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {

throw std::runtime_error("failed to create window surface!");

}

}

void pickPhysicalDevice() {

uint32_t deviceCount = 0;

vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);

if (deviceCount == 0) {

throw std::runtime_error("failed to find GPUs with Vulkan support!");

}

std::vector devices(deviceCount);

vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());

for (const auto& device : devices) {

if (isDeviceSuitable(device)) {

physicalDevice = device;

break;

}

}

if (physicalDevice == VK_NULL_HANDLE) {

throw std::runtime_error("failed to find a suitable GPU!");

}

}

void createLogicalDevice() {

QueueFamilyIndices indices = findQueueFamilies(physicalDevice);

std::vector queueCreateInfos;

std::set uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };

float queuePriority = 1.0f;

for (uint32_t queueFamily : uniqueQueueFamilies) {

VkDeviceQueueCreateInfo queueCreateInfo = {};

queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;

queueCreateInfo.queueFamilyIndex = queueFamily;

queueCreateInfo.queueCount = 1;

queueCreateInfo.pQueuePriorities = &queuePriority;

queueCreateInfos.push_back(queueCreateInfo);

}

VkPhysicalDeviceFeatures deviceFeatures = {};

deviceFeatures.fillModeNonSolid = 1; //by apple

VkDeviceCreateInfo createInfo = {};

createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size());

createInfo.pQueueCreateInfos = queueCreateInfos.data();

createInfo.pEnabledFeatures = &deviceFeatures;

createInfo.enabledExtensionCount = static_cast(deviceExtensions.size());

createInfo.ppEnabledExtensionNames = deviceExtensions.data();

if (enableValidationLayers) {

createInfo.enabledLayerCount = static_cast(validationLayers.size());

createInfo.ppEnabledLayerNames = validationLayers.data();

}

else {

createInfo.enabledLayerCount = 0;

}

if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {

throw std::runtime_error("failed to create logical device!");

}

vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);

vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);

}

void createSwapChain() {

SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);

VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);

VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);

VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);

uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;

if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {

imageCount = swapChainSupport.capabilities.maxImageCount;

}

VkSwapchainCreateInfoKHR createInfo = {};

createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;

createInfo.surface = surface;

createInfo.minImageCount = imageCount;

createInfo.imageFormat = surfaceFormat.format;

createInfo.imageColorSpace = surfaceFormat.colorSpace;

createInfo.imageExtent = extent;

createInfo.imageArrayLayers = 1;

createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;

QueueFamilyIndices indices = findQueueFamilies(physicalDevice);

uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };

if (indices.graphicsFamily != indices.presentFamily) {

createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;

createInfo.queueFamilyIndexCount = 2;

createInfo.pQueueFamilyIndices = queueFamilyIndices;

}

else {

createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;

}

createInfo.preTransform = swapChainSupport.capabilities.currentTransform;

createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

createInfo.presentMode = presentMode;

createInfo.clipped = VK_TRUE;

createInfo.oldSwapchain = VK_NULL_HANDLE;

if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {

throw std::runtime_error("failed to create swap chain!");

}

vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);

swapChainImages.resize(imageCount);

vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());

swapChainImageFormat = surfaceFormat.format;

swapChainExtent = extent;

}

void createImageViews() {

swapChainImageViews.resize(swapChainImages.size());

for (size_t i = 0; i < swapChainImages.size(); i++) {

VkImageViewCreateInfo createInfo = {};

createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;

createInfo.image = swapChainImages[i];

createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;

createInfo.format = swapChainImageFormat;

createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;

createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;

createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;

createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;

createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;

createInfo.subresourceRange.baseMipLevel = 0;

createInfo.subresourceRange.levelCount = 1;

createInfo.subresourceRange.baseArrayLayer = 0;

createInfo.subresourceRange.layerCount = 1;

if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {

throw std::runtime_error("failed to create image views!");

}

}

}

void createRenderPass() {

VkAttachmentDescription colorAttachment = {};

colorAttachment.format = swapChainImageFormat;

colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;

colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;

colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;

colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;

colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;

colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;

colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

VkAttachmentReference colorAttachmentRef = {};

colorAttachmentRef.attachment = 0;

colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

VkSubpassDescription subpass = {};

subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;

subpass.colorAttachmentCount = 1;

subpass.pColorAttachments = &colorAttachmentRef;

VkSubpassDependency dependency = {};

dependency.srcSubpass = VK_SUBPASS_EXTERNAL;

dependency.dstSubpass = 0;

dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;

dependency.srcAccessMask = 0;

dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;

dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

VkRenderPassCreateInfo renderPassInfo = {};

renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;

renderPassInfo.attachmentCount = 1;

renderPassInfo.pAttachments = &colorAttachment;

renderPassInfo.subpassCount = 1;

renderPassInfo.pSubpasses = &subpass;

renderPassInfo.dependencyCount = 1;

renderPassInfo.pDependencies = &dependency;

if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {

throw std::runtime_error("failed to create render pass!");

}

}

void createGraphicsPipeline() {

//auto vertShaderCode = readFile("shaders/vert.spv");

//auto fragShaderCode = readFile("shaders/frag.spv");

auto vertShaderCode = readFile("D:\\vcpro\\vulkanpro\\vulkantest6\\vul2\\Project1\\x64\\Debug\\shaders\\vert.spv");

auto fragShaderCode = readFile("D:\\vcpro\\vulkanpro\\vulkantest6\\vul2\\Project1\\x64\\Debug\\\shaders\\frag.spv");

VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);

VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);

VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};

vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;

vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;

vertShaderStageInfo.module = vertShaderModule;

vertShaderStageInfo.pName = "main";

VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};

fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;

fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;

fragShaderStageInfo.module = fragShaderModule;

fragShaderStageInfo.pName = "main";

VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };

auto bindingDescription = Vertex::getBindingDescription();

auto attributeDescriptions = Vertex::getAttributeDescriptions();

VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};

vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;

// 无绑定描述

//vertexInputInfo.vertexBindingDescriptionCount = 0;

// 无属性描述

//vertexInputInfo.vertexAttributeDescriptionCount = 0;

vertexInputInfo.vertexBindingDescriptionCount = 1;

vertexInputInfo.vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size());

vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;

vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();

VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};

inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;

inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // 绘图顺序

inputAssembly.primitiveRestartEnable = VK_FALSE;

VkViewport viewport = {};

viewport.x = 0.0f;

viewport.y = 0.0f;

viewport.width = (float)swapChainExtent.width;

viewport.height = (float)swapChainExtent.height;

viewport.minDepth = 0.0f;

viewport.maxDepth = 1.0f;

VkRect2D scissor = {};

scissor.offset = { 0, 0 };

scissor.extent = swapChainExtent;

VkPipelineViewportStateCreateInfo viewportState = {};

viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;

viewportState.viewportCount = 1;

viewportState.pViewports = &viewport;

viewportState.scissorCount = 1;

viewportState.pScissors = &scissor;

VkPipelineRasterizationStateCreateInfo rasterizer = {};

rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;

rasterizer.depthClampEnable = VK_FALSE;

rasterizer.rasterizerDiscardEnable = VK_FALSE;

rasterizer.polygonMode = VK_POLYGON_MODE_FILL; //by apple

rasterizer.lineWidth = 1.0f;

rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;

rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;

rasterizer.depthBiasEnable = VK_FALSE;

VkPipelineMultisampleStateCreateInfo multisampling = {};

multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;

multisampling.sampleShadingEnable = VK_FALSE;

multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;

VkPipelineColorBlendAttachmentState colorBlendAttachment = {};

colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;

colorBlendAttachment.blendEnable = VK_FALSE;

VkPipelineColorBlendStateCreateInfo colorBlending = {};

colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;

colorBlending.logicOpEnable = VK_FALSE;

colorBlending.logicOp = VK_LOGIC_OP_COPY;

colorBlending.attachmentCount = 1;

colorBlending.pAttachments = &colorBlendAttachment;

colorBlending.blendConstants[0] = 0.0f;

colorBlending.blendConstants[1] = 0.0f;

colorBlending.blendConstants[2] = 0.0f;

colorBlending.blendConstants[3] = 0.0f;

VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};

pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;

pipelineLayoutInfo.setLayoutCount = 1;

pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;

if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {

throw std::runtime_error("failed to create pipeline layout!");

}

VkGraphicsPipelineCreateInfo pipelineInfo = {};

pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;

pipelineInfo.stageCount = 2;

pipelineInfo.pStages = shaderStages;

pipelineInfo.pVertexInputState = &vertexInputInfo;

pipelineInfo.pInputAssemblyState = &inputAssembly;

pipelineInfo.pViewportState = &viewportState;

pipelineInfo.pRasterizationState = &rasterizer;

pipelineInfo.pMultisampleState = &multisampling;

pipelineInfo.pColorBlendState = &colorBlending;

pipelineInfo.layout = pipelineLayout;

pipelineInfo.renderPass = renderPass;

pipelineInfo.subpass = 0;

pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;

if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {

throw std::runtime_error("failed to create graphics pipeline!");

}

vkDestroyShaderModule(device, fragShaderModule, nullptr);

vkDestroyShaderModule(device, vertShaderModule, nullptr);

}

void createFramebuffers() {

swapChainFramebuffers.resize(swapChainImageViews.size());

for (size_t i = 0; i < swapChainImageViews.size(); i++) {

VkImageView attachments[] = {

swapChainImageViews[i]

};

VkFramebufferCreateInfo framebufferInfo = {};

framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;

framebufferInfo.renderPass = renderPass;

framebufferInfo.attachmentCount = 1;

framebufferInfo.pAttachments = attachments;

framebufferInfo.width = swapChainExtent.width;

framebufferInfo.height = swapChainExtent.height;

framebufferInfo.layers = 1;

if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {

throw std::runtime_error("failed to create framebuffer!");

}

}

}

void createCommandPool() {

QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);

VkCommandPoolCreateInfo poolInfo = {};

poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;

poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();

if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {

throw std::runtime_error("failed to create command pool!");

}

}

void createCommandBuffers() {

commandBuffers.resize(swapChainFramebuffers.size());

VkCommandBufferAllocateInfo allocInfo = {};

allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;

allocInfo.commandPool = commandPool;

allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;

allocInfo.commandBufferCount = (uint32_t)commandBuffers.size();

if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {

throw std::runtime_error("failed to allocate command buffers!");

}

for (size_t i = 0; i < commandBuffers.size(); i++) {

VkCommandBufferBeginInfo beginInfo = {};

beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS) {

throw std::runtime_error("failed to begin recording command buffer!");

}

VkRenderPassBeginInfo renderPassInfo = {};

renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;

renderPassInfo.renderPass = renderPass;

renderPassInfo.framebuffer = swapChainFramebuffers[i];

renderPassInfo.renderArea.offset = { 0, 0 };

renderPassInfo.renderArea.extent = swapChainExtent;

VkClearValue clearColor = { 0.0f, 0.0f, 0.0f, 1.0f };

renderPassInfo.clearValueCount = 1;

renderPassInfo.pClearValues = &clearColor;

vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);

// 开始绘图了

//vkCmdDraw(commandBuffers[i], 3, 1, 0, 0);

VkBuffer vertexBuffers[] = { vertexBuffer };

VkDeviceSize offsets[] = { 0 };

vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers,offsets);

vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16);//for index

vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[i], 0, nullptr);

vkCmdDrawIndexed(commandBuffers[i], static_cast(indices.size()), 1, 0, 0, 0);

//vkCmdDraw(commandBuffers[i], static_cast(vertices.size()),1, 0, 0);

vkCmdEndRenderPass(commandBuffers[i]);

if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {

throw std::runtime_error("failed to record command buffer!");

}

}

}

void createSyncObjects() {

imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);

renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);

inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);

imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE);

VkSemaphoreCreateInfo semaphoreInfo = {};

semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;

VkFenceCreateInfo fenceInfo = {};

fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;

fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;

for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {

if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS ||

vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS ||

vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) {

throw std::runtime_error("failed to create synchronization objects for a frame!");

}

}

}

void drawFrame() {

vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);

uint32_t imageIndex;

// 获取下一个image

VkResult result =vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);

// 若发现swapchain和窗口不适配,则重绘

if (result == VK_ERROR_OUT_OF_DATE_KHR) {

recreateSwapChain();

return;

} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {

throw std::runtime_error("failed to acquire swap chain image!");

}

if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {

vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);

}

imagesInFlight[imageIndex] = inFlightFences[currentFrame];

updateUniformBuffer(imageIndex);//new

VkSubmitInfo submitInfo = {};

submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };

VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };

submitInfo.waitSemaphoreCount = 1;

submitInfo.pWaitSemaphores = waitSemaphores;

submitInfo.pWaitDstStageMask = waitStages;

submitInfo.commandBufferCount = 1;

submitInfo.pCommandBuffers = &commandBuffers[imageIndex];

VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };

submitInfo.signalSemaphoreCount = 1;

submitInfo.pSignalSemaphores = signalSemaphores;

vkResetFences(device, 1, &inFlightFences[currentFrame]);

if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {

throw std::runtime_error("failed to submit draw command buffer!");

}

VkPresentInfoKHR presentInfo = {};

presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;

presentInfo.waitSemaphoreCount = 1;

presentInfo.pWaitSemaphores = signalSemaphores;

VkSwapchainKHR swapChains[] = { swapChain };

presentInfo.swapchainCount = 1;

presentInfo.pSwapchains = swapChains;

presentInfo.pImageIndices = &imageIndex;

// 显示

result = vkQueuePresentKHR(presentQueue, &presentInfo);

if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {

recreateSwapChain(); // 重新绘制

} else if (result != VK_SUCCESS) {

throw std::runtime_error("failed to present swap chain image!");

}

currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;

}

VkShaderModule createShaderModule(const std::vector& code) {

VkShaderModuleCreateInfo createInfo = {};

createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;

createInfo.codeSize = code.size();

createInfo.pCode = reinterpret_cast(code.data());

VkShaderModule shaderModule;

if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {

throw std::runtime_error("failed to create shader module!");

}

return shaderModule;

}

VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats) {

for (const auto& availableFormat : availableFormats) {

if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {

return availableFormat;

}

}

return availableFormats[0];

}

VkPresentModeKHR chooseSwapPresentMode(const std::vector& availablePresentModes) {

for (const auto& availablePresentMode : availablePresentModes) {

if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {

return availablePresentMode;

}

}

return VK_PRESENT_MODE_FIFO_KHR;

}

VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) {

if (capabilities.currentExtent.width != UINT32_MAX) {

return capabilities.currentExtent;

}

else {

//VkExtent2D actualExtent = { WIDTH, HEIGHT };

// 重新获取窗口的宽度和高度

int width, height;

glfwGetFramebufferSize(window, &width, &height);

VkExtent2D actualExtent = {

static_cast(width),

static_cast(height)

};

actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));

actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height));

return actualExtent;

}

}

SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) {

SwapChainSupportDetails details;

vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);

uint32_t formatCount;

vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);

if (formatCount != 0) {

details.formats.resize(formatCount);

vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());

}

uint32_t presentModeCount;

vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);

if (presentModeCount != 0) {

details.presentModes.resize(presentModeCount);

vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());

}

return details;

}

bool isDeviceSuitable(VkPhysicalDevice device) {

QueueFamilyIndices indices = findQueueFamilies(device);

bool extensionsSupported = checkDeviceExtensionSupport(device);

bool swapChainAdequate = false;

if (extensionsSupported) {

SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device);

swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();

}

return indices.isComplete() && extensionsSupported && swapChainAdequate;

}

bool checkDeviceExtensionSupport(VkPhysicalDevice device) {

uint32_t extensionCount;

vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);

std::vector availableExtensions(extensionCount);

vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());

std::set<:string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());

for (const auto& extension : availableExtensions) {

requiredExtensions.erase(extension.extensionName);

}

return requiredExtensions.empty();

}

QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {

QueueFamilyIndices indices;

uint32_t queueFamilyCount = 0;

vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);

std::vector queueFamilies(queueFamilyCount);

vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());

int i = 0;

for (const auto& queueFamily : queueFamilies) {

if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {

indices.graphicsFamily = i;

}

VkBool32 presentSupport = false;

vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);

if (presentSupport) {

indices.presentFamily = i;

}

if (indices.isComplete()) {

break;

}

i++;

}

return indices;

}

std::vector getRequiredExtensions() {

uint32_t glfwExtensionCount = 0;

const char** glfwExtensions;

glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);

std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);

if (enableValidationLayers) {

extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);

}

return extensions;

}

bool checkValidationLayerSupport() {

uint32_t layerCount;

vkEnumerateInstanceLayerProperties(&layerCount, nullptr);

std::vector availableLayers(layerCount);

vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());

for (const char* layerName : validationLayers) {

bool layerFound = false;

for (const auto& layerProperties : availableLayers) {

if (strcmp(layerName, layerProperties.layerName) == 0) {

layerFound = true;

break;

}

}

if (!layerFound) {

return false;

}

}

return true;

}

static std::vector readFile(const std::string& filename) {

std::ifstream file(filename, std::ios::ate | std::ios::binary);

if (!file.is_open()) {

throw std::runtime_error("failed to open file!");

}

size_t fileSize = (size_t)file.tellg();

std::vector buffer(fileSize);

file.seekg(0);

file.read(buffer.data(), fileSize);

file.close();

return buffer;

}

static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {

std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;

return VK_FALSE;

}

};

int main() {

HelloTriangleApplication app;

try {

app.run();

}

catch (const std::exception& e) {

std::cerr << e.what() << std::endl;

return EXIT_FAILURE;

}

return EXIT_SUCCESS;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值