Now draws a gradient with compute
This commit is contained in:
parent
921832a950
commit
e9af67ad25
@ -27,8 +27,11 @@ find_package( VulkanMemoryAllocator CONFIG REQUIRED )
|
|||||||
find_package( fmt REQUIRED )
|
find_package( fmt REQUIRED )
|
||||||
# Shader compilers
|
# Shader compilers
|
||||||
# Todo
|
# Todo
|
||||||
#find_program( GLSLANG_VALIDATOR "glslangValidator" HINTS $ENV{VULKAN_SDK}/bin REQUIRED )
|
|
||||||
|
|
||||||
|
add_executable (glslang::validator IMPORTED)
|
||||||
|
find_program (GLSLANG_VALIDATOR "glslangValidator" HINTS $ENV{VULKAN_SDK}/bin REQUIRED)
|
||||||
|
set_property (TARGET glslang::validator PROPERTY IMPORTED_LOCATION "${GLSLANG_VALIDATOR}")
|
||||||
|
find_program(SLANGC_EXECUTABLE slangc HINTS $ENV{VULKAN_SDK}/bin REQUIRED)
|
||||||
|
|
||||||
# fastgltf because it's not in nixpkgs
|
# fastgltf because it's not in nixpkgs
|
||||||
|
|
||||||
@ -47,9 +50,50 @@ FetchContent_Declare(
|
|||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(vk-bootstrap)
|
FetchContent_MakeAvailable(vk-bootstrap)
|
||||||
|
|
||||||
|
# Helper functions to build shaders
|
||||||
|
function(addGlslShader SOURCE OUTPUT_DIR)
|
||||||
|
get_filename_component(SHADER_NAME ${SOURCE} NAME_WE)
|
||||||
|
set(SPV_FILE "${OUTPUT_DIR}/${SHADER_NAME}.spv")
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${SPV_FILE}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR}
|
||||||
|
COMMAND glslang::validator
|
||||||
|
-V
|
||||||
|
--target-env vulkan1.3 # Change if needed
|
||||||
|
-o ${SPV_FILE}
|
||||||
|
${SOURCE}
|
||||||
|
DEPENDS ${SOURCE}
|
||||||
|
COMMENT "Compiling GLSL shader: ${SOURCE} -> ${SPV_FILE}"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
set(SPV_FILE ${SPV_FILE} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
|
function(addSlangShader SOURCES ENTRY_POINTS OUTPUT_DIR)
|
||||||
|
set(SPV_FILE "${OUTPUT_DIR}/slang.spv")
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${SPV_FILE}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR}
|
||||||
|
COMMAND ${SLANGC_EXECUTABLE}
|
||||||
|
${SOURCES}
|
||||||
|
-target spirv
|
||||||
|
-profile spirv_1_4+spvRayQueryKHR # Change if needed
|
||||||
|
-emit-spirv-directly
|
||||||
|
-fvk-use-entrypoint-name
|
||||||
|
${ENTRY_POINTS}
|
||||||
|
-o ${SPV_FILE}
|
||||||
|
DEPENDS ${SOURCES}
|
||||||
|
COMMENT "Compiling Slang shaders -> ${SPV_FILE}"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
set(SPV_FILE ${SPV_FILE} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
# A function to automate executables aditions
|
# A function to automate executables aditions
|
||||||
function ( addBinary BINARY_NAME )
|
function ( addBinary BINARY_NAME )
|
||||||
cmake_parse_arguments ( BINARY "" "SOURCE" "SHADER;LIBS;TEXTURES;MODELS" ${ARGN} )
|
cmake_parse_arguments ( BINARY "" "SOURCE" "SHADERS;SLANG_SHADERS;LIBS;TEXTURES;MODELS" ${ARGN} )
|
||||||
if (DEFINED BINARY_SOURCE)
|
if (DEFINED BINARY_SOURCE)
|
||||||
add_executable ( ${BINARY_NAME} src/${BINARY_SOURCE}.cpp )
|
add_executable ( ${BINARY_NAME} src/${BINARY_SOURCE}.cpp )
|
||||||
endif()
|
endif()
|
||||||
@ -75,7 +119,30 @@ function ( addBinary BINARY_NAME )
|
|||||||
BUILD_ID="${ENGINE_VERSION}"
|
BUILD_ID="${ENGINE_VERSION}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(DEFINED BINARY_SHADERS)
|
||||||
|
set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/${BINARY_NAME}/shaders)
|
||||||
|
set(ALL_SPV_FILES "")
|
||||||
|
foreach(SHADER_SRC ${BINARY_SHADERS})
|
||||||
|
if(NOT IS_ABSOLUTE ${SHADER_SRC})
|
||||||
|
set(SHADER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/${SHADER_SRC})
|
||||||
|
endif()
|
||||||
|
addGlslShader(${SHADER_SRC} ${SHADER_OUTPUT_DIR})
|
||||||
|
list(APPEND ALL_SPV_FILES ${SPV_FILE})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_custom_target(shaders_${BINARY_NAME} DEPENDS ${ALL_SPV_FILES})
|
||||||
|
add_dependencies(${BINARY_NAME} shaders_${BINARY_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED BINARY_SLANG_SHADERS)
|
||||||
|
set(SLANG_OUTPUT_DIR ${CMAKE_BINARY_DIR}/${BINARY_NAME}/shaders)
|
||||||
|
if(NOT DEFINED BINARY_SLANG_ENTRIES)
|
||||||
|
message(FATAL_ERROR "addBinary: SLANG_SHADERS nécessite SLANG_ENTRIES")
|
||||||
|
endif()
|
||||||
|
addSlangShader("${BINARY_SLANG_SHADERS}" "${BINARY_SLANG_ENTRIES}" ${SLANG_OUTPUT_DIR})
|
||||||
|
add_custom_target(slang_shaders_${BINARY_NAME} DEPENDS ${SPV_FILE})
|
||||||
|
add_dependencies(${BINARY_NAME} slang_shaders_${BINARY_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
if (DEFINED BINARY_LIBS)
|
if (DEFINED BINARY_LIBS)
|
||||||
target_link_libraries ( ${BINARY_NAME} ${BINARY_LIBS} )
|
target_link_libraries ( ${BINARY_NAME} ${BINARY_LIBS} )
|
||||||
@ -116,6 +183,7 @@ addBinary (
|
|||||||
engine
|
engine
|
||||||
SOURCE Engine/main
|
SOURCE Engine/main
|
||||||
|
|
||||||
|
SHADERS shaders/gradient.comp
|
||||||
LIBS glfw fmt vk-bootstrap vulkan
|
LIBS glfw fmt vk-bootstrap vulkan
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "descriptors.h" // Required for public interface custom allocator
|
#include "descriptors.h" // Required for public interface custom allocator
|
||||||
#include "Common/Types.h"
|
#include "Common/Types.h"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <fmt/base.h>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
|
||||||
@ -62,6 +64,10 @@ class Engine {
|
|||||||
VkDescriptorSet _drawImageDescriptors;
|
VkDescriptorSet _drawImageDescriptors;
|
||||||
VkDescriptorSetLayout _drawImageDescriptorLayout;
|
VkDescriptorSetLayout _drawImageDescriptorLayout;
|
||||||
|
|
||||||
|
// Pipelines
|
||||||
|
VkPipeline _gradientPipeline;
|
||||||
|
VkPipelineLayout _gradientPipelineLayout;
|
||||||
|
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
@ -77,6 +83,8 @@ class Engine {
|
|||||||
void initSwapchain();
|
void initSwapchain();
|
||||||
void initCommands();
|
void initCommands();
|
||||||
void initSyncStructures();
|
void initSyncStructures();
|
||||||
|
void initPipelines();
|
||||||
|
void initBackgroundPipelines();
|
||||||
|
|
||||||
void createSwapchain(
|
void createSwapchain(
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
@ -101,6 +109,7 @@ class Engine {
|
|||||||
#define IMAGES_IMPL
|
#define IMAGES_IMPL
|
||||||
#define INITIALIZERS_IMPL
|
#define INITIALIZERS_IMPL
|
||||||
#define DESCRIPTORS_IMPL
|
#define DESCRIPTORS_IMPL
|
||||||
|
#define PIPELINES_IMPL
|
||||||
#define CALLBACK_IMPL
|
#define CALLBACK_IMPL
|
||||||
#define TIMER_IMPL
|
#define TIMER_IMPL
|
||||||
#define TYPES_IMPL
|
#define TYPES_IMPL
|
||||||
@ -111,6 +120,7 @@ class Engine {
|
|||||||
#include "initializers.h"
|
#include "initializers.h"
|
||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
#include "descriptors.h"
|
#include "descriptors.h"
|
||||||
|
#include "pipelines.h"
|
||||||
#include "Common/Types.h"
|
#include "Common/Types.h"
|
||||||
#include "Common/Timer.h"
|
#include "Common/Timer.h"
|
||||||
|
|
||||||
@ -369,6 +379,7 @@ void Engine::initRender() {
|
|||||||
initCommands();
|
initCommands();
|
||||||
initSyncStructures();
|
initSyncStructures();
|
||||||
initDescriptors();
|
initDescriptors();
|
||||||
|
initPipelines();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::initVulkan() {
|
void Engine::initVulkan() {
|
||||||
@ -656,6 +667,100 @@ void Engine::initDescriptors(){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::initPipelines() {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fmt::println("[Engine:Init] Initializing pipelines...");
|
||||||
|
#endif
|
||||||
|
initBackgroundPipelines();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fmt::println("[Engine:Init] Pipelines initialized !");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::initBackgroundPipelines() {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fmt::println("[Engine:Init] Initializing compute pipelines...");
|
||||||
|
#endif
|
||||||
|
VkPipelineLayoutCreateInfo computeLayout {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.setLayoutCount = 1,
|
||||||
|
.pSetLayouts = &_drawImageDescriptorLayout
|
||||||
|
};
|
||||||
|
|
||||||
|
VK_CHECK(
|
||||||
|
vkCreatePipelineLayout(
|
||||||
|
_device,
|
||||||
|
&computeLayout,
|
||||||
|
nullptr,
|
||||||
|
&_gradientPipelineLayout
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create the actual shader
|
||||||
|
VkShaderModule computeDrawShader;
|
||||||
|
if (
|
||||||
|
!vkutil::loadShaderModule(
|
||||||
|
"shaders/gradient.spv",
|
||||||
|
_device,
|
||||||
|
&computeDrawShader
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
fmt::println("[Engine:Error] Error when building the compute shader !");
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo stageInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.stage = VK_SHADER_STAGE_COMPUTE_BIT,
|
||||||
|
.module = computeDrawShader,
|
||||||
|
.pName = "main"
|
||||||
|
};
|
||||||
|
|
||||||
|
VkComputePipelineCreateInfo computePipelineCreateInfo {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.stage = stageInfo,
|
||||||
|
.layout = _gradientPipelineLayout
|
||||||
|
};
|
||||||
|
|
||||||
|
VK_CHECK(
|
||||||
|
vkCreateComputePipelines(
|
||||||
|
_device,
|
||||||
|
VK_NULL_HANDLE,
|
||||||
|
1,
|
||||||
|
&computePipelineCreateInfo,
|
||||||
|
nullptr,
|
||||||
|
&_gradientPipeline
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
// Do some cleanup
|
||||||
|
vkDestroyShaderModule(
|
||||||
|
_device,
|
||||||
|
computeDrawShader,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
_mainDeletionQueue.pushFunction([this]() {
|
||||||
|
vkDestroyPipelineLayout(
|
||||||
|
_device,
|
||||||
|
_gradientPipelineLayout,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
vkDestroyPipeline(
|
||||||
|
_device,
|
||||||
|
_gradientPipeline,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
});
|
||||||
|
#ifdef DEBUG
|
||||||
|
fmt::println("[Engine:Init] Compute pipelines initalized !");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//================================
|
//================================
|
||||||
//=== Render-related Functions ===
|
//=== Render-related Functions ===
|
||||||
//================================
|
//================================
|
||||||
@ -682,7 +787,9 @@ void Engine::createSwapchain(
|
|||||||
.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
|
.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR) // VSync
|
.set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR)
|
||||||
|
// FIFO = VSync
|
||||||
|
// Mailbox = Unapped
|
||||||
.set_desired_extent(width, height)
|
.set_desired_extent(width, height)
|
||||||
.add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
.add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||||
.build()
|
.build()
|
||||||
@ -725,15 +832,34 @@ void Engine::drawBackground(
|
|||||||
|
|
||||||
VkImageSubresourceRange clearRange = vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
|
VkImageSubresourceRange clearRange = vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|
||||||
// Clear Image
|
vkCmdBindPipeline(
|
||||||
vkCmdClearColorImage(
|
|
||||||
cmd,
|
cmd,
|
||||||
_drawImage.image,
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
VK_IMAGE_LAYOUT_GENERAL,
|
_gradientPipeline
|
||||||
&clearValue,
|
|
||||||
1,
|
|
||||||
&clearRange
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets(
|
||||||
|
cmd,
|
||||||
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
|
_gradientPipelineLayout,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&_drawImageDescriptors,
|
||||||
|
0,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
vkCmdDispatch(
|
||||||
|
cmd,
|
||||||
|
std::ceil(
|
||||||
|
_drawExtent.width / 16.0
|
||||||
|
),
|
||||||
|
std::ceil(
|
||||||
|
_drawExtent.height / 16.0
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,12 +2,95 @@
|
|||||||
#define PIPELINES_H
|
#define PIPELINES_H
|
||||||
// Normal header
|
// Normal header
|
||||||
|
|
||||||
|
#include "Common/Types.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fmt/base.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
namespace vkutil {
|
||||||
|
bool loadShaderModule(
|
||||||
|
const char* filePath,
|
||||||
|
VkDevice device,
|
||||||
|
VkShaderModule* outShaderModule
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PIPELINES_IMPL
|
#ifdef PIPELINES_IMPL
|
||||||
#ifndef PIPELINES_IMPL_H
|
#ifndef PIPELINES_IMPL_H
|
||||||
#define PIPELINES_IMPL_H
|
#define PIPELINES_IMPL_H
|
||||||
// Implementation
|
// Implementation
|
||||||
|
// Imports
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
// Custom imports
|
||||||
|
#include "initializers.h"
|
||||||
|
|
||||||
|
namespace vkutil {
|
||||||
|
bool loadShaderModule(
|
||||||
|
const char* filePath,
|
||||||
|
VkDevice device,
|
||||||
|
VkShaderModule* outShaderModule
|
||||||
|
) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fmt::println("[Engine:Utils] Loading shader located at {}...", filePath);
|
||||||
|
#endif
|
||||||
|
// Open the file, with the cursor at the end
|
||||||
|
std::ifstream file(
|
||||||
|
filePath,
|
||||||
|
std::ios::ate | std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!file.is_open()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the size of the file by looking
|
||||||
|
// at the cursor
|
||||||
|
size_t fileSize = (size_t)file.tellg();
|
||||||
|
|
||||||
|
// Allocate a big enough vector to suit SPIR-V
|
||||||
|
std::vector<uint32_t> buffer(fileSize/ sizeof(uint32_t));
|
||||||
|
|
||||||
|
file.seekg(0); // Put the cursor at the begining
|
||||||
|
|
||||||
|
// Load the file in the buffer
|
||||||
|
file.read((char*)buffer.data(), fileSize);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// Create the shader module
|
||||||
|
VkShaderModuleCreateInfo createInfo {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.codeSize = buffer.size() * sizeof(uint32_t), // Convert to bytes
|
||||||
|
.pCode = buffer.data()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check that everything went well
|
||||||
|
VkShaderModule shaderModule;
|
||||||
|
|
||||||
|
if (vkCreateShaderModule(
|
||||||
|
device,
|
||||||
|
&createInfo,
|
||||||
|
nullptr,
|
||||||
|
&shaderModule
|
||||||
|
) != VK_SUCCESS){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*outShaderModule = shaderModule;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fmt::println("[Engine:Utils] Shader loaded from {} and size {}", filePath, fileSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user