Still works at least

This commit is contained in:
Emil Shanaty
2025-03-19 20:42:33 +03:00
parent 83531f3f91
commit 8eca4d330d
5 changed files with 402 additions and 58 deletions
+1
View File
@@ -0,0 +1 @@
*.db filter=lfs diff=lfs merge=lfs -text
+2
View File
@@ -5,9 +5,11 @@ set(CMAKE_CXX_STANDARD 17)
add_subdirectory(external/glfw) add_subdirectory(external/glfw)
add_subdirectory(external/glm) add_subdirectory(external/glm)
add_subdirectory(external/tinygltf)
find_package(Vulkan REQUIRED) find_package(Vulkan REQUIRED)
add_executable(acg_in_gd_lab src/main.cpp) add_executable(acg_in_gd_lab src/main.cpp)
target_link_libraries(acg_in_gd_lab PRIVATE glfw glm::glm ${Vulkan_LIBRARIES}) target_link_libraries(acg_in_gd_lab PRIVATE glfw glm::glm ${Vulkan_LIBRARIES})
target_link_libraries(acg_in_gd_lab PRIVATE tinygltf)
target_include_directories(acg_in_gd_lab PRIVATE ${Vulkan_INCLUDE_DIR}) target_include_directories(acg_in_gd_lab PRIVATE ${Vulkan_INCLUDE_DIR})
+2 -1
View File
@@ -3,4 +3,5 @@
set -ex set -ex
glslc shaders/shader.vert -o shaders/vert.spv glslc shaders/shader.vert -o shaders/vert.spv
glslc shaders/shader.frag -o shaders/frag.spv glslc shaders/shader.frag -o shaders/frag.spv
glslangValidator -V FilmicAnamorphSharpen.fx -o FilmicAnamorphSharpen.spv
+306
View File
@@ -0,0 +1,306 @@
/*------------------.
| :: Description :: |
'-------------------/
Filmic Anamorph Sharpen PS (version 1.5.0)
Copyright:
This code © 2018-2023 Jakub Maximilian Fober
Some changes by ccritchfield https://github.com/ccritchfield
License:
This work is licensed under the Creative Commons
Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/
*/
/*--------------.
| :: Commons :: |
'--------------*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "ColorConversion.fxh"
#include "LinearGammaWorkflow.fxh"
/*-----------.
| :: Menu :: |
'-----------*/
uniform float Strength
< __UNIFORM_SLIDER_FLOAT1
ui_label = "Strength";
ui_min = 0.0; ui_max = 100.0; ui_step = 0.01;
> = 60.0;
uniform float Offset
< __UNIFORM_SLIDER_FLOAT1
ui_units = " pixel";
ui_label = "Radius";
ui_tooltip = "High-pass cross offset in pixels";
ui_min = 0.0; ui_max = 2.0; ui_step = 0.01;
> = 0.1;
uniform float Clamp
< __UNIFORM_SLIDER_FLOAT1
ui_label = "Clamping";
ui_min = 0.5; ui_max = 1.0; ui_step = 0.001;
> = 0.65;
uniform bool UseMask
< __UNIFORM_INPUT_BOOL1
ui_label = "Sharpen only center";
ui_tooltip = "Sharpen only in center of the image";
> = false;
uniform bool DepthMask
< __UNIFORM_INPUT_BOOL1
ui_label = "Enable depth rim masking";
ui_tooltip = "Depth high-pass mask switch";
ui_category = "Depth mask";
ui_category_closed = true;
> = false;
uniform int DepthMaskContrast
< __UNIFORM_DRAG_INT1
ui_label = "Edges mask strength";
ui_tooltip = "Depth high-pass mask amount";
ui_category = "Depth mask";
ui_min = 0; ui_max = 2000; ui_step = 1;
> = 128;
uniform bool Preview
< __UNIFORM_INPUT_BOOL1
ui_label = "Preview sharpen layer";
ui_tooltip = "Preview sharpen layer and mask for adjustment.\n"
"If you don't see red strokes,\n"
"try changing Preprocessor Definitions in the Settings tab.";
ui_category = "Debug View";
ui_category_closed = true;
> = false;
/*---------------.
| :: Textures :: |
'---------------*/
// Define screen texture with mirror tiles
sampler BackBuffer
{
Texture = ReShade::BackBufferTex;
AddressU = MIRROR;
AddressV = MIRROR;
};
/*----------------.
| :: Functions :: |
'----------------*/
// Overlay blending mode
float Overlay(float LayerA, float LayerB)
{
float MinA = min(LayerA, 0.5);
float MinB = min(LayerB, 0.5);
float MaxA = max(LayerA, 0.5);
float MaxB = max(LayerB, 0.5);
return 2f*(MinA*MinB+MaxA+MaxB-MaxA*MaxB)-1.5;
}
// Overlay blending mode for one input
float Overlay(float LayerAB)
{
float MinAB = min(LayerAB, 0.5);
float MaxAB = max(LayerAB, 0.5);
return 2f*(MinAB*MinAB+MaxAB+MaxAB-MaxAB*MaxAB)-1.5;
}
/*--------------.
| :: Shaders :: |
'--------------*/
// Sharpen pass
float3 FilmicAnamorphSharpenPS(
float4 pos : SV_Position,
float2 UvCoord : TEXCOORD
) : SV_Target
{
// Sample display image
float3 Source = GammaConvert::to_linear(tex2D(BackBuffer, UvCoord).rgb);
// Generate radial mask
float Mask;
if (UseMask)
{
// Generate radial mask
Mask = 1f-length(UvCoord*2f-1f);
Mask = Overlay(Mask) * Strength;
// Bypass
if (Mask<=0) return GammaConvert::to_display(Source);
}
else Mask = Strength;
// Get pixel size
float2 Pixel = BUFFER_PIXEL_SIZE;
if (DepthMask)
{
/*
// original
float2 DepthPixel = Pixel*Offset+Pixel;
Pixel *= Offset;
*/
// !!! calc pixel*offset once, use twice
float2 PixelOffset = Pixel * Offset;
float2 DepthPixel = PixelOffset + Pixel;
Pixel = PixelOffset;
// Sample display depth image
float SourceDepth = ReShade::GetLinearizedDepth(UvCoord);
float2 NorSouWesEst[4] = {
float2(UvCoord.x, UvCoord.y + Pixel.y),
float2(UvCoord.x, UvCoord.y - Pixel.y),
float2(UvCoord.x + Pixel.x, UvCoord.y),
float2(UvCoord.x - Pixel.x, UvCoord.y)
};
float2 DepthNorSouWesEst[4] = {
float2(UvCoord.x, UvCoord.y + DepthPixel.y),
float2(UvCoord.x, UvCoord.y - DepthPixel.y),
float2(UvCoord.x + DepthPixel.x, UvCoord.y),
float2(UvCoord.x - DepthPixel.x, UvCoord.y)
};
// Luma high-pass color
// Luma high-pass depth
float HighPassColor = 0f, DepthMask = 0f;
[unroll]for(int s=0; s<4; s++)
{
HighPassColor +=
ColorConvert::RGB_to_Luma(
GammaConvert::to_linear(
tex2D(BackBuffer, NorSouWesEst[s]).rgb
));
DepthMask +=
ReShade::GetLinearizedDepth(NorSouWesEst[s])
+ReShade::GetLinearizedDepth(DepthNorSouWesEst[s]);
}
HighPassColor = 0.5-0.5*(HighPassColor*0.25-ColorConvert::RGB_to_Luma(Source));
DepthMask = 1f-DepthMask*0.125+SourceDepth;
DepthMask = min(1f, DepthMask)+1f-max(1f, DepthMask);
DepthMask = saturate(DepthMaskContrast*DepthMask+1f-DepthMaskContrast);
// Sharpen strength
HighPassColor = lerp(0.5, HighPassColor, Mask*DepthMask);
// Clamping sharpen
/*
// original
HighPassColor = Clamp!=1f ? max(min(HighPassColor, Clamp), 1f-Clamp) : HighPassColor;
*/
// !!! Clamp in settings above is restricted to 0.5 to 1.0
// !!! 1.0 - Clamp is the low value, while Clamp is the high value
// !!! so we can literally just use the clamp() func instead of min/max.
// !!! not sure if author was trying to take advantage of some kind of
// !!! compiler "cheat" using min/max instead of clamp to improve
// !!! performance. doesn't make sense to min/max otherwise.
HighPassColor = Clamp!=1f ? clamp(HighPassColor, 1f-Clamp, Clamp ) : HighPassColor;
float3 Sharpen = float3(
Overlay(Source.r, HighPassColor),
Overlay(Source.g, HighPassColor),
Overlay(Source.b, HighPassColor)
);
if(Preview) // Preview mode ON
{
float PreviewChannel = lerp(HighPassColor, HighPassColor*DepthMask, 0.5);
return
GammaConvert::to_display(float3(
1f-DepthMask * (1f-HighPassColor),
PreviewChannel,
PreviewChannel
));
}
return GammaConvert::to_display(Sharpen);
}
else
{
Pixel *= Offset;
float2 NorSouWesEst[4] = {
float2(UvCoord.x, UvCoord.y + Pixel.y),
float2(UvCoord.x, UvCoord.y - Pixel.y),
float2(UvCoord.x + Pixel.x, UvCoord.y),
float2(UvCoord.x - Pixel.x, UvCoord.y)
};
// Luma high-pass color
float HighPassColor = 0f;
[unroll] for(uint s=0u; s<4u; s++)
HighPassColor +=
ColorConvert::RGB_to_Luma(
GammaConvert::to_linear(
tex2D(BackBuffer, NorSouWesEst[s]).rgb
));
// !!! added space above to make it more obvious
// !!! that loop is now a one-liner in this else branch
// !!! where-as loop in branch above was multi-part
HighPassColor = 0.5-0.5*(HighPassColor*0.25-ColorConvert::RGB_to_Luma(Source));
// Sharpen strength
HighPassColor = lerp(0.5, HighPassColor, Mask);
// Clamping sharpen
/*
// original
HighPassColor = Clamp!=1f ? max(min(HighPassColor, Clamp), 1f-Clamp) : HighPassColor;
*/
// !!! Clamp in settings above is restricted to 0.5 to 1.0
// !!! 1.0 - Clamp is the low value, while Clamp is the high value
// !!! so we can literally just use the clamp() func instead of min/max.
// !!! not sure if author was trying to take advantage of some kind of
// !!! compiler "cheat" using min/max instead of clamp to improve
// !!! performance. doesn't make sense to min/max otherwise.
HighPassColor = Clamp!=1f ? clamp(HighPassColor, 1f-Clamp, Clamp) : HighPassColor;
float3 Sharpen = float3(
Overlay(Source.r, HighPassColor),
Overlay(Source.g, HighPassColor),
Overlay(Source.b, HighPassColor)
);
return GammaConvert::to_display(
Preview // preview mode ON
? HighPassColor
: Sharpen
);
}
}
/*-------------.
| :: Output :: |
'-------------*/
technique FilmicAnamorphSharpen
<
ui_label = "Filmic Anamorphic Sharpen";
ui_tooltip =
"This effect © 2018-2023 Jakub Maksymilian Fober\n"
"Licensed under CC BY-SA 4.0";
>
{
pass
{
VertexShader = PostProcessVS;
PixelShader = FilmicAnamorphSharpenPS;
}
}
+91 -57
View File
@@ -1,4 +1,7 @@
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@@ -11,23 +14,52 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <filesystem> #include <filesystem>
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#include "tiny_gltf.h"
using namespace tinygltf;
bool load_gltf() {
Model model;
TinyGLTF loader;
std::string err;
std::string warn;
bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, "models/Models/BrainStem/glTF/BrainStem.gltf"); // YOUR GLTF HERE
//bool ret = loader.LoadBinaryFromFile(&model, &err, &warn, argv[1]); // for binary glTF(.glb)
if (!warn.empty()) {
printf("Warn: %s\n", warn.c_str());
}
if (!err.empty()) {
printf("Err: %s\n", err.c_str());
}
if (!ret) {
printf("Failed to parse glTF\n");
return -1;
}
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, }
const VkAllocationCallbacks *pAllocator,
VkDebugUtilsMessengerEXT *pDebugMessenger) { VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); const VkAllocationCallbacks* pAllocator,
VkDebugUtilsMessengerEXT* pDebugMessenger) {
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
if (func != nullptr) { if (func != nullptr) {
return func(instance, pCreateInfo, pAllocator, pDebugMessenger); return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
} else { }
else {
return VK_ERROR_EXTENSION_NOT_PRESENT; return VK_ERROR_EXTENSION_NOT_PRESENT;
} }
} }
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger,
const VkAllocationCallbacks *pAllocator) { const VkAllocationCallbacks* pAllocator) {
auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance,
"vkDestroyDebugUtilsMessengerEXT"); "vkDestroyDebugUtilsMessengerEXT");
if (func != nullptr) { if (func != nullptr) {
func(instance, debugMessenger, pAllocator); func(instance, debugMessenger, pAllocator);
} }
@@ -54,13 +86,13 @@ struct SwapChainSupportDetails {
VkSurfaceFormatKHR chooseSwapSurfaceFormat() { VkSurfaceFormatKHR chooseSwapSurfaceFormat() {
for (const auto& format : formats) { for (const auto& format : formats) {
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && if (format.format == VK_FORMAT_B8G8R8A8_SRGB &&
format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
return format; return format;
} }
} }
if (!formats.empty()) if (!formats.empty())
return formats[0]; return formats[0];
return {VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_MAX_ENUM_KHR}; return { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_MAX_ENUM_KHR };
} }
VkPresentModeKHR chooseSwapPresentMode() { VkPresentModeKHR chooseSwapPresentMode() {
@@ -73,23 +105,23 @@ struct SwapChainSupportDetails {
return VK_PRESENT_MODE_IMMEDIATE_KHR; return VK_PRESENT_MODE_IMMEDIATE_KHR;
} }
VkExtent2D chooseSwapExtent(GLFWwindow *window) { VkExtent2D chooseSwapExtent(GLFWwindow* window) {
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) { if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
return capabilities.currentExtent; return capabilities.currentExtent;
} }
int width, height; int width, height;
glfwGetFramebufferSize(window, &width, &height); glfwGetFramebufferSize(window, &width, &height);
VkExtent2D actualExtent { VkExtent2D actualExtent{
static_cast<uint32_t>(width), static_cast<uint32_t>(width),
static_cast<uint32_t>(height) static_cast<uint32_t>(height)
}; };
actualExtent.width = std::clamp(actualExtent.width, actualExtent.width = std::clamp(actualExtent.width,
capabilities.minImageExtent.width, capabilities.minImageExtent.width,
capabilities.maxImageExtent.width); capabilities.maxImageExtent.width);
actualExtent.height = std::clamp(actualExtent.height, actualExtent.height = std::clamp(actualExtent.height,
capabilities.minImageExtent.height, capabilities.minImageExtent.height,
capabilities.maxImageExtent.height); capabilities.maxImageExtent.height);
return actualExtent; return actualExtent;
} }
@@ -103,7 +135,7 @@ struct SwapChainSupportDetails {
}; };
static std::vector<char> readFile(const std::filesystem::path & filepath) { static std::vector<char> readFile(const std::filesystem::path& filepath) {
std::ifstream file(filepath, std::ios::ate | std::ios::binary); std::ifstream file(filepath, std::ios::ate | std::ios::binary);
if (!file.is_open()) { if (!file.is_open()) {
throw std::runtime_error(std::string("failed to open a file: ") + filepath.string()); throw std::runtime_error(std::string("failed to open a file: ") + filepath.string());
@@ -124,11 +156,11 @@ private:
const int HEIGHT = 600; const int HEIGHT = 600;
const std::string appName = "Vulkan on MacOS"; const std::string appName = "Vulkan on MacOS";
const std::string engineName = "The Best Engine"; const std::string engineName = "The Best Engine";
const std::vector<const char *> deviceExtensions = { const std::vector<const char*> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
"VK_KHR_portability_subset", "VK_KHR_portability_subset",
}; };
const std::vector<const char *> validationLayers = { const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation" "VK_LAYER_KHRONOS_validation"
}; };
@@ -138,7 +170,7 @@ private:
const bool enableValidationLayers = true; const bool enableValidationLayers = true;
#endif #endif
GLFWwindow *window = nullptr; GLFWwindow* window = nullptr;
VkInstance instance = VK_NULL_HANDLE; VkInstance instance = VK_NULL_HANDLE;
VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE;
@@ -166,6 +198,7 @@ public:
void run() { void run() {
initWindow(); initWindow();
initVulkan(); initVulkan();
mainLoop(); mainLoop();
cleanup(); cleanup();
} }
@@ -178,9 +211,9 @@ private:
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow( window = glfwCreateWindow(
WIDTH, HEIGHT, WIDTH, HEIGHT,
appName.c_str(), appName.c_str(),
nullptr, nullptr); nullptr, nullptr);
} }
void initVulkan() { void initVulkan() {
@@ -205,9 +238,9 @@ private:
std::vector<VkLayerProperties> availableLayers(layerCount); std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
for (const auto &layerName: validationLayers) { for (const auto& layerName : validationLayers) {
bool layerFound = false; bool layerFound = false;
for (const auto &layerProperties: availableLayers) { for (const auto& layerProperties : availableLayers) {
if (strcmp(layerName, layerProperties.layerName) == 0) { if (strcmp(layerName, layerProperties.layerName) == 0) {
layerFound = true; layerFound = true;
break; break;
@@ -220,12 +253,12 @@ private:
return true; return true;
} }
std::vector<const char *> getRequiredExtensions() const { std::vector<const char*> getRequiredExtensions() const {
uint32_t glfwExtensionCount = 0; uint32_t glfwExtensionCount = 0;
const char **glfwExtensions; const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
std::vector<const char *> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
if (enableValidationLayers) { if (enableValidationLayers) {
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
@@ -237,15 +270,15 @@ private:
return extensions; return extensions;
} }
static void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo) { static void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
createInfo = {}; createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity = createInfo.messageSeverity =
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo.messageType = createInfo.messageType =
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback = debugCallback; createInfo.pfnUserCallback = debugCallback;
} }
@@ -291,17 +324,17 @@ private:
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
std::cout << "available extensions:\n"; std::cout << "available extensions:\n";
for (const auto &extension: extensions) { for (const auto& extension : extensions) {
std::cout << '\t' << extension.extensionName << '\n'; std::cout << '\t' << extension.extensionName << '\n';
} }
} }
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType, VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void *pUserData) { void* pUserData) {
std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;
@@ -377,10 +410,10 @@ private:
bool checkDeviceExtensionSupport(VkPhysicalDevice dev) { bool checkDeviceExtensionSupport(VkPhysicalDevice dev) {
uint32_t extensionCount; uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(dev, nullptr, vkEnumerateDeviceExtensionProperties(dev, nullptr,
&extensionCount, nullptr); &extensionCount, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount); std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(dev, nullptr, vkEnumerateDeviceExtensionProperties(dev, nullptr,
&extensionCount, availableExtensions.data()); &extensionCount, availableExtensions.data());
std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
for (const auto& extension : availableExtensions) { for (const auto& extension : availableExtensions) {
@@ -414,9 +447,9 @@ private:
} }
std::cout << ", swapchain is not empty: " << swapChainAdequate << "\n"; std::cout << ", swapchain is not empty: " << swapChainAdequate << "\n";
return hasQueues && isSupportExtensions && swapChainAdequate; return hasQueues && isSupportExtensions && swapChainAdequate;
}; };
for (const auto &dev: devices) { for (const auto& dev : devices) {
if (isDeviceSuitable(dev)) { if (isDeviceSuitable(dev)) {
physicalDevice = dev; physicalDevice = dev;
break; break;
@@ -438,7 +471,7 @@ private:
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos; std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
float queuePriority = 1.0f; float queuePriority = 1.0f;
for (uint32_t queueFamily : uniqueQueueFamilies){ for (uint32_t queueFamily : uniqueQueueFamilies) {
VkDeviceQueueCreateInfo queueCreateInfo{}; VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily; queueCreateInfo.queueFamilyIndex = queueFamily;
@@ -493,7 +526,7 @@ private:
createInfo.oldSwapchain = VK_NULL_HANDLE; createInfo.oldSwapchain = VK_NULL_HANDLE;
QueueFamilyIndices indices = findQueueFamilies(physicalDevice); QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()}; uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };
if (indices.graphicsFamily != indices.presentFamily) { if (indices.graphicsFamily != indices.presentFamily) {
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
createInfo.queueFamilyIndexCount = 2; createInfo.queueFamilyIndexCount = 2;
@@ -585,7 +618,7 @@ private:
renderPassInfo.dependencyCount = 1; renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency; renderPassInfo.pDependencies = &dependency;
if(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
throw std::runtime_error("failed to create a render pass"); throw std::runtime_error("failed to create a render pass");
} }
} }
@@ -593,7 +626,7 @@ private:
void createGraphicsPipeline() { void createGraphicsPipeline() {
auto vertShaderCode = readFile("shaders/vert.spv"); auto vertShaderCode = readFile("shaders/vert.spv");
auto fragShaderCode = readFile("shaders/frag.spv"); auto fragShaderCode = readFile("shaders/frag.spv");
VkShaderModule vertShaderModule = createShaderModule(vertShaderCode); VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = createShaderModule(fragShaderCode); VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
@@ -610,8 +643,8 @@ private:
fragShaderStageInfo.pName = "main"; fragShaderStageInfo.pName = "main";
std::vector<VkPipelineShaderStageCreateInfo> shaderStages = { std::vector<VkPipelineShaderStageCreateInfo> shaderStages = {
vertShaderStageInfo, vertShaderStageInfo,
fragShaderStageInfo fragShaderStageInfo,
}; };
VkPipelineVertexInputStateCreateInfo vertexInputState{}; VkPipelineVertexInputStateCreateInfo vertexInputState{};
@@ -777,9 +810,9 @@ private:
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass; renderPassInfo.renderPass = renderPass;
renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex]; renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex];
renderPassInfo.renderArea.offset = {0, 0}; renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent = swapChainExtent; renderPassInfo.renderArea.extent = swapChainExtent;
VkClearValue clearColor = {{{0.0f, 0.0f, 0.4f, 1.0f}}}; VkClearValue clearColor = { {{0.0f, 0.0f, 0.4f, 1.0f}} };
renderPassInfo.clearValueCount = 1; renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearColor; renderPassInfo.pClearValues = &clearColor;
@@ -796,7 +829,7 @@ private:
vkCmdSetViewport(commandBuffer, 0, 1, &viewport); vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor{}; VkRect2D scissor{};
scissor.offset = {0, 0}; scissor.offset = { 0, 0 };
scissor.extent = swapChainExtent; scissor.extent = swapChainExtent;
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
@@ -822,10 +855,10 @@ private:
VkSubmitInfo submitInfo{}; VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
std::vector<VkSemaphore> waitSemaphores = {imageAvailableSemaphore}; std::vector<VkSemaphore> waitSemaphores = { imageAvailableSemaphore };
std::vector<VkPipelineStageFlags> waitStages = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; std::vector<VkPipelineStageFlags> waitStages = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
std::vector<VkCommandBuffer> commandBuffers = {commandBuffer}; std::vector<VkCommandBuffer> commandBuffers = { commandBuffer };
std::vector<VkSemaphore> signalSemaphores = {renderFinishedSemaphore}; std::vector<VkSemaphore> signalSemaphores = { renderFinishedSemaphore };
submitInfo.waitSemaphoreCount = waitSemaphores.size(); submitInfo.waitSemaphoreCount = waitSemaphores.size();
submitInfo.pWaitSemaphores = waitSemaphores.data(); submitInfo.pWaitSemaphores = waitSemaphores.data();
submitInfo.pWaitDstStageMask = waitStages.data(); submitInfo.pWaitDstStageMask = waitStages.data();
@@ -844,7 +877,7 @@ private:
presentInfo.waitSemaphoreCount = signalSemaphores.size(); presentInfo.waitSemaphoreCount = signalSemaphores.size();
presentInfo.pWaitSemaphores = signalSemaphores.data(); presentInfo.pWaitSemaphores = signalSemaphores.data();
std::vector<VkSwapchainKHR> swapChains = {swapChain}; std::vector<VkSwapchainKHR> swapChains = { swapChain };
presentInfo.swapchainCount = swapChains.size(); presentInfo.swapchainCount = swapChains.size();
presentInfo.pSwapchains = swapChains.data(); presentInfo.pSwapchains = swapChains.data();
presentInfo.pImageIndices = &imageIndex; presentInfo.pImageIndices = &imageIndex;
@@ -895,7 +928,8 @@ int main() {
try { try {
app.run(); app.run();
} catch (const std::exception &e) { }
catch (const std::exception& e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }