2024-10-11 18:00:39 -05:00
|
|
|
@startuml
|
|
|
|
title Main Execution
|
|
|
|
caption
|
|
|
|
//**Main execution from the run function in the entrypoint**//
|
|
|
|
//**This dictates basic flow of the vulkan boilerplate system. **//
|
|
|
|
endcaption
|
|
|
|
|
2024-10-13 04:56:45 -05:00
|
|
|
://**main()**//; <<procedure>>
|
2024-10-11 18:00:39 -05:00
|
|
|
://**run()**//; <<procedure>>
|
|
|
|
split
|
|
|
|
://**initWindow()**//; <<procedure>>
|
|
|
|
:glfwInit();
|
|
|
|
:window = glfwCreateWindow(...);
|
|
|
|
note left
|
|
|
|
//Create window and initialize default settings//
|
|
|
|
endnote
|
|
|
|
:glfwSetWindowUserPointer(...);
|
|
|
|
note left
|
|
|
|
//Set the user-defined pointer of the window//
|
|
|
|
endnote
|
|
|
|
:glfwSetFramebufferSizeCallback(...);
|
|
|
|
note left
|
|
|
|
//This is a callback to resizing of the window//
|
|
|
|
//we call and set a bool to true, which we get//
|
|
|
|
//and rebuild the swap chain when true.//
|
|
|
|
endnote
|
|
|
|
stop
|
|
|
|
split again
|
|
|
|
://**initVulkan()**//; <<procedure>>
|
|
|
|
split
|
|
|
|
://**createInstance()**//; <<procedure>>
|
|
|
|
split
|
|
|
|
:Debug::checkUnavailableValidationLayers();
|
|
|
|
:**VkApplicationInfo** appInfo{};
|
|
|
|
://set appInfo data, Vulkan version,//
|
|
|
|
//Engine version and name, and title//;
|
|
|
|
:**VkApplicationCreateInfo** createInfo{};
|
|
|
|
:createInfo.pApplicationInfo = &appInfo;
|
|
|
|
:Debug::vulkanDebugSetup(createInfo, vulkaninstance);
|
|
|
|
end split
|
|
|
|
split again
|
|
|
|
:Debug::setupDebugMessenger(VkInstance&);
|
|
|
|
note right: Setup debug messenger, print data to console
|
|
|
|
:glfwCreateWindowSurface(...);
|
|
|
|
note right
|
|
|
|
This function handles Window System Integration
|
|
|
|
automatically across platforms based on build environment.
|
|
|
|
====
|
|
|
|
//Basically, this is an abstraction of the Window across platforms//
|
|
|
|
end note
|
|
|
|
partition "**DeviceControl**" {
|
|
|
|
:pickPhysicalDevice(...);
|
|
|
|
note right
|
|
|
|
Enumerate through GPU's in the
|
|
|
|
system and choose a compatible one.
|
|
|
|
====
|
|
|
|
//in the future, this should choose the BEST//
|
|
|
|
//GPU, not just the first one that is compatible..//
|
|
|
|
end note
|
|
|
|
:createLogicalDevice(...);
|
|
|
|
note right
|
|
|
|
Logical devices interface with the
|
|
|
|
physical device and defines queues
|
|
|
|
end note
|
|
|
|
:createSwapChain(...);
|
|
|
|
note right
|
|
|
|
Swap Chains are used to handle buffer ownership
|
|
|
|
infrastructure. Being platform agnostic has its
|
|
|
|
complications, this is a perfect example.
|
|
|
|
This process is HEAVILY documented.
|
|
|
|
end note
|
|
|
|
:createImageViews(...);
|
|
|
|
note right
|
|
|
|
This is a cool function, quite a simple
|
|
|
|
description of images that will be shown on the
|
|
|
|
screen! It also determines //how// to access the image
|
|
|
|
end note
|
|
|
|
}
|
|
|
|
|
2024-10-12 04:14:22 -05:00
|
|
|
:**Graphics**::createRenderPass(...);
|
|
|
|
note right
|
|
|
|
This is pretty simple, it sets up the image bit depth
|
|
|
|
and the color bit depth! Basically, the format of the
|
|
|
|
displayed images, simple, but important!
|
|
|
|
end note
|
|
|
|
:**Buffers**::createDescriptorSetLayout();
|
|
|
|
note right
|
|
|
|
This function creates a table of pointers to the stored
|
|
|
|
data that we want, in this case it would be pointing to
|
|
|
|
pre-programmed model view and projection values, and
|
|
|
|
a time variable.
|
|
|
|
end note
|
2024-10-11 18:00:39 -05:00
|
|
|
partition "**Graphics**" {
|
|
|
|
:createGraphicsPipeline(...);
|
|
|
|
note right
|
|
|
|
This is a complex function that goes through every
|
|
|
|
step of the render pipeline and sets the settings we
|
|
|
|
desire for each step! **HEAVILY** documented.
|
|
|
|
end note
|
|
|
|
:createFramebuffers(...);
|
|
|
|
note right
|
|
|
|
This function creates framebuffers for all the images
|
|
|
|
that are queued to be displayed, very important!
|
|
|
|
end note
|
|
|
|
:createCommandPool(...);
|
|
|
|
note right
|
|
|
|
Commands in Vulkan are not executed using function calls
|
|
|
|
You have to record the ops you want to perform to command
|
|
|
|
buffer objects, pools manage the memory used for buffers.
|
|
|
|
end note
|
|
|
|
}
|
2024-10-13 20:32:20 -05:00
|
|
|
partition "**TextureLibraries**" {
|
|
|
|
:createTextureImage();
|
|
|
|
note right
|
|
|
|
This function imports the pixels from an image, puts them
|
|
|
|
into a buffer, and copies them from memory into a texture!
|
|
|
|
A bit complicated because we are moving and freeing lots of
|
|
|
|
memory, but quite useful.
|
|
|
|
end note
|
|
|
|
:createTextureImageView();
|
|
|
|
note right
|
|
|
|
This function creates a image view for the texture, just
|
|
|
|
builds a struct holding information about the texture, like
|
|
|
|
layers, mip levels, and etc.
|
|
|
|
end note
|
|
|
|
:createTextureSampler();
|
|
|
|
note right
|
|
|
|
This function is **incredibly** important. This builds a
|
|
|
|
texture sampler, information about what to do with the
|
|
|
|
texture once its created. This defines settings like
|
|
|
|
//UVW mode//, //Filtering//, //Anisotropy//, and
|
|
|
|
//Mipmap modes//
|
|
|
|
end note
|
|
|
|
}
|
2024-10-11 18:00:39 -05:00
|
|
|
partition "**Buffers**" {
|
|
|
|
:createVertexBuffer();
|
|
|
|
note right
|
|
|
|
Vertex buffers are incredibly useful, in essence,
|
|
|
|
you can read data from memory as vertex input to the
|
|
|
|
vertex shader rather than hardcoded data!
|
|
|
|
end note
|
|
|
|
:createIndexBuffer();
|
|
|
|
note right
|
|
|
|
Index buffers are cool, basically, you can store
|
|
|
|
some vertices that would normally be duplicated
|
|
|
|
at corners to triangulate. this saves cycles at
|
|
|
|
scale, complex objects rejoice!
|
|
|
|
end note
|
2024-10-12 04:14:22 -05:00
|
|
|
:createUniformBuffer();
|
|
|
|
note right
|
|
|
|
Map the buffer data to memory (The struct) as a pointer
|
|
|
|
we can use this as a reference of where to write data to
|
|
|
|
when the fence lets us write data.
|
|
|
|
(see **recordCommandBuffer()**).
|
|
|
|
end note
|
|
|
|
:createDescriptorPool();
|
|
|
|
note right
|
|
|
|
Here we create a pool to manage the memory and allocate
|
|
|
|
space for the descriptor sets! Very useful and the same
|
|
|
|
structure as command buffers & pools.
|
|
|
|
end note
|
|
|
|
:createDescriptorSetLayout();
|
|
|
|
note right
|
|
|
|
//Descriptor set **layouts** specify the types of resources accessible//
|
|
|
|
//by the graphical pipeline. A descriptor set is the actual buffer//
|
|
|
|
//or resource that gets bound to descriptors and passed in.//
|
|
|
|
These differ from Vertex & Index buffers, as they are not unique
|
|
|
|
to the graphics pipeline. Specification of compute vs. graphics is
|
|
|
|
therefore necessary. (see **createDescriptorSets()**)
|
|
|
|
end note
|
2024-10-11 18:00:39 -05:00
|
|
|
}
|
2024-10-13 20:32:20 -05:00
|
|
|
:**Graphics**::createCommandBuffer();
|
2024-10-11 18:00:39 -05:00
|
|
|
note right
|
|
|
|
This is the partner to the commandPool creator,
|
|
|
|
storing the commands we wish to perform whilst
|
|
|
|
waiting in a queue. These are very efficient.
|
|
|
|
end note
|
2024-10-13 20:32:20 -05:00
|
|
|
:**RenderPresent**::createSyncObject();
|
2024-10-11 18:00:39 -05:00
|
|
|
note right
|
|
|
|
This is **HEAVILY** documented, create Semaphores
|
|
|
|
and Fences, for halting and starting execution, basically
|
|
|
|
a traffic controller for the GPU.
|
|
|
|
end note
|
|
|
|
end split
|
|
|
|
stop
|
|
|
|
split again
|
|
|
|
repeat ://**mainLoop()**//; <<procedure>>
|
|
|
|
:glfwPollEvents();
|
|
|
|
:RenderPresent::drawFrame();
|
|
|
|
repeat while (!glfwWindowShouldClose(...))
|
|
|
|
:vkDeviceWaitIdle(...);
|
|
|
|
stop
|
|
|
|
split again
|
|
|
|
://**cleanup()**//; <<procedure>>
|
|
|
|
note right
|
|
|
|
//This function initiates a series of shutdown//
|
|
|
|
//destroy functions, safely stopping execution//;
|
|
|
|
endnote
|
|
|
|
:return EXIT_SUCCESS;
|
|
|
|
stop
|
|
|
|
end split
|
|
|
|
|
|
|
|
@enduml
|