Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • vulkan2021/vkcv-framework
1 result
Select Git revision
Show changes
Commits on Source (19)
Showing
with 356 additions and 63 deletions
......@@ -29,6 +29,8 @@ set(vkcv_sources
${vkcv_source}/vkcv/ImageManager.hpp
${vkcv_source}/vkcv/ImageManager.cpp
${vkcv_include}/vkcv/Logger.hpp
${vkcv_include}/vkcv/SwapChain.hpp
${vkcv_source}/vkcv/SwapChain.cpp
......
......@@ -6,9 +6,20 @@ if (spirv-cross_FOUND)
message(${vkcv_config_msg} " SPIRV Cross - " ${SPIRV_CROSS_VERSION})
else()
if (EXISTS "${vkcv_lib_path}/SPIRV-Cross")
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS OFF CACHE INTERNAL "")
set(SPIRV_CROSS_SHARED OFF CACHE INTERNAL "")
set(SPIRV_CROSS_STATIC ON CACHE INTERNAL "")
set(SPIRV_CROSS_CLI OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_GLSL ON CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_HLSL OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_MSL OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_CPP ON CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_REFLECT OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_C_API OFF CACHE INTERNAL "")
set(SPIRV_CROSS_ENABLE_UTIL OFF CACHE INTERNAL "")
set(SPIRV_CROSS_SKIP_INSTALL ON CACHE INTERNAL "")
add_subdirectory(${vkcv_lib}/SPIRV-Cross)
......
......@@ -157,6 +157,19 @@ namespace vkcv
[[nodiscard]]
PipelineHandle createGraphicsPipeline(const PipelineConfig &config);
/**
* Creates a basic vulkan compute pipeline using @p shader program and returns it using the @p handle.
* Fixed Functions for pipeline are set with standard values.
*
* @param shader program that hold the compiles compute shader
* @param handle a handle to return the created vulkan handle
* @return True if pipeline creation was successful, False if not
*/
[[nodiscard]]
PipelineHandle createComputePipeline(
const ShaderProgram &config,
const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
/**
* Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle.
* Fixed Functions for pipeline are set with standard values.
......@@ -211,7 +224,7 @@ namespace vkcv
*/
[[nodiscard]]
DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &bindings);
void writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites& writes);
void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites& writes);
DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
......@@ -228,6 +241,13 @@ namespace vkcv
const std::vector<DrawcallInfo> &drawcalls,
const std::vector<ImageHandle> &renderTargets);
void recordComputeDispatchToCmdStream(
CommandStreamHandle cmdStream,
PipelineHandle computePipeline,
const uint32_t dispatchCount[3],
const std::vector<DescriptorSetUsage> &descriptorSetUsages,
const PushConstantData& pushConstantData);
/**
* @brief end recording and present image
*/
......
#pragma once
#include <iostream>
namespace vkcv {
enum class LogLevel {
INFO,
WARNING,
ERROR
};
constexpr auto getLogOutput(LogLevel level) {
switch (level) {
case LogLevel::INFO:
return stdout;
default:
return stderr;
}
}
constexpr const char* getLogName(LogLevel level) {
switch (level) {
case LogLevel::INFO:
return "INFO";
case LogLevel::WARNING:
return "WARNING";
case LogLevel::ERROR:
return "ERROR";
default:
return "UNKNOWN";
}
}
#ifndef NDEBUG
#ifndef VKCV_DEBUG_MESSAGE_LEN
#define VKCV_DEBUG_MESSAGE_LEN 1024
#endif
#ifdef _MSC_VER
#define __PRETTY_FUNCTION__ __FUNCSIG__
#endif
#define vkcv_log(level, ...) { \
char output_message [ \
VKCV_DEBUG_MESSAGE_LEN \
]; \
std::snprintf( \
output_message, \
VKCV_DEBUG_MESSAGE_LEN, \
__VA_ARGS__ \
); \
std::fprintf( \
getLogOutput(level), \
"[%s]: %s [%s, line %d: %s]\n", \
vkcv::getLogName(level), \
output_message, \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__ \
); \
}
#else
#define vkcv_log(level, ...) {}
#endif
}
......@@ -7,6 +7,8 @@
#define STBI_ONLY_JPEG
#include <stb_image.h>
#include <vkcv/Logger.hpp>
namespace vkcv::asset {
/**
......@@ -39,11 +41,12 @@ uint8_t convertTypeToInt(const fx::gltf::Accessor::Type type) {
* @param path path to file that is responsible for error
*/
void print_what (const std::exception& e, const std::string &path) {
fprintf(stderr, "ERROR loading file %s: %s\n", path.c_str(), e.what());
vkcv_log(LogLevel::ERROR, "Loading file %s: %s",
path.c_str(), e.what());
try {
std::rethrow_if_nested(e);
} catch (const std::exception& nested) {
std::cerr << "nested: ";
print_what(nested, path);
}
}
......@@ -121,7 +124,7 @@ int loadMesh(const std::string &path, Mesh &mesh) {
const size_t off = indexBufferView.byteOffset;
const void *const ptr = ((char*)indexBuffer.data.data()) + off;
if (!memcpy(indexBufferData.data(), ptr, indexBufferView.byteLength)) {
std::cerr << "ERROR copying index buffer data.\n";
vkcv_log(LogLevel::ERROR, "Copying index buffer data");
return 0;
}
}
......@@ -136,7 +139,7 @@ int loadMesh(const std::string &path, Mesh &mesh) {
const size_t off = 0;
const void *const ptr = ((char*)vertexBuffer.data.data()) + off;
if (!memcpy(vertexBufferData.data(), ptr, vertexBuffer.byteLength)) {
std::cerr << "ERROR copying vertex buffer data.\n";
vkcv_log(LogLevel::ERROR, "Copying vertex buffer data");
return 0;
}
}
......@@ -150,9 +153,8 @@ int loadMesh(const std::string &path, Mesh &mesh) {
case fx::gltf::Accessor::ComponentType::UnsignedInt:
indexType = UINT32; break;
default:
std::cerr << "ERROR: Index type not supported: " <<
static_cast<uint16_t>(indexAccessor.componentType) <<
std::endl;
vkcv_log(LogLevel::ERROR, "Index type (%u) not supported",
static_cast<uint16_t>(indexAccessor.componentType));
return 0;
}
......
......@@ -207,7 +207,7 @@ int main(int argc, const char** argv) {
vkcv::SamplerDescriptorWrite(1, sampler),
vkcv::SamplerDescriptorWrite(4, shadowSampler) };
setWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) };
core.writeResourceDescription(descriptorSet, 0, setWrites);
core.writeDescriptorSet(descriptorSet, setWrites);
auto start = std::chrono::system_clock::now();
const auto appStartTime = start;
......
......@@ -130,9 +130,9 @@ int main(int argc, const char** argv) {
};
vkcv::DescriptorWrites setWrites;
setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) };
core.writeResourceDescription(descriptorSet, 0, setWrites);
setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) };
core.writeDescriptorSet(descriptorSet, setWrites);
vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle();
......
File added
%VULKAN_SDK%\Bin32\glslc.exe shader.vert -o vert.spv
%VULKAN_SDK%\Bin32\glslc.exe shader.frag -o frag.spv
%VULKAN_SDK%\Bin32\glslc.exe shader.comp -o comp.spv
pause
\ No newline at end of file
#version 440
layout(std430, binding = 0) buffer testBuffer
{
float test1[10];
float test2[10];
float test3[10];
};
layout( push_constant ) uniform constants{
float pushConstant;
};
layout(local_size_x = 5) in;
void main(){
if(gl_GlobalInvocationID.x >= 10){
return;
}
test1[gl_GlobalInvocationID.x] = gl_GlobalInvocationID.x;
test2[gl_GlobalInvocationID.x] = 69; // nice!
test3[gl_GlobalInvocationID.x] = pushConstant;
}
\ No newline at end of file
......@@ -92,6 +92,7 @@ int main(int argc, const char** argv) {
return EXIT_FAILURE;
}
// Graphics Pipeline
vkcv::ShaderProgram triangleShaderProgram{};
triangleShaderProgram.addShader(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/vert.spv"));
triangleShaderProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/frag.spv"));
......@@ -115,6 +116,30 @@ int main(int argc, const char** argv) {
return EXIT_FAILURE;
}
// Compute Pipeline
vkcv::ShaderProgram computeShaderProgram{};
computeShaderProgram.addShader(vkcv::ShaderStage::COMPUTE, std::filesystem::path("shaders/comp.spv"));
computeShaderProgram.reflectShader(vkcv::ShaderStage::COMPUTE);
// take care, assuming shader has exactly one descriptor set
vkcv::DescriptorSetHandle computeDescriptorSet = core.createDescriptorSet(computeShaderProgram.getReflectedDescriptors()[0]);
vkcv::PipelineHandle computePipeline = core.createComputePipeline(
computeShaderProgram,
{ core.getDescriptorSet(computeDescriptorSet).layout });
struct ComputeTestBuffer {
float test1[10];
float test2[10];
float test3[10];
};
vkcv::Buffer computeTestBuffer = core.createBuffer<ComputeTestBuffer>(vkcv::BufferType::STORAGE, 1);
vkcv::DescriptorWrites computeDescriptorWrites;
computeDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, computeTestBuffer.getHandle()) };
core.writeDescriptorSet(computeDescriptorSet, computeDescriptorWrites);
/*
* BufferHandle triangleVertices = core.createBuffer(vertices);
* BufferHandle triangleIndices = core.createBuffer(indices);
......@@ -164,6 +189,17 @@ int main(int argc, const char** argv) {
pushConstantData,
{ drawcall },
{ swapchainInput });
const uint32_t dispatchSize[3] = { 2, 1, 1 };
const float theMeaningOfLife = 42;
core.recordComputeDispatchToCmdStream(
cmdStream,
computePipeline,
dispatchSize,
{ vkcv::DescriptorSetUsage(0, core.getDescriptorSet(computeDescriptorSet).vulkanHandle) },
vkcv::PushConstantData((void*)&theMeaningOfLife, sizeof(theMeaningOfLife)));
core.prepareSwapchainImageForPresent(cmdStream);
core.submitCommandStream(cmdStream);
......
#include "vkcv/CommandResources.hpp"
#include <iostream>
#include "vkcv/Logger.hpp"
namespace vkcv {
......@@ -62,7 +63,7 @@ namespace vkcv {
return queueManager.getPresentQueue();
}
else {
std::cerr << "getQueueForSubmit error: unknown queue type" << std::endl;
vkcv_log(LogLevel::ERROR, "Unknown queue type");
return queueManager.getGraphicsQueues().front(); // graphics is the most general queue
}
}
......
#include "vkcv/CommandStreamManager.hpp"
#include "vkcv/Core.hpp"
#include "vkcv/Logger.hpp"
namespace vkcv {
CommandStreamManager::CommandStreamManager() noexcept : m_core(nullptr){}
......@@ -14,7 +16,7 @@ namespace vkcv {
void CommandStreamManager::init(Core* core) {
if (!core) {
std::cerr << "Error: CommandStreamManager::init requires valid core pointer" << std::endl;
vkcv_log(LogLevel::ERROR, "Requires valid core pointer");
}
m_core = core;
}
......@@ -57,7 +59,7 @@ namespace vkcv {
const size_t id = handle.getId();
if (id >= m_commandStreams.size()) {
std::cerr << "Error: CommandStreamManager::recordCommandsToStream requires valid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Requires valid handle");
return;
}
......@@ -71,7 +73,7 @@ namespace vkcv {
const size_t id = handle.getId();
if (id >= m_commandStreams.size()) {
std::cerr << "Error: CommandStreamManager::addFinishCallbackToStream requires valid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Requires valid handle");
return;
}
......@@ -86,7 +88,7 @@ namespace vkcv {
const size_t id = handle.getId();
if (id >= m_commandStreams.size()) {
std::cerr << "Error: CommandStreamManager::submitCommandStreamSynchronous requires valid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Requires valid handle");
return;
}
CommandStream& stream = m_commandStreams[id];
......@@ -111,7 +113,7 @@ namespace vkcv {
vk::CommandBuffer CommandStreamManager::getStreamCommandBuffer(const CommandStreamHandle handle) {
const size_t id = handle.getId();
if (id >= m_commandStreams.size()) {
std::cerr << "Error: CommandStreamManager::submitCommandStreamSynchronous requires valid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Requires valid handle");
return nullptr;
}
return m_commandStreams[id].cmdBuffer;
......
......@@ -16,6 +16,8 @@
#include "ImageLayoutTransitions.hpp"
#include "vkcv/CommandStreamManager.hpp"
#include "vkcv/Logger.hpp"
namespace vkcv
{
......@@ -101,6 +103,13 @@ namespace vkcv
return m_PipelineManager->createPipeline(config, *m_PassManager);
}
PipelineHandle Core::createComputePipeline(
const ShaderProgram &shaderProgram,
const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts)
{
return m_PipelineManager->createComputePipeline(shaderProgram, descriptorSetLayouts);
}
PassHandle Core::createPass(const PassConfig &config)
{
......@@ -125,7 +134,7 @@ namespace vkcv
}
if (result != vk::Result::eSuccess) {
std::cerr << vk::to_string(result) << std::endl;
vkcv_log(LogLevel::ERROR, "%s", vk::to_string(result).c_str());
return Result::ERROR;
}
......@@ -149,7 +158,7 @@ namespace vkcv
}
if (acquireSwapchainImage() != Result::SUCCESS) {
std::cerr << "Acquire failed!" << std::endl;
vkcv_log(LogLevel::ERROR, "Acquire failed");
m_currentSwapchainImageIndex = std::numeric_limits<uint32_t>::max();
}
......@@ -234,7 +243,7 @@ namespace vkcv
1);
if(m_Context.m_Device.createFramebuffer(&createInfo, nullptr, &framebuffer) != vk::Result::eSuccess)
{
std::cout << "FAILED TO CREATE TEMPORARY FRAMEBUFFER!" << std::endl;
vkcv_log(LogLevel::ERROR, "Failed to create temporary framebuffer");
return;
}
......@@ -298,6 +307,40 @@ namespace vkcv
recordCommandsToStream(cmdStreamHandle, submitFunction, finishFunction);
}
void Core::recordComputeDispatchToCmdStream(
CommandStreamHandle cmdStreamHandle,
PipelineHandle computePipeline,
const uint32_t dispatchCount[3],
const std::vector<DescriptorSetUsage>& descriptorSetUsages,
const PushConstantData& pushConstantData) {
auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
const auto pipelineLayout = m_PipelineManager->getVkPipelineLayout(computePipeline);
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_PipelineManager->getVkPipeline(computePipeline));
for (const auto& usage : descriptorSetUsages) {
cmdBuffer.bindDescriptorSets(
vk::PipelineBindPoint::eCompute,
pipelineLayout,
usage.setLocation,
{ usage.vulkanHandle },
{});
}
if (pushConstantData.sizePerDrawcall > 0) {
cmdBuffer.pushConstants(
pipelineLayout,
vk::ShaderStageFlagBits::eCompute,
0,
pushConstantData.sizePerDrawcall,
pushConstantData.data);
}
cmdBuffer.dispatch(dispatchCount[0], dispatchCount[1], dispatchCount[2]);
};
recordCommandsToStream(cmdStreamHandle, submitFunction, nullptr);
}
void Core::endFrame() {
if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
return;
......@@ -325,7 +368,7 @@ namespace vkcv
}
if (result != vk::Result::eSuccess) {
std::cout << "Error: swapchain present failed... " << vk::to_string(result) << std::endl;
vkcv_log(LogLevel::ERROR, "Swapchain present failed (%s)", vk::to_string(result).c_str());
}
}
......@@ -402,10 +445,9 @@ namespace vkcv
return m_DescriptorManager->createDescriptorSet(bindings);
}
void Core::writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites &writes) {
m_DescriptorManager->writeResourceDescription(
handle,
setIndex,
void Core::writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites &writes) {
m_DescriptorManager->writeDescriptorSet(
handle,
writes,
*m_ImageManager,
*m_BufferManager,
......
#include "DescriptorManager.hpp"
#include "vkcv/Logger.hpp"
namespace vkcv
{
DescriptorManager::DescriptorManager(vk::Device device) noexcept:
......@@ -53,7 +55,7 @@ namespace vkcv
vk::DescriptorSetLayoutCreateInfo layoutInfo({}, setBindings);
if(m_Device.createDescriptorSetLayout(&layoutInfo, nullptr, &set.layout) != vk::Result::eSuccess)
{
std::cout << "FAILED TO CREATE DESCRIPTOR SET LAYOUT" << std::endl;
vkcv_log(LogLevel::ERROR, "Failed to create descriptor set layout");
return DescriptorSetHandle();
};
......@@ -69,10 +71,10 @@ namespace vkcv
result = m_Device.allocateDescriptorSets(&allocInfo, &set.vulkanHandle);
}
if (result != vk::Result::eSuccess) {
std::cout << "FAILED TO ALLOCATE DESCRIPTOR SET" << std::endl;
std::cout << vk::to_string(result) << std::endl;
vkcv_log(LogLevel::ERROR, "Failed to create descriptor set (%s)",
vk::to_string(result).c_str());
m_Device.destroy(set.layout);
return DescriptorSetHandle();
}
};
......@@ -90,9 +92,8 @@ namespace vkcv
vk::DescriptorType type;
};
void DescriptorManager::writeResourceDescription(
void DescriptorManager::writeDescriptorSet(
const DescriptorSetHandle &handle,
size_t setIndex,
const DescriptorWrites &writes,
const ImageManager &imageManager,
const BufferManager &bufferManager,
......@@ -239,7 +240,7 @@ namespace vkcv
case DescriptorType::IMAGE_STORAGE:
return vk::DescriptorType::eStorageImage;
default:
std::cerr << "Error: DescriptorManager::convertDescriptorTypeFlag, unknown DescriptorType" << std::endl;
vkcv_log(LogLevel::ERROR, "Unknown DescriptorType");
return vk::DescriptorType::eUniformBuffer;
}
}
......@@ -266,7 +267,7 @@ namespace vkcv
void DescriptorManager::destroyDescriptorSetById(uint64_t id) {
if (id >= m_DescriptorSets.size()) {
std::cerr << "Error: DescriptorManager::destroyResourceDescriptionById invalid id" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid id");
return;
}
......@@ -282,7 +283,7 @@ namespace vkcv
vk::DescriptorPool pool;
if (m_Device.createDescriptorPool(&m_PoolInfo, nullptr, &pool) != vk::Result::eSuccess)
{
std::cout << "FAILED TO ALLOCATE DESCRIPTOR POOL." << std::endl;
vkcv_log(LogLevel::WARNING, "Failed to allocate descriptor pool");
pool = nullptr;
};
m_Pools.push_back(pool);
......
......@@ -23,9 +23,8 @@ namespace vkcv
DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &descriptorBindings);
void writeResourceDescription(
void writeDescriptorSet(
const DescriptorSetHandle &handle,
size_t setIndex,
const DescriptorWrites &writes,
const ImageManager &imageManager,
const BufferManager &bufferManager,
......
......@@ -6,6 +6,7 @@
#include "ImageManager.hpp"
#include "vkcv/Core.hpp"
#include "ImageLayoutTransitions.hpp"
#include "vkcv/Logger.hpp"
#include <algorithm>
......@@ -206,7 +207,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::getVulkanImage invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return nullptr;
}
......@@ -219,7 +220,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::getVulkanDeviceMemory invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return nullptr;
}
......@@ -232,7 +233,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::getVulkanImageView invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return nullptr;
}
......@@ -245,7 +246,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::switchImageLayout invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return;
}
......@@ -280,7 +281,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::switchImageLayout invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return;
}
......@@ -295,7 +296,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::fillImage invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return;
}
......@@ -369,7 +370,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::getImageWidth invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return 0;
}
......@@ -382,7 +383,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::getImageHeight invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return 0;
}
......@@ -395,7 +396,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::getImageDepth invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return 0;
}
......@@ -407,7 +408,7 @@ namespace vkcv {
void ImageManager::destroyImageById(uint64_t id)
{
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::destroyImageById invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return;
}
......@@ -436,7 +437,7 @@ namespace vkcv {
const uint64_t id = handle.getId();
if (id >= m_images.size()) {
std::cerr << "Error: ImageManager::destroyImageById invalid handle" << std::endl;
vkcv_log(LogLevel::ERROR, "Invalid handle");
return vk::Format::eUndefined;
}
......
#include "PipelineManager.hpp"
#include "vkcv/Image.hpp"
#include "vkcv/Logger.hpp"
namespace vkcv
{
......@@ -20,15 +21,25 @@ namespace vkcv
// currently assuming default 32 bit formats, no lower precision or normalized variants supported
vk::Format vertexFormatToVulkanFormat(const VertexFormat format) {
switch (format) {
case VertexFormat::FLOAT: return vk::Format::eR32Sfloat;
case VertexFormat::FLOAT2: return vk::Format::eR32G32Sfloat;
case VertexFormat::FLOAT3: return vk::Format::eR32G32B32Sfloat;
case VertexFormat::FLOAT4: return vk::Format::eR32G32B32A32Sfloat;
case VertexFormat::INT: return vk::Format::eR32Sint;
case VertexFormat::INT2: return vk::Format::eR32G32Sint;
case VertexFormat::INT3: return vk::Format::eR32G32B32Sint;
case VertexFormat::INT4: return vk::Format::eR32G32B32A32Sint;
default: std::cerr << "Warning: Unknown vertex format" << std::endl; return vk::Format::eUndefined;
case VertexFormat::FLOAT:
return vk::Format::eR32Sfloat;
case VertexFormat::FLOAT2:
return vk::Format::eR32G32Sfloat;
case VertexFormat::FLOAT3:
return vk::Format::eR32G32B32Sfloat;
case VertexFormat::FLOAT4:
return vk::Format::eR32G32B32A32Sfloat;
case VertexFormat::INT:
return vk::Format::eR32Sint;
case VertexFormat::INT2:
return vk::Format::eR32G32Sint;
case VertexFormat::INT3:
return vk::Format::eR32G32B32Sint;
case VertexFormat::INT4:
return vk::Format::eR32G32B32A32Sint;
default:
vkcv_log(LogLevel::WARNING, "Unknown vertex format");
return vk::Format::eUndefined;
}
}
......@@ -40,7 +51,7 @@ namespace vkcv
const bool existsFragmentShader = config.m_ShaderProgram.existsShader(ShaderStage::FRAGMENT);
if (!(existsVertexShader && existsFragmentShader))
{
std::cout << "Core::createGraphicsPipeline requires vertex and fragment shader code" << std::endl;
vkcv_log(LogLevel::ERROR, "Requires vertex and fragment shader code");
return PipelineHandle();
}
......@@ -182,6 +193,7 @@ namespace vkcv
{},
(config.m_DescriptorLayouts),
(pushConstantRange));
vk::PipelineLayout vkPipelineLayout{};
if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)
{
......@@ -314,4 +326,65 @@ namespace vkcv
return m_Configs.at(id);
}
PipelineHandle PipelineManager::createComputePipeline(
const ShaderProgram &shaderProgram,
const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
// Temporally handing over the Shader Program instead of a pipeline config
vk::ShaderModule computeModule{};
if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess)
return PipelineHandle();
vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo(
{},
vk::ShaderStageFlagBits::eCompute,
computeModule,
"main",
nullptr
);
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts);
const size_t pushConstantSize = shaderProgram.getPushConstantSize();
vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize);
if (pushConstantSize > 0) {
pipelineLayoutCreateInfo.setPushConstantRangeCount(1);
pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange);
}
vk::PipelineLayout vkPipelineLayout{};
if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)
{
m_Device.destroy(computeModule);
return PipelineHandle();
}
vk::ComputePipelineCreateInfo computePipelineCreateInfo{};
computePipelineCreateInfo.stage = pipelineComputeShaderStageInfo;
computePipelineCreateInfo.layout = vkPipelineLayout;
vk::Pipeline vkPipeline;
if (m_Device.createComputePipelines(nullptr, 1, &computePipelineCreateInfo, nullptr, &vkPipeline)!= vk::Result::eSuccess)
{
m_Device.destroy(computeModule);
return PipelineHandle();
}
m_Device.destroy(computeModule);
const uint64_t id = m_Pipelines.size();
m_Pipelines.push_back({ vkPipeline, vkPipelineLayout });
return PipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); });
}
// There is an issue for refactoring the Pipeline Manager.
// While including Compute Pipeline Creation, some private helper functions where introduced:
vk::Result PipelineManager::createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, const ShaderStage stage)
{
std::vector<char> code = shaderProgram.getShader(stage).shaderCode;
vk::ShaderModuleCreateInfo moduleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data()));
return m_Device.createShaderModule(&moduleInfo, nullptr, &module);
}
}
\ No newline at end of file
......@@ -21,7 +21,9 @@ namespace vkcv
std::vector<PipelineConfig> m_Configs;
void destroyPipelineById(uint64_t id);
vk::Result createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, ShaderStage stage);
public:
PipelineManager() = delete; // no default ctor
explicit PipelineManager(vk::Device device) noexcept; // ctor
......@@ -35,6 +37,10 @@ namespace vkcv
PipelineHandle createPipeline(const PipelineConfig &config, PassManager& passManager);
PipelineHandle createComputePipeline(
const ShaderProgram& shaderProgram,
const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts);
[[nodiscard]]
vk::Pipeline getVkPipeline(const PipelineHandle &handle) const;
......
......@@ -4,7 +4,7 @@
#include <iostream>
#include "vkcv/QueueManager.hpp"
#include "vkcv/Logger.hpp"
namespace vkcv {
......@@ -95,7 +95,8 @@ namespace vkcv {
found = true;
}
}
std::cerr << "Warning: not enough \"" << vk::to_string(qFlag) << "\"-Queues." << std::endl;
vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
}
break;
case vk::QueueFlagBits::eCompute:
......@@ -116,7 +117,8 @@ namespace vkcv {
found = true;
}
}
std::cerr << "Warning: not enough \"" << vk::to_string(qFlag) << "\"-Queues." << std::endl;
vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
}
break;
case vk::QueueFlagBits::eTransfer:
......@@ -137,7 +139,8 @@ namespace vkcv {
found = true;
}
}
std::cerr << "Warning: not enough \"" << vk::to_string(qFlag) << "\"-Queues." << std::endl;
vkcv_log(LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str());
}
break;
default:
......