include
QVulkanApp.h
#ifndef Q_VULKANAPP_H
#define Q_VULKANAPP_H
#include <QQuickItem>
#include <QQuickWindow>
#define RESOURCE
#define FUNCTION
#define Q_RESOURCE
class VkRenderer;
class QVulkanApp : public QQuickItem {
Q_OBJECT
public:
QVulkanApp();
public slots:
void sync();
void cleanup();
private slots:
void slotWindowChanged(QQuickWindow*);
private RESOURCE:
VkRenderer* _renderer = nullptr;
private FUNCTION:
void freeResource();
};
#endif
VkRenderer.h
#ifndef VKRENDERER_H
#define VKRENDERER_H
#include <QRunnable>
#include <QQuickWindow>
#include <QVulkanInstance>
#include <QVulkanFunctions>
#include <QSGRendererInterface>
#define RESOURCE
#define FUNCTION
#define Q_RESOURCE
#define _DEBUG
class QVulkanApp;
class VkRenderer: public QObject {
Q_OBJECT friend QVulkanApp;
public:
VkRenderer() = default;
virtual
~VkRenderer();
public slots:
void slotRenderStart();
void slotRenderPassRecStart();
public FUNCTION:
void setWindow(QQuickWindow* window) {_window = window;}
void setViewportSize(const QSize &size) {_viewportSize = size;}
void setExtentWidth(const uint32_t w) {_swapChainExtent.width = w;}
void setExtentHeight(const uint32_t h) {_swapChainExtent.height = h;}
private Q_RESOURCE:
QQuickWindow*
_window = nullptr;
QVulkanInstance*
_instance = nullptr;
QVulkanDeviceFunctions*
_devFunc = nullptr;
QVulkanFunctions*
_func = nullptr;
QSGRendererInterface*
_rItf = nullptr;
private RESOURCE:
enum class RenderStage {
VERTEX_STAGE,
FRAGMENT_STAGE
};
const static int
MAX_FRAME_IN_FLIGHT = 3;
const static int
UBUF_SIZE = 4;
bool
_initialized = false;
QSize
_viewportSize;
VkExtent2D
_swapChainExtent = {};
VkPhysicalDevice
_gpu = VK_NULL_HANDLE;
VkDevice
_device = VK_NULL_HANDLE;
VkDescriptorSet
_descriptorSet = VK_NULL_HANDLE;
VkDescriptorPool
_descriptorPool = VK_NULL_HANDLE;
VkDescriptorSetLayout
_descriptorLayout = VK_NULL_HANDLE;
VkBuffer
_uBuffer = VK_NULL_HANDLE;
VkDeviceMemory
_uBufferMem = VK_NULL_HANDLE;
VkBuffer
_vertBuffer = VK_NULL_HANDLE;
VkDeviceMemory
_vertBufferMem = VK_NULL_HANDLE;
VkDeviceSize
_allocPerUbuf = 0;
VkPhysicalDeviceProperties
_gpuProps = {};
VkPhysicalDeviceMemoryProperties
_gpuMemProps = {};
VkRenderPass
_renderPass = {};
VkPipelineLayout
_pipelineLayout = {};
VkPipelineCache
_pipelineCache = VK_NULL_HANDLE;
VkPipeline
_graphicsPipeline = {};
std::vector<const char*> validationLayers = {
"VK_LAYER_LUNARG_standard_validation"
};
private FUNCTION:
void
init();
void
createGraphicsPipeline();
void
createDescriptorPool();
void
createDescriptorLayout();
VkShaderModule
createShaderModule(const QByteArray&);
uint32_t
findMemoryType(uint32_t, VkMemoryPropertyFlags);
void
createBuffer(
VkDeviceSize,
VkBufferUsageFlags,
VkMemoryPropertyFlags,
VkBuffer&,
VkDeviceMemory&
);
};
class Cleanup: public QRunnable {
public:
explicit
Cleanup(VkRenderer* renderer): _renderer(renderer) {}
void
run() override
{
delete _renderer;
_renderer = nullptr;
}
private:
VkRenderer* _renderer = nullptr;
};
#endif
VkDepending.h
#ifndef VKDEPENDING_H
#define VKDEPENDING_H
#pragma once
#include <glm/glm.hpp>
#include <glm/gtx/hash.hpp>
#include <vulkan/vulkan.h>
#include <array>
#include <vector>
#include <iostream>
struct Vertex {
glm::vec3 pos;
glm::vec3 color;
glm::vec2 texCoord;
static VkVertexInputBindingDescription getBindingDescription() {
VkVertexInputBindingDescription bindingDescription = {};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return bindingDescription;
}
static std::array<VkVertexInputAttributeDescription, 3>
getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions = {};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Vertex, color);
attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2;
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
return attributeDescriptions;
}
bool operator==(const Vertex& other) const {
return pos == other.pos && color == other.color && texCoord == other.texCoord;
}
};
namespace std {
template<> struct hash<Vertex> {
size_t operator() (Vertex const& vertex) const {
return (
(hash<glm::vec3>()(vertex.pos) ^ (hash<glm::vec3>()(vertex.color) << 1))
>> 1) ^
(hash<glm::vec2>()(vertex.texCoord) << 1);
}
};
};
struct QueueFamilyIndices {
int graphicsFamily = -1;
int presentFamily = -1;
bool isComplete() {
return graphicsFamily >= 0 &&
presentFamily >= 0;
}
};
struct UniformBufferObject {
glm::mat4 model;
glm::mat4 view;
glm::mat4 proj;
};
struct SwapChainSupportDetails {
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign) {
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
bool debugOutputFilter(
VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
uint64_t object,
size_t location,
int32_t messageCode,
const char* pLayerPrefix,
const char* pMessage
);
#endif
src
QVulkanApp.cxx
#include "QVulkanApp.h"
#include "VkRenderer.h"
#include <iostream>
QVulkanApp::QVulkanApp() {
connect(
this, &QQuickItem::windowChanged,
this, &QVulkanApp::slotWindowChanged
);
std::cerr << "QVulkanApp is running as \"QQuickItem\"\n";
}
void QVulkanApp::slotWindowChanged(QQuickWindow* window) {
if(window) {
connect(
window, &QQuickWindow::beforeSynchronizing,
this, &QVulkanApp::sync, Qt::DirectConnection
);
window->setColor(qRgba(0, 0, 0, 255));
} else if(_renderer && _renderer->_initialized) {
cleanup();
}
}
void QVulkanApp::sync() {
if(!_renderer) {
_renderer = new VkRenderer;
connect(
window(), &QQuickWindow::beforeRendering,
_renderer, &VkRenderer::slotRenderStart, Qt::DirectConnection
);
connect(
window(), &QQuickWindow::beforeRenderPassRecording,
_renderer, &VkRenderer::slotRenderPassRecStart, Qt::DirectConnection
);
}
_renderer->setWindow(window());
_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
}
void QVulkanApp::cleanup() {
delete _renderer;
_renderer = nullptr;
}
void QVulkanApp::freeResource() {
window()->scheduleRenderJob(
new Cleanup(_renderer), QQuickWindow::BeforeSynchronizingStage
);
_renderer = nullptr;
}
VkRenderer.cxx
#include "VkRenderer.h"
#include "VKDepending.h"
#include <include/LCBHSS/lcbhss_space.h>
void VkRenderer::init() {
int framesInFlight;
{
framesInFlight = _window->graphicsStateInfo().framesInFlight;
assert(framesInFlight <= MAX_FRAME_IN_FLIGHT);
}
{
_instance = reinterpret_cast<QVulkanInstance*>(
_rItf->getResource(_window, QSGRendererInterface::VulkanInstanceResource)
);
_instance->installDebugOutputFilter(&debugOutputFilter);
assert(_instance && _instance->isValid());
}
{
_gpu = *reinterpret_cast<VkPhysicalDevice*>(
_rItf->getResource(_window, QSGRendererInterface::PhysicalDeviceResource)
);
assert(_gpu);
}
{
_device = *reinterpret_cast<VkDevice*>(
_rItf->getResource(_window, QSGRendererInterface::DeviceResource)
);
assert(_device);
}
{
_devFunc = _instance->deviceFunctions(_device);
_func = _instance->functions();
assert(_devFunc && _func);
}
{
VkRenderPass renderPass = *reinterpret_cast<VkRenderPass *>(
_rItf->getResource(_window, QSGRendererInterface::RenderPassResource)
);
assert(renderPass);
}
{
_func->vkGetPhysicalDeviceProperties(_gpu, &_gpuProps);
_func->vkGetPhysicalDeviceMemoryProperties(_gpu, &_gpuMemProps);
_allocPerUbuf = aligned(
UBUF_SIZE, _gpuProps.limits.minUniformBufferOffsetAlignment
);
}
{
createBuffer(
framesInFlight * _allocPerUbuf,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_uBuffer, _uBufferMem
);
createDescriptorLayout();
}
createGraphicsPipeline();
createDescriptorPool();
_initialized = true;
}
VkShaderModule VkRenderer::createShaderModule(
const QByteArray& code
) {
VkShaderModuleCreateInfo createInfo = {};
createInfo.sType =
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = code.size();
createInfo.pCode = reinterpret_cast<const uint32_t*>(
code.data());
VkShaderModule shaderModule;
if (_devFunc->vkCreateShaderModule(
_device, &createInfo, nullptr, &shaderModule
) != VK_SUCCESS) {
throw std::runtime_error("failed to create shader module");
}
return shaderModule;
}
void VkRenderer::createDescriptorLayout() {
VkDescriptorSetLayoutBinding uboLayoutBingding {};
{
uboLayoutBingding.binding = 0;
uboLayoutBingding.descriptorType =
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
uboLayoutBingding.descriptorCount = 1;
uboLayoutBingding.stageFlags =
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
uboLayoutBingding.pImmutableSamplers = nullptr;
}
VkDescriptorSetLayoutBinding samplerLayoutBinding = {};
{
samplerLayoutBinding.binding = 1;
samplerLayoutBinding.descriptorCount = 1;
samplerLayoutBinding.descriptorType =
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
samplerLayoutBinding.pImmutableSamplers = nullptr;
samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
}
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {
uboLayoutBingding, samplerLayoutBinding
};
VkDescriptorSetLayoutCreateInfo layoutInfo {};
{
layoutInfo.sType =
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
layoutInfo.pBindings = bindings.data();
}
if (_devFunc->vkCreateDescriptorSetLayout(
_device, &layoutInfo, nullptr, &_descriptorLayout
) != VK_SUCCESS)
throw std::runtime_error("Failed to create descriptor set layout: %d");
}
void VkRenderer::createGraphicsPipeline() {
{
VkPipelineCacheCreateInfo pipelineCacheInfo {};
pipelineCacheInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
if (_devFunc->vkCreatePipelineCache(
_device, &pipelineCacheInfo, nullptr, &_pipelineCache
) != VK_SUCCESS)
throw std::runtime_error("failed to create pipeline cache: %d");
}
{
VkPipelineLayoutCreateInfo pipelineLayoutInfo {};
pipelineLayoutInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &_descriptorLayout;
if (_devFunc->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;
auto vertShaderPath =
QLatin1String(":/resource/shader/compiledShader/vert.spv");
auto fragShaderPath =
QLatin1String(":/resource/shader/compiledShader/frag.spv");
VkShaderModule vertShaderModule = {};
VkShaderModule fragShaderModule = {};
{
QFile vertShader(vertShaderPath);
if(!vertShader.open(QIODevice::ReadOnly))
throw std::runtime_error("failed to read vert shader");
const QByteArray vertShaderCode =
vertShader.readAll();
assert(!vertShaderCode.isEmpty());
vertShaderModule = createShaderModule(vertShaderCode);
}
{
QFile fragShader(fragShaderPath);
if(!fragShader.open(QIODevice::ReadOnly))
throw std::runtime_error("failed to read frag shader");
const QByteArray fragShaderCode =
fragShader.readAll();
assert(!fragShaderCode.isEmpty());
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
};
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
{
vertexInputInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
auto bindingDescription = Vertex::getBindingDescription();
auto attributeDescriptions = Vertex::getAttributeDescriptions();
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.vertexAttributeDescriptionCount =
static_cast<uint32_t>(attributeDescriptions.size());
vertexInputInfo.pVertexBindingDescriptions =
&bindingDescription;
vertexInputInfo.pVertexAttributeDescriptions =
attributeDescriptions.data();
}
VkDynamicState dynStates[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamicInfo {};
{
dynamicInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicInfo.dynamicStateCount = 2;
dynamicInfo.pDynamicStates = dynStates;
}
VkPipelineViewportStateCreateInfo viewportInfo {};
{
viewportInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportInfo.viewportCount = viewportInfo.scissorCount = 1;
}
VkPipelineInputAssemblyStateCreateInfo inputAssembly {};
{
inputAssembly.sType =
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology =
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
}
VkPipelineRasterizationStateCreateInfo rsInfo {};
{
rsInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rsInfo.lineWidth = 1.0f;
}
VkPipelineMultisampleStateCreateInfo msInfo {};
{
msInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
msInfo.rasterizationSamples =
VK_SAMPLE_COUNT_1_BIT;
}
VkPipelineDepthStencilStateCreateInfo dsInfo {};
dsInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
VkPipelineColorBlendStateCreateInfo blendInfo {};
blendInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
VkPipelineColorBlendAttachmentState blend {};
blend.blendEnable = true;
blend.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blend.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
blend.colorBlendOp = VK_BLEND_OP_ADD;
blend.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blend.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blend.alphaBlendOp = VK_BLEND_OP_ADD;
blend.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT;
blendInfo.attachmentCount = 1;
blendInfo.pAttachments = &blend;
{
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pDynamicState = &dynamicInfo;
pipelineInfo.pViewportState = &viewportInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pRasterizationState = &rsInfo;
pipelineInfo.pMultisampleState = &msInfo;
pipelineInfo.pDepthStencilState = &dsInfo;
pipelineInfo.pColorBlendState = &blendInfo;
pipelineInfo.layout = _pipelineLayout;
pipelineInfo.renderPass = _renderPass;
}
if (_devFunc->vkCreateGraphicsPipelines(
_device, _pipelineCache, 1, &pipelineInfo, nullptr, &_graphicsPipeline
) != VK_SUCCESS) {
throw std::runtime_error("failed to create graphics pipeline");
}
_devFunc->vkDestroyShaderModule(_device, fragShaderModule, nullptr);
_devFunc->vkDestroyShaderModule(_device, vertShaderModule, nullptr);
}
void VkRenderer::createDescriptorPool() {
VkDescriptorPoolSize descPoolSizes[] = {
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1 }
};
VkDescriptorPoolCreateInfo descPoolInfo {};
{
descPoolInfo.sType =
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descPoolInfo.flags = 0;
descPoolInfo.maxSets = 1;
descPoolInfo.poolSizeCount = sizeof(descPoolSizes) / sizeof(descPoolSizes[0]);
descPoolInfo.pPoolSizes = descPoolSizes;
}
if (_devFunc->vkCreateDescriptorPool(
_device, &descPoolInfo, nullptr, &_descriptorPool
) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor pool");
}
VkDescriptorSetAllocateInfo descAllocInfo {};
{
descAllocInfo.sType =
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
descAllocInfo.descriptorPool = _descriptorPool;
descAllocInfo.descriptorSetCount = 1;
descAllocInfo.pSetLayouts = &_descriptorLayout;
}
if (_devFunc->vkAllocateDescriptorSets(
_device, &descAllocInfo, &_descriptorSet
) != VK_SUCCESS)
throw std::runtime_error("failed to allocate descriptor set");
VkWriteDescriptorSet writeInfo {};
{
writeInfo.sType =
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.dstSet = _descriptorSet;
writeInfo.dstBinding = 0;
writeInfo.descriptorCount = 1;
writeInfo.descriptorType =
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
}
VkDescriptorBufferInfo bufInfo {};
{
bufInfo.buffer = _uBuffer;
bufInfo.offset = 0;
bufInfo.range = UBUF_SIZE;
writeInfo.pBufferInfo = &bufInfo;
}
_devFunc->vkUpdateDescriptorSets(_device, 1, &writeInfo, 0, nullptr);
}
void VkRenderer::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 (_devFunc->vkCreateBuffer(_device, &bufferInfo, nullptr, &buffer)
!= VK_SUCCESS
) {
throw std::runtime_error("failed to create buffer");
}
VkMemoryRequirements memRequirements;
_devFunc->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 (_devFunc->vkAllocateMemory(
_device, &allocInfo, nullptr, &bufferMemory
) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate buffer memory");
}
_devFunc->vkBindBufferMemory(_device, buffer, bufferMemory, 0);
}
uint32_t VkRenderer::findMemoryType(
uint32_t typeFilter,
VkMemoryPropertyFlags properties
) {
for (uint32_t i = 0; i < _gpuMemProps.memoryTypeCount; i++) {
if ((typeFilter & (1 << i)) &&
((_gpuMemProps.memoryTypes[i].propertyFlags & properties) ==
properties)
) {
return i;
}
}
throw std::runtime_error("failed to find suitable memory type");
}
void VkRenderer::slotRenderStart() {
_rItf = _window->rendererInterface();
assert(_rItf->graphicsApi() == QSGRendererInterface::VulkanRhi);
if(!_initialized) {
init();
}
}
void VkRenderer::slotRenderPassRecStart() {
const QQuickWindow::GraphicsStateInfo &stateInfo(
_window->graphicsStateInfo()
);
VkDeviceSize ubufOffset = stateInfo.currentFrameSlot * _allocPerUbuf;
void* data = nullptr;
if(_devFunc->vkMapMemory(
_device, _uBufferMem, ubufOffset, _allocPerUbuf, 0, &data
) != VK_SUCCESS) {
throw std::runtime_error("failed to map uniform buffer memeory");
}
_devFunc->vkUnmapMemory(_device, _uBufferMem);
_window->beginExternalCommands();
VkCommandBuffer cmdBuf = *reinterpret_cast<VkCommandBuffer*>(
_rItf->getResource(_window, QSGRendererInterface::CommandListResource)
);
assert(cmdBuf);
}
VkRenderer::~VkRenderer() {
if(!_devFunc) {
return;
} else {
std::cerr << "cleanup event\n";
_devFunc->vkDestroyPipeline(_device, _graphicsPipeline, nullptr);
_devFunc->vkDestroyPipelineLayout(_device, _pipelineLayout, nullptr);
_devFunc->vkDestroyDescriptorSetLayout(_device, _descriptorLayout, nullptr);
_devFunc->vkDestroyDescriptorPool(_device, _descriptorPool, nullptr);
_devFunc->vkDestroyPipelineCache(_device, _pipelineCache, nullptr);
_devFunc->vkDestroyBuffer(_device, _uBuffer, nullptr);
_devFunc->vkFreeMemory(_device, _uBufferMem, nullptr);
std::cerr << "cleanup finished\n";
}
}
main.cxx
#include <QtQml>
#include <QQuickView>
#include <QGuiApplication>
#include "src/QVulkanApp/QVulkanApp.h"
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qmlRegisterType<QVulkanApp>("VulkanApp", 1, 14, "VulkanScene");
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::VulkanRhi);
QGuiApplication app(argc, argv);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:/qml/main.qml"));
view.show();
return app.exec();
}
VkRawFunction.cxx
#include "VKDepending.h"
bool debugOutputFilter(
VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
uint64_t object,
size_t location,
int32_t messageCode,
const char* pLayerPrefix,
const char* pMessage
) {
std::cerr
<< "validation layer catched an exception\n"
<< "[ReportFlag]: " << flags << "\n"
<< "[ObjectType]: " << objectType << "\n"
<< "[ThreadLocation]: " << location << "\n"
<< "[Object]: " << object << "\n"
<< "[MessageCode]" << messageCode << "\n"
<< "[LayerPrefix]: " << pLayerPrefix << "\n"
<< "****[Message]*** " << pMessage << "\n";
return false;
}
qml.qrc
main.qml
import QtQuick 2.14
import QtQuick.Controls 2.14
import VulkanApp 1.14
VulkanScene {
id: vkScene
width: 1280
height: 720
}