#include "first_app.hpp" // libs #define GLM_FORCE_RADIANS #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include // std #include #include namespace hk { struct SimplePushConstantData { glm::mat2 transform{1.0f}; glm::vec2 offset; alignas(16) glm::vec3 color; }; FirstApp::FirstApp() { loadGameObjects(); createPipelineLayout(); createPipeline(); } FirstApp::~FirstApp() { vkDestroyPipelineLayout(m_device.device(), m_pipelineLayout, nullptr); } void FirstApp::run() { while (!m_window.shouldClose()) { glfwPollEvents(); if (auto commandBuffer = m_renderer.beginFrame()) { m_renderer.beginSwapChainRenderPass(commandBuffer); renderGameObjects(commandBuffer); m_renderer.endSwapChainRenderPass(commandBuffer); m_renderer.endFrame(); } } vkDeviceWaitIdle(m_device.device()); } void FirstApp::loadGameObjects() { std::vector vertices{ {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}}, {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} }; auto model = std::make_shared(m_device, vertices); auto triangle = GameObject::createGameObject(); triangle.m_model = model; triangle.m_color = {.1f, .8f, .1f}; triangle.m_transform2d.translation.x = .2f; triangle.m_transform2d.scale = {2.0f, .5f}; triangle.m_transform2d.rotation = .25f * glm::two_pi(); m_gameObjects.push_back(std::move(triangle)); } void FirstApp::createPipelineLayout() { VkPushConstantRange pushConstantRange{}; pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; pushConstantRange.offset = 0; pushConstantRange.size = sizeof(SimplePushConstantData); VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.setLayoutCount = 0; pipelineLayoutInfo.pSetLayouts = nullptr; pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; if (vkCreatePipelineLayout(m_device.device(), &pipelineLayoutInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) { throw std::runtime_error("failed to create pipeline layout!"); } } void FirstApp::createPipeline() { assert(m_pipelineLayout != nullptr && "Cannot create pipeline before pipeline layout"); PipelineConfigInfo pipelineConfig{}; Pipeline::defaultPipelineConfigInfo(pipelineConfig); pipelineConfig.renderPass = m_renderer.getSwapChainRenderPass(); pipelineConfig.pipelineLayout = m_pipelineLayout; m_pipeline = std::make_unique( m_device, "shaders/simple_shader.vert.spv", "shaders/simple_shader.frag.spv", pipelineConfig); } void FirstApp::renderGameObjects(VkCommandBuffer commandBuffer) { m_pipeline->bind(commandBuffer); for (auto &obj : m_gameObjects) { obj.m_transform2d.rotation = glm::mod(obj.m_transform2d.rotation + 0.01f, glm::two_pi()); SimplePushConstantData push{}; push.offset = obj.m_transform2d.translation; push.color = obj.m_color; push.transform = obj.m_transform2d.mat2(); vkCmdPushConstants( commandBuffer, m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(SimplePushConstantData), &push); obj.m_model->bind(commandBuffer); obj.m_model->draw(commandBuffer); } } }