Extend set of samples (#296)

+ 12_InitFrameBuffers, 13_InitVertexBuffer, 14_InitPipeline, 15_DrawCube;
+ extend utilities and add utilities on geometries, math, and shaders
+ slightly adjust some other samples
This commit is contained in:
Andreas Süßenbach
2019-03-15 10:40:45 +01:00
committed by Markus Tavenrath
parent 70c837fba2
commit cd8e5283c3
20 changed files with 1372 additions and 211 deletions

View File

@@ -0,0 +1,67 @@
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
struct Vertex
{
float x, y, z, w; // Position
float r, g, b, a; // Color
};
static const Vertex coloredCubeData[] =
{
// red face
{ -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
// green face
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f },
// blue face
{ -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f },
// yellow face
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
// magenta face
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
// cyan face
{ 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
};

31
samples/utils/math.cpp Normal file
View File

@@ -0,0 +1,31 @@
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "math.hpp"
namespace vk
{
namespace su
{
glm::mat4x4 createModelViewProjectionClipMatrix()
{
glm::mat4x4 model = glm::mat4x4(1.0f);
glm::mat4x4 view = glm::lookAt(glm::vec3(-5.0f, 3.0f, -10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f));
glm::mat4x4 projection = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.0f);
glm::mat4x4 clip = glm::mat4x4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f); // vulkan clip space has inverted y and half z !
return clip * projection * view * model;
}
}
}

26
samples/utils/math.hpp Normal file
View File

@@ -0,0 +1,26 @@
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#define GLM_FORCE_RADIANS
#pragma warning(disable:4201) // disable warning C4201: nonstandard extension used: nameless struct/union; needed to get glm/detail/type_vec?.hpp without warnings
#include <glm/gtc/matrix_transform.hpp>
namespace vk
{
namespace su
{
glm::mat4x4 createModelViewProjectionClipMatrix();
}
}

188
samples/utils/shaders.cpp Normal file
View File

@@ -0,0 +1,188 @@
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h"
namespace vk
{
namespace su
{
EShLanguage translateShaderStage(vk::ShaderStageFlagBits stage)
{
switch (stage)
{
case vk::ShaderStageFlagBits::eVertex: return EShLangVertex;
case vk::ShaderStageFlagBits::eTessellationControl: return EShLangTessControl;
case vk::ShaderStageFlagBits::eTessellationEvaluation: return EShLangTessEvaluation;
case vk::ShaderStageFlagBits::eGeometry: return EShLangGeometry;
case vk::ShaderStageFlagBits::eFragment: return EShLangFragment;
case vk::ShaderStageFlagBits::eCompute: return EShLangCompute;
default:
assert(false && "Unknown shader stage");
return EShLangVertex;
}
}
void init(TBuiltInResource & resource)
{
resource.maxLights = 32;
resource.maxClipPlanes = 6;
resource.maxTextureUnits = 32;
resource.maxTextureCoords = 32;
resource.maxVertexAttribs = 64;
resource.maxVertexUniformComponents = 4096;
resource.maxVaryingFloats = 64;
resource.maxVertexTextureImageUnits = 32;
resource.maxCombinedTextureImageUnits = 80;
resource.maxTextureImageUnits = 32;
resource.maxFragmentUniformComponents = 4096;
resource.maxDrawBuffers = 32;
resource.maxVertexUniformVectors = 128;
resource.maxVaryingVectors = 8;
resource.maxFragmentUniformVectors = 16;
resource.maxVertexOutputVectors = 16;
resource.maxFragmentInputVectors = 15;
resource.minProgramTexelOffset = -8;
resource.maxProgramTexelOffset = 7;
resource.maxClipDistances = 8;
resource.maxComputeWorkGroupCountX = 65535;
resource.maxComputeWorkGroupCountY = 65535;
resource.maxComputeWorkGroupCountZ = 65535;
resource.maxComputeWorkGroupSizeX = 1024;
resource.maxComputeWorkGroupSizeY = 1024;
resource.maxComputeWorkGroupSizeZ = 64;
resource.maxComputeUniformComponents = 1024;
resource.maxComputeTextureImageUnits = 16;
resource.maxComputeImageUniforms = 8;
resource.maxComputeAtomicCounters = 8;
resource.maxComputeAtomicCounterBuffers = 1;
resource.maxVaryingComponents = 60;
resource.maxVertexOutputComponents = 64;
resource.maxGeometryInputComponents = 64;
resource.maxGeometryOutputComponents = 128;
resource.maxFragmentInputComponents = 128;
resource.maxImageUnits = 8;
resource.maxCombinedImageUnitsAndFragmentOutputs = 8;
resource.maxCombinedShaderOutputResources = 8;
resource.maxImageSamples = 0;
resource.maxVertexImageUniforms = 0;
resource.maxTessControlImageUniforms = 0;
resource.maxTessEvaluationImageUniforms = 0;
resource.maxGeometryImageUniforms = 0;
resource.maxFragmentImageUniforms = 8;
resource.maxCombinedImageUniforms = 8;
resource.maxGeometryTextureImageUnits = 16;
resource.maxGeometryOutputVertices = 256;
resource.maxGeometryTotalOutputComponents = 1024;
resource.maxGeometryUniformComponents = 1024;
resource.maxGeometryVaryingComponents = 64;
resource.maxTessControlInputComponents = 128;
resource.maxTessControlOutputComponents = 128;
resource.maxTessControlTextureImageUnits = 16;
resource.maxTessControlUniformComponents = 1024;
resource.maxTessControlTotalOutputComponents = 4096;
resource.maxTessEvaluationInputComponents = 128;
resource.maxTessEvaluationOutputComponents = 128;
resource.maxTessEvaluationTextureImageUnits = 16;
resource.maxTessEvaluationUniformComponents = 1024;
resource.maxTessPatchComponents = 120;
resource.maxPatchVertices = 32;
resource.maxTessGenLevel = 64;
resource.maxViewports = 16;
resource.maxVertexAtomicCounters = 0;
resource.maxTessControlAtomicCounters = 0;
resource.maxTessEvaluationAtomicCounters = 0;
resource.maxGeometryAtomicCounters = 0;
resource.maxFragmentAtomicCounters = 8;
resource.maxCombinedAtomicCounters = 8;
resource.maxAtomicCounterBindings = 1;
resource.maxVertexAtomicCounterBuffers = 0;
resource.maxTessControlAtomicCounterBuffers = 0;
resource.maxTessEvaluationAtomicCounterBuffers = 0;
resource.maxGeometryAtomicCounterBuffers = 0;
resource.maxFragmentAtomicCounterBuffers = 1;
resource.maxCombinedAtomicCounterBuffers = 1;
resource.maxAtomicCounterBufferSize = 16384;
resource.maxTransformFeedbackBuffers = 4;
resource.maxTransformFeedbackInterleavedComponents = 64;
resource.maxCullDistances = 8;
resource.maxCombinedClipAndCullDistances = 8;
resource.maxSamples = 4;
resource.limits.nonInductiveForLoops = 1;
resource.limits.whileLoops = 1;
resource.limits.doWhileLoops = 1;
resource.limits.generalUniformIndexing = 1;
resource.limits.generalAttributeMatrixVectorIndexing = 1;
resource.limits.generalVaryingIndexing = 1;
resource.limits.generalSamplerIndexing = 1;
resource.limits.generalVariableIndexing = 1;
resource.limits.generalConstantMatrixVectorIndexing = 1;
}
bool GLSLtoSPV(const vk::ShaderStageFlagBits shaderType, std::string const& glslShader, std::vector<unsigned int> &spvShader)
{
EShLanguage stage = translateShaderStage(shaderType);
const char *shaderStrings[1];
shaderStrings[0] = glslShader.data();
glslang::TShader shader(stage);
shader.setStrings(shaderStrings, 1);
TBuiltInResource resource;
init(resource);
// Enable SPIR-V and Vulkan rules when parsing GLSL
EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
if (!shader.parse(&resource, 100, false, messages))
{
puts(shader.getInfoLog());
puts(shader.getInfoDebugLog());
return false; // something didn't work
}
glslang::TProgram program;
program.addShader(&shader);
//
// Program-level processing...
//
if (!program.link(messages))
{
puts(shader.getInfoLog());
puts(shader.getInfoDebugLog());
fflush(stdout);
return false;
}
glslang::GlslangToSpv(*program.getIntermediate(stage), spvShader);
return true;
}
vk::UniqueShaderModule createShaderModule(vk::UniqueDevice &device, vk::ShaderStageFlagBits shaderStage, std::string const& shaderText)
{
std::vector<unsigned int> shaderSPV;
bool ok = GLSLtoSPV(shaderStage, shaderText, shaderSPV);
assert(ok);
return device->createShaderModuleUnique(vk::ShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), shaderSPV.size() * sizeof(unsigned int), shaderSPV.data()));
}
}
}

69
samples/utils/shaders.hpp Normal file
View File

@@ -0,0 +1,69 @@
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "vulkan/vulkan.hpp"
#include <string>
#include <vector>
namespace vk
{
namespace su
{
vk::UniqueShaderModule createShaderModule(vk::UniqueDevice &device, vk::ShaderStageFlagBits shaderStage, std::string const& shaderText);
bool GLSLtoSPV(const vk::ShaderStageFlagBits shaderType, std::string const& glslShader, std::vector<unsigned int> &spvShader);
}
}
const std::string vertexShaderText = R"(
#version 400
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (std140, binding = 0) uniform bufferVals
{
mat4 mvp;
} myBufferVals;
layout (location = 0) in vec4 pos;
layout (location = 1) in vec4 inColor;
layout (location = 0) out vec4 outColor;
void main()
{
outColor = inColor;
gl_Position = myBufferVals.mvp * pos;
}
)";
const std::string fragmentShaderText = R"(
#version 400
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (location = 0) in vec4 color;
layout (location = 0) out vec4 outColor;
void main()
{
outColor = color;
}
)";

View File

@@ -54,6 +54,12 @@ namespace vk
return device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex));
}
vk::UniqueCommandPool createCommandPool(vk::UniqueDevice &device, uint32_t queueFamilyIndex)
{
vk::CommandPoolCreateInfo commandPoolCreateInfo(vk::CommandPoolCreateFlagBits::eResetCommandBuffer, queueFamilyIndex);
return device->createCommandPoolUnique(commandPoolCreateInfo);
}
vk::UniqueDebugReportCallbackEXT createDebugReportCallback(vk::UniqueInstance &instance)
{
vk::DebugReportFlagsEXT flags(vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning | vk::DebugReportFlagBitsEXT::eError);
@@ -82,6 +88,76 @@ namespace vk
return physicalDevice.createDeviceUnique(deviceCreateInfo);
}
std::vector<vk::UniqueFramebuffer> createFramebuffers(vk::UniqueDevice &device, vk::UniqueRenderPass &renderPass, std::vector<vk::UniqueImageView> const& imageViews, vk::UniqueImageView &depthImageView, int width, int height)
{
vk::ImageView attachments[2];
attachments[1] = depthImageView.get();
std::vector<vk::UniqueFramebuffer> framebuffers;
framebuffers.reserve(imageViews.size());
for (auto const& view : imageViews)
{
attachments[0] = view.get();
framebuffers.push_back(device->createFramebufferUnique(vk::FramebufferCreateInfo(vk::FramebufferCreateFlags(), renderPass.get(), 2, attachments, width, height, 1)));
}
return framebuffers;
}
vk::UniquePipeline createGraphicsPipeline(vk::UniqueDevice &device, vk::UniquePipelineCache &pipelineCache, vk::UniqueShaderModule &vertexShaderModule, vk::UniqueShaderModule &fragmentShaderModule, uint32_t vertexStride, vk::UniquePipelineLayout &pipelineLayout, vk::UniqueRenderPass &renderPass)
{
vk::PipelineShaderStageCreateInfo pipelineShaderStageCreateInfos[2] =
{
vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, vertexShaderModule.get(), "main"),
vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule.get(), "main")
};
vk::VertexInputBindingDescription vertexInputBindingDescription(0, vertexStride);
vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
{
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32A32Sfloat, 0),
vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32A32Sfloat, 16)
};
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(vk::PipelineVertexInputStateCreateFlags(), 1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList);
vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(vk::PipelineViewportStateCreateFlags(), 1, nullptr, 1, nullptr);
vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo(vk::PipelineRasterizationStateCreateFlags(), false, false, vk::PolygonMode::eFill, vk::CullModeFlagBits::eBack, vk::FrontFace::eClockwise, false, 0.0f, 0.0f, 0.0f, 1.0f);
vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo;
vk::StencilOpState stencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways);
vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo(vk::PipelineDepthStencilStateCreateFlags(), true, true, vk::CompareOp::eLessOrEqual, false, false, stencilOpState, stencilOpState);
vk::ColorComponentFlags colorComponentFlags(vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA);
vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState(false, vk::BlendFactor::eZero, vk::BlendFactor::eZero, vk::BlendOp::eAdd, vk::BlendFactor::eZero, vk::BlendFactor::eZero, vk::BlendOp::eAdd, colorComponentFlags);
vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo(vk::PipelineColorBlendStateCreateFlags(), false, vk::LogicOp::eNoOp, 1, &pipelineColorBlendAttachmentState, { { (1.0f, 1.0f, 1.0f, 1.0f) } });
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates);
vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(vk::PipelineCreateFlags(), 2, pipelineShaderStageCreateInfos, &pipelineVertexInputStateCreateInfo, &pipelineInputAssemblyStateCreateInfo, nullptr, &pipelineViewportStateCreateInfo, &pipelineRasterizationStateCreateInfo, &pipelineMultisampleStateCreateInfo, &pipelineDepthStencilStateCreateInfo, &pipelineColorBlendStateCreateInfo, &pipelineDynamicStateCreateInfo, pipelineLayout.get(), renderPass.get());
return device->createGraphicsPipelineUnique(pipelineCache.get(), graphicsPipelineCreateInfo);
}
vk::UniqueImage createImage(vk::UniqueDevice &device, vk::Format format, uint32_t width, uint32_t height, vk::ImageTiling tiling)
{
vk::Extent3D extend3D(width, height, 1);
vk::ImageCreateInfo imageCreateInfo({}, vk::ImageType::e2D, format, extend3D, 1, 1, vk::SampleCountFlagBits::e1, tiling, vk::ImageUsageFlagBits::eDepthStencilAttachment);
return device->createImageUnique(imageCreateInfo);
}
vk::UniqueImageView createImageView(vk::UniqueDevice &device, vk::UniqueImage &image, vk::Format format)
{
vk::ComponentMapping componentMapping(ComponentSwizzle::eR, ComponentSwizzle::eG, ComponentSwizzle::eB, ComponentSwizzle::eA);
vk::ImageSubresourceRange imageSubresourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1);
vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image.get(), vk::ImageViewType::e2D, format, componentMapping, imageSubresourceRange);
return device->createImageViewUnique(imageViewCreateInfo);
}
vk::UniqueInstance createInstance(std::string const& appName, std::string const& engineName, std::vector<std::string> const& extensions)
{
std::vector<char const*> enabledLayers;
@@ -122,6 +198,74 @@ namespace vk
return instance;
}
vk::UniqueRenderPass createRenderPass(vk::UniqueDevice &device, vk::Format colorFormat, vk::Format depthFormat)
{
vk::AttachmentDescription attachmentDescriptions[2] =
{
vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore, vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR),
vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), depthFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore, vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eStore, vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal)
};
vk::AttachmentReference colorAttachment(0, vk::ImageLayout::eColorAttachmentOptimal);
vk::AttachmentReference depthAttachment(1, vk::ImageLayout::eDepthStencilAttachmentOptimal);
vk::SubpassDescription subpassDescription(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 0, nullptr, 1, &colorAttachment, nullptr, &depthAttachment);
return device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachmentDescriptions, 1, &subpassDescription));
}
vk::UniqueSwapchainKHR createSwapChain(vk::PhysicalDevice physicalDevice, vk::UniqueSurfaceKHR &surface, vk::UniqueDevice &device, uint32_t width, uint32_t height, vk::Format format, uint32_t graphicsQueueFamilyIndex, uint32_t presentQueueFamilyIndex)
{
vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.get());
VkExtent2D swapchainExtent;
if (surfaceCapabilities.currentExtent.width == std::numeric_limits<uint32_t>::max())
{
// If the surface size is undefined, the size is set to the size of the images requested.
swapchainExtent.width = clamp(width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width);
swapchainExtent.height = clamp(height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height);
}
else
{
// If the surface size is defined, the swap chain size must match
swapchainExtent = surfaceCapabilities.currentExtent;
}
vk::SurfaceTransformFlagBitsKHR preTransform = (surfaceCapabilities.supportedTransforms & vk::SurfaceTransformFlagBitsKHR::eIdentity) ? vk::SurfaceTransformFlagBitsKHR::eIdentity : surfaceCapabilities.currentTransform;
vk::CompositeAlphaFlagBitsKHR compositeAlpha =
(surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePreMultiplied) ? vk::CompositeAlphaFlagBitsKHR::ePreMultiplied :
(surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePostMultiplied) ? vk::CompositeAlphaFlagBitsKHR::ePostMultiplied :
(surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::eInherit) ? vk::CompositeAlphaFlagBitsKHR::eInherit : vk::CompositeAlphaFlagBitsKHR::eOpaque;
vk::SwapchainCreateInfoKHR swapChainCreateInfo({}, surface.get(), surfaceCapabilities.minImageCount, format, vk::ColorSpaceKHR::eSrgbNonlinear, swapchainExtent, 1,
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::SharingMode::eExclusive, 0, nullptr, preTransform, compositeAlpha, vk::PresentModeKHR::eFifo, true,
nullptr);
uint32_t queueFamilyIndices[2] = { graphicsQueueFamilyIndex, presentQueueFamilyIndex };
if (graphicsQueueFamilyIndex != presentQueueFamilyIndex)
{
// If the graphics and present queues are from different queue families, we either have to explicitly transfer ownership of images between
// the queues, or we have to create the swapchain with imageSharingMode as vk::SharingMode::eConcurrent
swapChainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent;
swapChainCreateInfo.queueFamilyIndexCount = 2;
swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
}
return device->createSwapchainKHRUnique(swapChainCreateInfo);
}
std::vector<vk::UniqueImageView> createSwapChainImageViews(vk::UniqueDevice &device, vk::UniqueSwapchainKHR &swapChain, vk::Format format)
{
std::vector<vk::Image> images = device->getSwapchainImagesKHR(swapChain.get());
std::vector<vk::UniqueImageView> imageViews;
imageViews.reserve(images.size());
vk::ComponentMapping componentMapping(ComponentSwizzle::eR, ComponentSwizzle::eG, ComponentSwizzle::eB, ComponentSwizzle::eA);
vk::ImageSubresourceRange imageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1);
for (auto const& image : images)
{
imageViews.push_back(device->createImageViewUnique(vk::ImageViewCreateInfo(vk::ImageViewCreateFlags(), image, vk::ImageViewType::e2D, format, componentMapping, imageSubresourceRange)));
}
return imageViews;
}
VkBool32 debugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT /*objectType*/, uint64_t /*object*/, size_t /*location*/, int32_t /*messageCode*/, const char* /*pLayerPrefix*/, const char* pMessage, void* /*pUserData*/)
{
switch (flags)
@@ -191,11 +335,43 @@ namespace vk
throw std::runtime_error("Could not find queues for both graphics or present -> terminating");
}
uint32_t findMemoryType(vk::PhysicalDeviceMemoryProperties const& memoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirementsMask)
{
uint32_t typeIndex = uint32_t(~0);
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++)
{
if ((typeBits & 1) && ((memoryProperties.memoryTypes[i].propertyFlags & requirementsMask) == requirementsMask))
{
typeIndex = i;
break;
}
typeBits >>= 1;
}
assert(typeIndex != ~0);
return typeIndex;
}
std::vector<std::string> getDeviceExtensions()
{
return{ VK_KHR_SWAPCHAIN_EXTENSION_NAME };
}
vk::ImageTiling getImageTiling(vk::FormatProperties const& formatProperties)
{
if (formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment)
{
return vk::ImageTiling::eLinear;
}
else if (formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment)
{
return vk::ImageTiling::eOptimal;
}
else
{
throw std::runtime_error("DepthStencilAttachment is not supported for D16Unorm depth format.");
}
}
std::vector<std::string> getInstanceExtensions()
{
std::vector<std::string> extensions;
@@ -230,6 +406,15 @@ namespace vk
return (formats[0].format == vk::Format::eUndefined) ? vk::Format::eB8G8R8A8Unorm : formats[0].format;
}
void submitAndWait(vk::UniqueDevice &device, vk::Queue queue, vk::UniqueCommandBuffer &commandBuffer)
{
vk::UniqueFence fence = device->createFenceUnique(vk::FenceCreateInfo());
vk::PipelineStageFlags pipelineStageFlags = vk::PipelineStageFlagBits::eColorAttachmentOutput;
queue.submit(vk::SubmitInfo(0, nullptr, &pipelineStageFlags, 1, &commandBuffer.get()), fence.get());
while (vk::Result::eTimeout == device->waitForFences(fence.get(), VK_TRUE, vk::su::FenceTimeout))
;
}
#if defined(VK_USE_PLATFORM_WIN32_KHR)
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

View File

@@ -32,6 +32,20 @@ namespace vk
return static_cast<TargetType>(value);
}
template <class T>
void copyToDevice(vk::UniqueDevice &device, vk::UniqueDeviceMemory &memory, T const* pData, size_t count)
{
uint8_t* deviceData = static_cast<uint8_t*>(device->mapMemory(memory.get(), 0, count * sizeof(T)));
memcpy(deviceData, pData, count * sizeof(T));
device->unmapMemory(memory.get());
}
template <class T>
void copyToDevice(vk::UniqueDevice &device, vk::UniqueDeviceMemory &memory, T const& data)
{
copyToDevice<T>(device, memory, &data, 1);
}
template<class T>
VULKAN_HPP_INLINE constexpr const T& clamp(const T& v, const T& lo, const T& hi)
{
@@ -39,16 +53,27 @@ namespace vk
}
vk::UniqueDeviceMemory allocateMemory(vk::UniqueDevice &device, vk::PhysicalDeviceMemoryProperties const& memoryProperties, vk::MemoryRequirements const& memoryRequirements, vk::MemoryPropertyFlags memoryPropertyFlags);
vk::UniqueCommandPool createCommandPool(vk::UniqueDevice &device, uint32_t queueFamilyIndex);
vk::UniqueDebugReportCallbackEXT createDebugReportCallback(vk::UniqueInstance &instance);
vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device);
vk::UniqueDevice createDevice(vk::PhysicalDevice physicalDevice, uint32_t queueFamilyIndex, std::vector<std::string> const& extensions = {});
std::vector<vk::UniqueFramebuffer> createFramebuffers(vk::UniqueDevice &device, vk::UniqueRenderPass &renderPass, std::vector<vk::UniqueImageView> const& imageViews, vk::UniqueImageView &depthImageView, int width, int height);
vk::UniquePipeline createGraphicsPipeline(vk::UniqueDevice &device, vk::UniquePipelineCache &pipelineCache, vk::UniqueShaderModule &vertexShaderModule, vk::UniqueShaderModule &fragmentShaderModule, uint32_t vertexStride, vk::UniquePipelineLayout &pipelineLayout, vk::UniqueRenderPass &renderPass);
vk::UniqueInstance createInstance(std::string const& appName, std::string const& engineName, std::vector<std::string> const& extensions = {});
vk::UniqueImage createImage(vk::UniqueDevice &device, vk::Format format, uint32_t width, uint32_t height, vk::ImageTiling tiling = vk::ImageTiling::eOptimal);
vk::UniqueImageView createImageView(vk::UniqueDevice &device, vk::UniqueImage &image, vk::Format format);
vk::UniqueRenderPass createRenderPass(vk::UniqueDevice &device, vk::Format colorFormat, vk::Format depthFormat);
vk::UniqueSwapchainKHR createSwapChain(vk::PhysicalDevice physicalDevice, vk::UniqueSurfaceKHR &surface, vk::UniqueDevice &device, uint32_t width, uint32_t height, vk::Format format, uint32_t graphicsQueueFamilyIndex, uint32_t presentQueueFamilyIndex);
std::vector<vk::UniqueImageView> createSwapChainImageViews(vk::UniqueDevice &device, vk::UniqueSwapchainKHR &swapChain, vk::Format format);
VkBool32 debugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData);
uint32_t findGraphicsQueueFamilyIndex(std::vector<vk::QueueFamilyProperties> const& queueFamilyProperties);
std::pair<uint32_t, uint32_t> findGraphicsAndPresentQueueFamilyIndex(vk::PhysicalDevice physicalDevice, vk::UniqueSurfaceKHR & surface);
uint32_t findMemoryType(vk::PhysicalDeviceMemoryProperties const& memoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirementsMask);
std::vector<std::string> getDeviceExtensions();
vk::ImageTiling getImageTiling(vk::FormatProperties const& formatProperties);
std::vector<std::string> getInstanceExtensions();
vk::Format pickColorFormat(std::vector<vk::SurfaceFormatKHR> const& formats);
void submitAndWait(vk::UniqueDevice &device, vk::Queue queue, vk::UniqueCommandBuffer &commandBuffer);
#if defined(VK_USE_PLATFORM_WIN32_KHR)
HWND initializeWindow(std::string const& className, std::string const& windowName, LONG width, LONG height);