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 )
|
||||
# Shader compilers
|
||||
# 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
|
||||
|
||||
@ -47,9 +50,50 @@ FetchContent_Declare(
|
||||
)
|
||||
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
|
||||
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)
|
||||
add_executable ( ${BINARY_NAME} src/${BINARY_SOURCE}.cpp )
|
||||
endif()
|
||||
@ -75,7 +119,30 @@ function ( addBinary BINARY_NAME )
|
||||
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)
|
||||
target_link_libraries ( ${BINARY_NAME} ${BINARY_LIBS} )
|
||||
@ -116,6 +183,7 @@ addBinary (
|
||||
engine
|
||||
SOURCE Engine/main
|
||||
|
||||
SHADERS shaders/gradient.comp
|
||||
LIBS glfw fmt vk-bootstrap vulkan
|
||||
)
|
||||
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
|
||||
#include "descriptors.h" // Required for public interface custom allocator
|
||||
#include "Common/Types.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <fmt/base.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
||||
@ -62,6 +64,10 @@ class Engine {
|
||||
VkDescriptorSet _drawImageDescriptors;
|
||||
VkDescriptorSetLayout _drawImageDescriptorLayout;
|
||||
|
||||
// Pipelines
|
||||
VkPipeline _gradientPipeline;
|
||||
VkPipelineLayout _gradientPipelineLayout;
|
||||
|
||||
|
||||
void init();
|
||||
|
||||
@ -77,6 +83,8 @@ class Engine {
|
||||
void initSwapchain();
|
||||
void initCommands();
|
||||
void initSyncStructures();
|
||||
void initPipelines();
|
||||
void initBackgroundPipelines();
|
||||
|
||||
void createSwapchain(
|
||||
uint32_t width,
|
||||
@ -101,6 +109,7 @@ class Engine {
|
||||
#define IMAGES_IMPL
|
||||
#define INITIALIZERS_IMPL
|
||||
#define DESCRIPTORS_IMPL
|
||||
#define PIPELINES_IMPL
|
||||
#define CALLBACK_IMPL
|
||||
#define TIMER_IMPL
|
||||
#define TYPES_IMPL
|
||||
@ -111,6 +120,7 @@ class Engine {
|
||||
#include "initializers.h"
|
||||
#include "callbacks.h"
|
||||
#include "descriptors.h"
|
||||
#include "pipelines.h"
|
||||
#include "Common/Types.h"
|
||||
#include "Common/Timer.h"
|
||||
|
||||
@ -369,6 +379,7 @@ void Engine::initRender() {
|
||||
initCommands();
|
||||
initSyncStructures();
|
||||
initDescriptors();
|
||||
initPipelines();
|
||||
}
|
||||
|
||||
void Engine::initVulkan() {
|
||||
@ -656,6 +667,100 @@ void Engine::initDescriptors(){
|
||||
#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 ===
|
||||
//================================
|
||||
@ -682,7 +787,9 @@ void Engine::createSwapchain(
|
||||
.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)
|
||||
.add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||
.build()
|
||||
@ -725,15 +832,34 @@ void Engine::drawBackground(
|
||||
|
||||
VkImageSubresourceRange clearRange = vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
|
||||
// Clear Image
|
||||
vkCmdClearColorImage(
|
||||
vkCmdBindPipeline(
|
||||
cmd,
|
||||
_drawImage.image,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
&clearValue,
|
||||
1,
|
||||
&clearRange
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
_gradientPipeline
|
||||
);
|
||||
|
||||
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
|
||||
// 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
|
||||
|
||||
#ifdef PIPELINES_IMPL
|
||||
#ifndef PIPELINES_IMPL_H
|
||||
#define PIPELINES_IMPL_H
|
||||
// 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user