Skip to content
Snippets Groups Projects
Verified Commit 9f3c4023 authored by Tobias Frisch's avatar Tobias Frisch
Browse files

Adjust mesh shader example to use EXT extension

parent df985b6d
Branches
No related tags found
1 merge request!111Resolve "Cross vendor mesh shader support"
struct ObjectMatrices{ struct ObjectMatrices {
mat4 model; mat4 model;
mat4 mvp; mat4 mvp;
}; };
\ No newline at end of file
struct Meshlet{
uint vertexOffset; struct Task {
uint vertexCount; uint meshletIndices[32];
uint indexOffset; mat4 mvp;
uint indexCount; };
vec3 meanPosition;
float boundingSphereRadius; struct Meshlet {
}; uint vertexOffset;
\ No newline at end of file uint vertexCount;
uint indexOffset;
uint indexCount;
vec3 meanPosition;
float boundingSphereRadius;
};
#version 450 #version 450
#extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 passNormal; layout(location = 0) in vec3 passNormal;
layout(location = 1) in flat uint passTaskIndex; layout(location = 1) in flat uint passTaskIndex;
layout(location = 0) out vec3 outColor; layout(location = 0) out vec3 outColor;
uint lowbias32(uint x) uint lowbias32(uint x) {
{
x ^= x >> 16; x ^= x >> 16;
x *= 0x7feb352dU; x *= 0x7feb352dU;
x ^= x >> 15; x ^= x >> 15;
...@@ -15,15 +15,16 @@ uint lowbias32(uint x) ...@@ -15,15 +15,16 @@ uint lowbias32(uint x)
return x; return x;
} }
float hashToFloat(uint hash){ float hashToFloat(uint hash) {
return (hash % 255) / 255.f; return (hash % 255) / 255.f;
} }
vec3 colorFromIndex(uint i){ vec3 colorFromIndex(uint i) {
return vec3( return vec3(
hashToFloat(lowbias32(i+0)), hashToFloat(lowbias32(i+0)),
hashToFloat(lowbias32(i+1)), hashToFloat(lowbias32(i+1)),
hashToFloat(lowbias32(i+2))); hashToFloat(lowbias32(i+2))
);
} }
void main() { void main() {
......
...@@ -13,32 +13,25 @@ layout(max_vertices=64, max_primitives=126) out; ...@@ -13,32 +13,25 @@ layout(max_vertices=64, max_primitives=126) out;
layout(location = 0) out vec3 passNormal[]; layout(location = 0) out vec3 passNormal[];
layout(location = 1) out uint passTaskIndex[]; layout(location = 1) out uint passTaskIndex[];
struct Vertex struct Vertex {
{ vec3 position;
vec3 position; float padding0; float padding0;
vec3 normal; float padding1; vec3 normal;
float padding1;
}; };
layout(std430, binding = 0) readonly buffer vertexBuffer layout(std430, binding = 0) readonly buffer vertexBuffer {
{
Vertex vertices[]; Vertex vertices[];
}; };
layout(std430, binding = 1) readonly buffer indexBuffer layout(std430, binding = 1) readonly buffer indexBuffer {
{
uint localIndices[]; // breaks for 16 bit indices uint localIndices[]; // breaks for 16 bit indices
}; };
layout(std430, binding = 2) readonly buffer meshletBuffer layout(std430, binding = 2) readonly buffer meshletBuffer {
{
Meshlet meshlets[]; Meshlet meshlets[];
}; };
struct Task {
uint meshletIndices[32];
mat4 mvp;
};
taskPayloadSharedEXT Task IN; taskPayloadSharedEXT Task IN;
void main() { void main() {
...@@ -46,17 +39,16 @@ void main() { ...@@ -46,17 +39,16 @@ void main() {
Meshlet meshlet = meshlets[meshletIndex]; Meshlet meshlet = meshlets[meshletIndex];
// set vertices // set vertices
for(uint i = 0; i < 2; i++){ for (uint i = 0; i < 2; i++) {
uint workIndex = gl_LocalInvocationID.x + 32 * i; uint workIndex = gl_LocalInvocationID.x + 32 * i;
if(workIndex >= meshlet.vertexCount){ if (workIndex >= meshlet.vertexCount) {
break; break;
} }
uint vertexIndex = meshlet.vertexOffset + workIndex; uint vertexIndex = meshlet.vertexOffset + workIndex;
Vertex vertex = vertices[vertexIndex]; Vertex vertex = vertices[vertexIndex];
gl_MeshVerticesEXT[workIndex].gl_Position = IN.mvp * vec4(vertex.position, 1); gl_MeshVerticesEXT[workIndex].gl_Position = IN.mvp * vec4(vertex.position, 1);
passNormal[workIndex] = vertex.normal; passNormal[workIndex] = vertex.normal;
passTaskIndex[workIndex] = meshletIndex; passTaskIndex[workIndex] = meshletIndex;
} }
...@@ -64,7 +56,7 @@ void main() { ...@@ -64,7 +56,7 @@ void main() {
// set local indices // set local indices
for (uint i = 0; i < 12; i++) { for (uint i = 0; i < 12; i++) {
uint workIndex = gl_LocalInvocationID.x + i * 32; uint workIndex = gl_LocalInvocationID.x + i * 32;
if(workIndex >= meshlet.indexCount){ if (workIndex >= meshlet.indexCount) {
break; break;
} }
......
...@@ -8,37 +8,30 @@ ...@@ -8,37 +8,30 @@
layout(local_size_x=32, local_size_y=1, local_size_z=1) in; layout(local_size_x=32, local_size_y=1, local_size_z=1) in;
struct Task {
uint meshletIndices[32];
mat4 mvp;
};
taskPayloadSharedEXT Task OUT; taskPayloadSharedEXT Task OUT;
layout( push_constant ) uniform constants{ layout( push_constant ) uniform constants {
uint matrixIndex;
uint meshletCount; uint meshletCount;
uint matrixIndex;
}; };
// TODO: reuse mesh stage binding at location 2 after required fix in framework // TODO: reuse mesh stage binding at location 2 after required fix in framework
layout(std430, binding = 5) readonly buffer meshletBuffer layout(std430, binding = 5) readonly buffer meshletBuffer {
{
Meshlet meshlets[]; Meshlet meshlets[];
}; };
struct Plane{ struct Plane {
vec3 pointOnPlane; vec3 pointOnPlane;
float padding0; float padding0;
vec3 normal; vec3 normal;
float padding1; float padding1;
}; };
layout(set=0, binding=3, std140) uniform cameraPlaneBuffer{ layout(set=0, binding = 3, std140) uniform cameraPlaneBuffer {
Plane cameraPlanes[6]; Plane cameraPlanes[6];
}; };
layout(std430, binding = 4) readonly buffer matrixBuffer layout(std430, binding = 4) readonly buffer matrixBuffer {
{
ObjectMatrices objectMatrices[]; ObjectMatrices objectMatrices[];
}; };
...@@ -46,9 +39,9 @@ shared uint taskCount; ...@@ -46,9 +39,9 @@ shared uint taskCount;
bool isSphereInsideFrustum(vec3 spherePos, float sphereRadius, Plane cameraPlanes[6]){ bool isSphereInsideFrustum(vec3 spherePos, float sphereRadius, Plane cameraPlanes[6]){
bool isInside = true; bool isInside = true;
for(int i = 0; i < 6; i++){ for (int i = 0; i < 6; i++) {
Plane p = cameraPlanes[i]; Plane p = cameraPlanes[i];
isInside = isInside && dot(p.normal, spherePos - p.pointOnPlane) - sphereRadius < 0; isInside = isInside && dot(p.normal, spherePos - p.pointOnPlane) - sphereRadius < 0;
} }
return isInside; return isInside;
} }
...@@ -64,6 +57,8 @@ void main() { ...@@ -64,6 +57,8 @@ void main() {
if (gl_LocalInvocationID.x == 0) { if (gl_LocalInvocationID.x == 0) {
taskCount = 0; taskCount = 0;
} }
memoryBarrierShared();
// TODO: scaling support // TODO: scaling support
vec3 meshletPositionWorld = (vec4(meshlet.meanPosition, 1) * objectMatrices[matrixIndex].model).xyz; vec3 meshletPositionWorld = (vec4(meshlet.meanPosition, 1) * objectMatrices[matrixIndex].model).xyz;
...@@ -72,6 +67,8 @@ void main() { ...@@ -72,6 +67,8 @@ void main() {
OUT.meshletIndices[outIndex] = gl_GlobalInvocationID.x; OUT.meshletIndices[outIndex] = gl_GlobalInvocationID.x;
} }
memoryBarrierShared();
if (gl_LocalInvocationID.x == 0) { if (gl_LocalInvocationID.x == 0) {
OUT.mvp = objectMatrices[matrixIndex].mvp; OUT.mvp = objectMatrices[matrixIndex].mvp;
EmitMeshTasksEXT(taskCount, 1, 1); EmitMeshTasksEXT(taskCount, 1, 1);
......
...@@ -8,22 +8,20 @@ layout(location = 0) in vec3 inPosition; ...@@ -8,22 +8,20 @@ layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal; layout(location = 1) in vec3 inNormal;
layout(location = 0) out vec3 passNormal; layout(location = 0) out vec3 passNormal;
layout(location = 1) out uint dummyOutput; layout(location = 1) out flat uint passTaskIndex;
layout(std430, binding = 0) readonly buffer matrixBuffer layout(std430, binding = 0) readonly buffer matrixBuffer {
{
ObjectMatrices objectMatrices[]; ObjectMatrices objectMatrices[];
}; };
layout( push_constant ) uniform constants{ layout( push_constant ) uniform constants {
uint matrixIndex;
uint padding; // pad to same size as mesh shader constants uint padding; // pad to same size as mesh shader constants
uint matrixIndex;
}; };
void main() { void main() {
gl_Position = objectMatrices[matrixIndex].mvp * vec4(inPosition, 1.0); passNormal = inNormal;
passNormal = inNormal; passTaskIndex = 0;
dummyOutput = padding * 0; // padding must be used, else compiler shrinks constant size gl_Position = objectMatrices[matrixIndex].mvp * vec4(inPosition, 1.0);
} }
\ No newline at end of file
...@@ -94,8 +94,10 @@ int main(int argc, const char** argv) { ...@@ -94,8 +94,10 @@ int main(int argc, const char** argv) {
applicationName, applicationName,
VK_MAKE_VERSION(0, 0, 1), VK_MAKE_VERSION(0, 0, 1),
{ vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute },
features features,
{ VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME }
); );
vkcv::WindowHandle windowHandle = core.createWindow(applicationName, 1280, 720, true); vkcv::WindowHandle windowHandle = core.createWindow(applicationName, 1280, 720, true);
vkcv::Window &window = core.getWindow(windowHandle); vkcv::Window &window = core.getWindow(windowHandle);
...@@ -106,7 +108,6 @@ int main(int argc, const char** argv) { ...@@ -106,7 +108,6 @@ int main(int argc, const char** argv) {
vkcv::asset::loadScene(path, mesh); vkcv::asset::loadScene(path, mesh);
assert(!mesh.vertexGroups.empty()); assert(!mesh.vertexGroups.empty());
auto vertexBuffer = vkcv::buffer<uint8_t>( auto vertexBuffer = vkcv::buffer<uint8_t>(
core, core,
vkcv::BufferType::VERTEX, vkcv::BufferType::VERTEX,
...@@ -199,7 +200,7 @@ int main(int argc, const char** argv) { ...@@ -199,7 +200,7 @@ int main(int argc, const char** argv) {
} }
vkcv::ShaderProgram bunnyShaderProgram{}; vkcv::ShaderProgram bunnyShaderProgram{};
vkcv::shader::GLSLCompiler compiler (vkcv::shader::GLSLCompileTarget::MESH_SHADING); vkcv::shader::GLSLCompiler compiler;
compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("assets/shaders/shader.vert"), compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("assets/shaders/shader.vert"),
[&bunnyShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { [&bunnyShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
...@@ -249,17 +250,19 @@ int main(int argc, const char** argv) { ...@@ -249,17 +250,19 @@ int main(int argc, const char** argv) {
// mesh shader // mesh shader
vkcv::ShaderProgram meshShaderProgram; vkcv::ShaderProgram meshShaderProgram;
compiler.compile(vkcv::ShaderStage::TASK, std::filesystem::path("assets/shaders/shader.task"), vkcv::shader::GLSLCompiler mesh_compiler (vkcv::shader::GLSLCompileTarget::MESH_SHADING);
mesh_compiler.compile(vkcv::ShaderStage::TASK, std::filesystem::path("assets/shaders/shader.task"),
[&meshShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { [&meshShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
meshShaderProgram.addShader(shaderStage, path); meshShaderProgram.addShader(shaderStage, path);
}); });
compiler.compile(vkcv::ShaderStage::MESH, std::filesystem::path("assets/shaders/shader.mesh"), mesh_compiler.compile(vkcv::ShaderStage::MESH, std::filesystem::path("assets/shaders/shader.mesh"),
[&meshShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { [&meshShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
meshShaderProgram.addShader(shaderStage, path); meshShaderProgram.addShader(shaderStage, path);
}); });
compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("assets/shaders/shader.frag"), mesh_compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("assets/shaders/shader.frag"),
[&meshShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { [&meshShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
meshShaderProgram.addShader(shaderStage, path); meshShaderProgram.addShader(shaderStage, path);
}); });
...@@ -343,11 +346,15 @@ int main(int argc, const char** argv) { ...@@ -343,11 +346,15 @@ int main(int argc, const char** argv) {
matrixBuffer.fill({ objectMatrices }); matrixBuffer.fill({ objectMatrices });
struct PushConstants { struct MeshletPushConstants {
uint32_t matrixIndex;
uint32_t meshletCount; uint32_t meshletCount;
uint32_t matrixIndex;
};
MeshletPushConstants pushConstants {
static_cast<uint32_t>(meshShaderModelData.meshlets.size()),
0
}; };
PushConstants pushConstants{ 0, static_cast<uint32_t>(meshShaderModelData.meshlets.size()) };
if (updateFrustumPlanes) { if (updateFrustumPlanes) {
const CameraPlanes cameraPlanes = computeCameraPlanes(camera); const CameraPlanes cameraPlanes = computeCameraPlanes(camera);
...@@ -357,7 +364,7 @@ int main(int argc, const char** argv) { ...@@ -357,7 +364,7 @@ int main(int argc, const char** argv) {
const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
vkcv::PushConstants pushConstantData = vkcv::pushConstants<PushConstants>(); vkcv::PushConstants pushConstantData = vkcv::pushConstants<MeshletPushConstants>();
pushConstantData.appendDrawcall(pushConstants); pushConstantData.appendDrawcall(pushConstants);
if (useMeshShader) { if (useMeshShader) {
...@@ -378,14 +385,14 @@ int main(int argc, const char** argv) { ...@@ -378,14 +385,14 @@ int main(int argc, const char** argv) {
vkcv::InstanceDrawcall drawcall (vertexData); vkcv::InstanceDrawcall drawcall (vertexData);
drawcall.useDescriptorSet(0, vertexShaderDescriptorSet); drawcall.useDescriptorSet(0, vertexShaderDescriptorSet);
core.recordDrawcallsToCmdStream( /*core.recordDrawcallsToCmdStream(
cmdStream, cmdStream,
bunnyPipeline, bunnyPipeline,
pushConstantData, pushConstantData,
{ drawcall }, { drawcall },
{ renderTargets }, { renderTargets },
windowHandle windowHandle
); );*/
} }
core.prepareSwapchainImageForPresent(cmdStream); core.prepareSwapchainImageForPresent(cmdStream);
......
...@@ -132,17 +132,24 @@ namespace vkcv { ...@@ -132,17 +132,24 @@ namespace vkcv {
assert(outCreateInfo); assert(outCreateInfo);
std::vector<uint32_t> code = shaderProgram.getShaderBinary(stage); std::vector<uint32_t> code = shaderProgram.getShaderBinary(stage);
vk::ShaderModuleCreateInfo vertexModuleInfo({}, code.size() * sizeof(uint32_t), vk::ShaderModuleCreateInfo vertexModuleInfo(
code.data()); {},
code.size() * sizeof(uint32_t),
code.data()
);
vk::ShaderModule shaderModule; vk::ShaderModule shaderModule;
if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule) if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule)
!= vk::Result::eSuccess) != vk::Result::eSuccess)
return false; return false;
const static auto entryName = "main"; const static auto entryName = "main";
*outCreateInfo = vk::PipelineShaderStageCreateInfo(
*outCreateInfo = vk::PipelineShaderStageCreateInfo({}, shaderStageToVkShaderStage(stage), vk::PipelineShaderStageCreateFlags(),
shaderModule, entryName, nullptr); shaderStageToVkShaderStage(stage),
shaderModule,
entryName,
nullptr
);
return true; return true;
} }
...@@ -157,7 +164,8 @@ namespace vkcv { ...@@ -157,7 +164,8 @@ namespace vkcv {
static void fillVertexInputDescription( static void fillVertexInputDescription(
std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions, std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions,
std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions, std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions,
const bool existsVertexShader, const GraphicsPipelineConfig &config) { const bool existsVertexShader,
const GraphicsPipelineConfig &config) {
if (existsVertexShader) { if (existsVertexShader) {
const VertexLayout &layout = config.getVertexLayout(); const VertexLayout &layout = config.getVertexLayout();
...@@ -214,7 +222,9 @@ namespace vkcv { ...@@ -214,7 +222,9 @@ namespace vkcv {
static vk::PipelineTessellationStateCreateInfo static vk::PipelineTessellationStateCreateInfo
createPipelineTessellationStateCreateInfo(const GraphicsPipelineConfig &config) { createPipelineTessellationStateCreateInfo(const GraphicsPipelineConfig &config) {
vk::PipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo( vk::PipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo(
{}, config.getTesselationControlPoints()); {},
config.getTesselationControlPoints()
);
return pipelineTessellationStateCreateInfo; return pipelineTessellationStateCreateInfo;
} }
...@@ -235,8 +245,13 @@ namespace vkcv { ...@@ -235,8 +245,13 @@ namespace vkcv {
scissor = vk::Rect2D({ 0, 0 }, { config.getWidth(), config.getHeight() }); scissor = vk::Rect2D({ 0, 0 }, { config.getWidth(), config.getHeight() });
vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo({}, 1, &viewport, 1, vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(
&scissor); {},
1,
&viewport,
1,
&scissor
);
return pipelineViewportStateCreateInfo; return pipelineViewportStateCreateInfo;
} }
...@@ -276,8 +291,18 @@ namespace vkcv { ...@@ -276,8 +291,18 @@ namespace vkcv {
} }
vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo( vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo(
{}, config.isDepthClampingEnabled(), false, vk::PolygonMode::eFill, cullMode, {},
vk::FrontFace::eCounterClockwise, false, 0.f, 0.f, 0.f, 1.f); config.isDepthClampingEnabled(),
false,
vk::PolygonMode::eFill,
cullMode,
vk::FrontFace::eCounterClockwise,
false,
0.f,
0.f,
0.f,
1.f
);
static vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization; static vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization;
...@@ -376,11 +401,17 @@ namespace vkcv { ...@@ -376,11 +401,17 @@ namespace vkcv {
static vk::PushConstantRange pushConstantRange; static vk::PushConstantRange pushConstantRange;
const size_t pushConstantsSize = config.getShaderProgram().getPushConstantsSize(); const size_t pushConstantsSize = config.getShaderProgram().getPushConstantsSize();
pushConstantRange = pushConstantRange = vk::PushConstantRange(
vk::PushConstantRange(vk::ShaderStageFlagBits::eAll, 0, pushConstantsSize); vk::ShaderStageFlagBits::eAll,
0,
pushConstantsSize
);
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, (descriptorSetLayouts), vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo (
(pushConstantRange)); vk::PipelineLayoutCreateFlags(),
descriptorSetLayouts,
pushConstantRange
);
if (pushConstantsSize == 0) { if (pushConstantsSize == 0) {
pipelineLayoutCreateInfo.pushConstantRangeCount = 0; pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
...@@ -397,9 +428,17 @@ namespace vkcv { ...@@ -397,9 +428,17 @@ namespace vkcv {
static vk::PipelineDepthStencilStateCreateInfo static vk::PipelineDepthStencilStateCreateInfo
createPipelineDepthStencilStateCreateInfo(const GraphicsPipelineConfig &config) { createPipelineDepthStencilStateCreateInfo(const GraphicsPipelineConfig &config) {
const vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilCreateInfo( const vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilCreateInfo(
vk::PipelineDepthStencilStateCreateFlags(), config.getDepthTest() != DepthTest::None, vk::PipelineDepthStencilStateCreateFlags(),
config.isWritingDepth(), depthTestToVkCompareOp(config.getDepthTest()), false, false, config.getDepthTest() != DepthTest::None,
{}, {}, 0.0f, 1.0f); config.isWritingDepth(),
depthTestToVkCompareOp(config.getDepthTest()),
false,
false,
{},
{},
0.0f,
1.0f
);
return pipelineDepthStencilCreateInfo; return pipelineDepthStencilCreateInfo;
} }
...@@ -449,7 +488,7 @@ namespace vkcv { ...@@ -449,7 +488,7 @@ namespace vkcv {
|| (existsTaskShader && existsMeshShader)); || (existsTaskShader && existsMeshShader));
if (!validGeometryStages) { if (!validGeometryStages) {
vkcv_log(LogLevel::ERROR, "Requires vertex or task and mesh shader"); vkcv_log(LogLevel::ERROR, "Requires a valid geometry shader stage");
return {}; return {};
} }
...@@ -613,13 +652,16 @@ namespace vkcv { ...@@ -613,13 +652,16 @@ namespace vkcv {
} }
// pipeline layout // pipeline layout
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = createPipelineLayoutCreateInfo(
createPipelineLayoutCreateInfo(config, descriptorSetLayouts); config,
descriptorSetLayouts
);
vk::PipelineLayout vkPipelineLayout {}; const auto& pipelineLayout = (
if (getCore().getContext().getDevice().createPipelineLayout(&pipelineLayoutCreateInfo, getCore().getContext().getDevice().createPipelineLayout(pipelineLayoutCreateInfo)
nullptr, &vkPipelineLayout) );
!= vk::Result::eSuccess) {
if (!pipelineLayout) {
destroyShaderModules(); destroyShaderModules();
return {}; return {};
} }
...@@ -637,33 +679,50 @@ namespace vkcv { ...@@ -637,33 +679,50 @@ namespace vkcv {
break; break;
} }
} }
const bool usesTesselation = (
existsTessellationControlShader &&
existsTessellationEvaluationShader
);
// Get all setting structs together and create the Pipeline // Get all setting structs together and create the Pipeline
const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(
{}, static_cast<uint32_t>(shaderStages.size()), shaderStages.data(), {},
&pipelineVertexInputStateCreateInfo, static_cast<uint32_t>(shaderStages.size()),
&pipelineInputAssemblyStateCreateInfo, shaderStages.data(),
&pipelineTessellationStateCreateInfo, existsVertexShader? &pipelineVertexInputStateCreateInfo : nullptr,
existsVertexShader? &pipelineInputAssemblyStateCreateInfo : nullptr,
usesTesselation? &pipelineTessellationStateCreateInfo : nullptr,
&pipelineViewportStateCreateInfo, &pipelineViewportStateCreateInfo,
&pipelineRasterizationStateCreateInfo, &pipelineRasterizationStateCreateInfo,
&pipelineMultisampleStateCreateInfo, &pipelineMultisampleStateCreateInfo,
p_depthStencilCreateInfo, p_depthStencilCreateInfo,
&pipelineColorBlendStateCreateInfo, &pipelineColorBlendStateCreateInfo,
&dynamicStateCreateInfo, &dynamicStateCreateInfo,
vkPipelineLayout, pipelineLayout,
pass, pass,
0, 0,
{}, {},
0 0
); );
vk::Pipeline vkPipeline {}; vkcv_log(LogLevel::RAW_INFO, "STAGES: %lu", shaderStages.size());
if (getCore().getContext().getDevice().createGraphicsPipelines( for (const auto& shaderStage : shaderStages) {
nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) vkcv_log(LogLevel::RAW_INFO, "STAGE: %s %s %s",
!= vk::Result::eSuccess) { shaderStage.pName,
vk::to_string(shaderStage.stage).c_str(),
vk::to_string(shaderStage.flags).c_str()
);
}
auto pipelineResult = getCore().getContext().getDevice().createGraphicsPipeline(
nullptr, graphicsPipelineCreateInfo
);
if (pipelineResult.result != vk::Result::eSuccess) {
// Catch runtime error if the creation of the pipeline fails. // Catch runtime error if the creation of the pipeline fails.
// Destroy everything to keep the memory clean. // Destroy everything to keep the memory clean.
getCore().getContext().getDevice().destroy(vkPipelineLayout); getCore().getContext().getDevice().destroy(pipelineLayout);
destroyShaderModules(); destroyShaderModules();
return {}; return {};
} }
...@@ -672,7 +731,7 @@ namespace vkcv { ...@@ -672,7 +731,7 @@ namespace vkcv {
destroyShaderModules(); destroyShaderModules();
// Hand over Handler to main Application // Hand over Handler to main Application
return add({ vkPipeline, vkPipelineLayout, config }); return add({ pipelineResult.value, pipelineLayout, config });
} }
vk::Pipeline vk::Pipeline
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment