diff --git a/samples/07_InitUniformBuffer/07_InitUniformBuffer.cpp b/samples/07_InitUniformBuffer/07_InitUniformBuffer.cpp index 70ef593..aa9e011 100644 --- a/samples/07_InitUniformBuffer/07_InitUniformBuffer.cpp +++ b/samples/07_InitUniformBuffer/07_InitUniformBuffer.cpp @@ -42,30 +42,16 @@ int main(int /*argc*/, char * /*argv[]*/) /* VULKAN_HPP_KEY_START */ - glm::mat4x4 projection = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.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 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 ! glm::mat4x4 mvpc = clip * projection * view * model; vk::UniqueBuffer uniformDataBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(mvpc), vk::BufferUsageFlagBits::eUniformBuffer)); vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements(uniformDataBuffer.get()); - uint32_t typeBits = memoryRequirements.memoryTypeBits; - - vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); - vk::MemoryPropertyFlags requirementsMask = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent; - 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); + uint32_t typeIndex = vk::su::findMemoryType(physicalDevices[0].getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); vk::UniqueDeviceMemory uniformDataMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, typeIndex)); uint8_t* pData = static_cast(device->mapMemory(uniformDataMemory.get(), 0, memoryRequirements.size)); diff --git a/samples/09_InitDescriptorSet/09_InitDescriptorSet.cpp b/samples/09_InitDescriptorSet/09_InitDescriptorSet.cpp index d8337d7..8100b46 100644 --- a/samples/09_InitDescriptorSet/09_InitDescriptorSet.cpp +++ b/samples/09_InitDescriptorSet/09_InitDescriptorSet.cpp @@ -43,6 +43,8 @@ int main(int /*argc*/, char * /*argv[]*/) vk::UniqueBuffer buffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer)); vk::UniqueDeviceMemory deviceMemory = vk::su::allocateMemory(device, physicalDevices[0].getMemoryProperties(), device->getBufferMemoryRequirements(buffer.get()), vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); + device->bindBufferMemory(buffer.get(), deviceMemory.get(), 0); + vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device); /* VULKAN_HPP_KEY_START */ @@ -54,7 +56,6 @@ int main(int /*argc*/, char * /*argv[]*/) // allocate a descriptor set std::vector descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get())); - device->bindBufferMemory(buffer.get(), deviceMemory.get(), 0); vk::DescriptorBufferInfo descriptorBufferInfo(buffer.get(), 0, sizeof(glm::mat4x4)); device->updateDescriptorSets(vk::WriteDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &descriptorBufferInfo), {}); diff --git a/samples/10_InitRenderPass/10_InitRenderPass.cpp b/samples/10_InitRenderPass/10_InitRenderPass.cpp index 0b1fa59..8536320 100644 --- a/samples/10_InitRenderPass/10_InitRenderPass.cpp +++ b/samples/10_InitRenderPass/10_InitRenderPass.cpp @@ -51,7 +51,7 @@ int main(int /*argc*/, char * /*argv[]*/) vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())); - const vk::Format depthFormat = vk::Format::eD16Unorm; + vk::Format depthFormat = vk::Format::eD16Unorm; /* VULKAN_HPP_KEY_START */ @@ -71,6 +71,12 @@ int main(int /*argc*/, char * /*argv[]*/) // functions are called by the destructor of the UniqueRenderPass and the UniqueSemaphore on leaving this scope. /* VULKAN_HPP_KEY_END */ + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(window); +#else +#pragma error "unhandled platform" +#endif } catch (vk::SystemError err) { diff --git a/samples/11_InitShaders/11_InitShaders.cpp b/samples/11_InitShaders/11_InitShaders.cpp index 9feea7f..49c6242 100644 --- a/samples/11_InitShaders/11_InitShaders.cpp +++ b/samples/11_InitShaders/11_InitShaders.cpp @@ -15,6 +15,7 @@ // VulkanHpp Samples : 11_InitShaders // Initialize vertex and fragment shaders +#include "..\utils\shaders.hpp" #include "..\utils\utils.hpp" #include "vulkan/vulkan.hpp" #include "SPIRV/GlslangToSpv.h" @@ -23,160 +24,6 @@ static char const* AppName = "11_InitShaders"; static char const* EngineName = "Vulkan.hpp"; -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 &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; -} - int main(int /*argc*/, char * /*argv[]*/) { try @@ -189,56 +36,21 @@ int main(int /*argc*/, char * /*argv[]*/) std::vector physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); - vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], vk::su::findGraphicsQueueFamilyIndex(physicalDevices[0].getQueueFamilyProperties()), vk::su::getDeviceExtensions()); + vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], vk::su::findGraphicsQueueFamilyIndex(physicalDevices[0].getQueueFamilyProperties())); /* VULKAN_HPP_KEY_START */ - static 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; -} -)"; - - static 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; -} -)"; - glslang::InitializeProcess(); std::vector vertexShaderSPV; - bool ok = GLSLtoSPV(vk::ShaderStageFlagBits::eVertex, vertexShaderText, vertexShaderSPV); + bool ok = vk::su::GLSLtoSPV(vk::ShaderStageFlagBits::eVertex, vertexShaderText, vertexShaderSPV); assert(ok); vk::ShaderModuleCreateInfo vertexShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), vertexShaderSPV.size() * sizeof(unsigned int), vertexShaderSPV.data()); vk::UniqueShaderModule vertexShaderModule = device->createShaderModuleUnique(vertexShaderModuleCreateInfo); std::vector fragmentShaderSPV; - ok = GLSLtoSPV(vk::ShaderStageFlagBits::eFragment, fragmentShaderText, fragmentShaderSPV); + ok = vk::su::GLSLtoSPV(vk::ShaderStageFlagBits::eFragment, fragmentShaderText, fragmentShaderSPV); assert(ok); vk::ShaderModuleCreateInfo fragmentShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), fragmentShaderSPV.size() * sizeof(unsigned int), fragmentShaderSPV.data()); diff --git a/samples/11_InitShaders/CMakeLists.txt b/samples/11_InitShaders/CMakeLists.txt index 9d94308..95db820 100644 --- a/samples/11_InitShaders/CMakeLists.txt +++ b/samples/11_InitShaders/CMakeLists.txt @@ -17,11 +17,13 @@ cmake_minimum_required(VERSION 3.2) project(11_InitShaders) set(HEADERS + ../utils/shaders.hpp ../utils/utils.hpp ) set(SOURCES 11_InitShaders.cpp + ../utils/shaders.cpp ../utils/utils.cpp ) diff --git a/samples/12_InitFrameBuffers/12_InitFrameBuffers.cpp b/samples/12_InitFrameBuffers/12_InitFrameBuffers.cpp new file mode 100644 index 0000000..865d160 --- /dev/null +++ b/samples/12_InitFrameBuffers/12_InitFrameBuffers.cpp @@ -0,0 +1,100 @@ +// 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. +// +// VulkanHpp Samples : 12_InitFrameBuffers +// Initialize framebuffers + +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" +#include + +static char const* AppName = "12_InitFrameBuffers"; +static char const* EngineName = "Vulkan.hpp"; + +int main(int /*argc*/, char * /*argv[]*/) +{ + try + { + vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions()); +#if !defined(NDEBUG) + vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); +#endif + + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + assert(!physicalDevices.empty()); + + uint32_t width = 64; + uint32_t height = 64; +#if defined(VK_USE_PLATFORM_WIN32_KHR) + HWND window = vk::su::initializeWindow(AppName, AppName, width, height); + vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); +#else +#pragma error "unhandled platform" +#endif + + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); + + vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())); + vk::UniqueSwapchainKHR swapChain = vk::su::createSwapChain(physicalDevices[0], surface, device, width, height, colorFormat, graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); + std::vector swapChainImageViews = vk::su::createSwapChainImageViews(device, swapChain, colorFormat); + + vk::Format depthFormat = vk::Format::eD16Unorm; + vk::UniqueImage depthImage = vk::su::createImage(device, depthFormat, width, height); + vk::UniqueDeviceMemory depthMemory = vk::su::allocateMemory(device, physicalDevices[0].getMemoryProperties(), device->getImageMemoryRequirements(depthImage.get()), vk::MemoryPropertyFlagBits::eDeviceLocal); + device->bindImageMemory(depthImage.get(), depthMemory.get(), 0); + vk::UniqueImageView depthViewImage = vk::su::createImageView(device, depthImage, depthFormat); + + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, colorFormat, depthFormat); + + /* VULKAN_KEY_START */ + + vk::ImageView attachments[2]; + attachments[1] = depthViewImage.get(); + + std::vector framebuffers; + framebuffers.reserve(swapChainImageViews.size()); + for (auto const& view : swapChainImageViews) + { + attachments[0] = view.get(); + framebuffers.push_back(device->createFramebufferUnique(vk::FramebufferCreateInfo(vk::FramebufferCreateFlags(), renderPass.get(), 2, attachments, width, height, 1))); + } + + // Note: No need to explicitly destroy the Framebuffers, as the destroy functions are called by the destructor of the UniqueFramebuffer on leaving this scope. + + /* VULKAN_KEY_END */ + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(window); +#else +#pragma error "unhandled platform" +#endif + } + catch (vk::SystemError err) + { + std::cout << "vk::SystemError: " << err.what() << std::endl; + exit(-1); + } + catch (std::runtime_error err) + { + std::cout << "std::runtime_error: " << err.what() << std::endl; + exit(-1); + } + catch (...) + { + std::cout << "unknown error\n"; + exit(-1); + } + return 0; +} diff --git a/samples/12_InitFrameBuffers/CMakeLists.txt b/samples/12_InitFrameBuffers/CMakeLists.txt new file mode 100644 index 0000000..5982526 --- /dev/null +++ b/samples/12_InitFrameBuffers/CMakeLists.txt @@ -0,0 +1,39 @@ +# 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. + +cmake_minimum_required(VERSION 3.2) + +project(12_InitFrameBuffers) + +set(HEADERS + ../utils/utils.hpp +) + +set(SOURCES + 12_InitFrameBuffers.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(12_InitFrameBuffers + ${HEADERS} + ${SOURCES} +) + +set_target_properties(12_InitFrameBuffers PROPERTIES FOLDER "Samples") +target_include_directories(12_InitFrameBuffers PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(12_InitFrameBuffers PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp b/samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp new file mode 100644 index 0000000..aef36f4 --- /dev/null +++ b/samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp @@ -0,0 +1,135 @@ +// 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. +// +// VulkanHpp Samples : 13_InitVertexBuffer +// Initialize vertex buffer + +#include "../utils/geometries.hpp" +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" +#include + +static char const* AppName = "13_InitVertexBuffer"; +static char const* EngineName = "Vulkan.hpp"; + +int main(int /*argc*/, char * /*argv[]*/) +{ + try + { + vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions()); +#if !defined(NDEBUG) + vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); +#endif + + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + assert(!physicalDevices.empty()); + + uint32_t width = 64; + uint32_t height = 64; +#if defined(VK_USE_PLATFORM_WIN32_KHR) + HWND window = vk::su::initializeWindow(AppName, AppName, width, height); + vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); +#else +#pragma error "unhandled platform" +#endif + + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); + + vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); + std::vector commandBuffers = device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)); + + vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); + + vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())); + vk::UniqueSwapchainKHR swapChain = vk::su::createSwapChain(physicalDevices[0], surface, device, width, height, colorFormat, graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); + std::vector swapChainImageViews = vk::su::createSwapChainImageViews(device, swapChain, colorFormat); + + vk::Format depthFormat = vk::Format::eD16Unorm; + vk::UniqueImage depthImage = vk::su::createImage(device, depthFormat, width, height); + vk::UniqueDeviceMemory depthMemory = vk::su::allocateMemory(device, physicalDevices[0].getMemoryProperties(), device->getImageMemoryRequirements(depthImage.get()), vk::MemoryPropertyFlagBits::eDeviceLocal); + device->bindImageMemory(depthImage.get(), depthMemory.get(), 0); + vk::UniqueImageView depthViewImage = vk::su::createImageView(device, depthImage, depthFormat); + + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, colorFormat, depthFormat); + + std::vector framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainImageViews, depthViewImage, width, height); + + /* VULKAN_KEY_START */ + + // create a vertex buffer for some vertex and color data + vk::UniqueBuffer vertexBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer)); + + // allocate device memory for that buffer + vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements(vertexBuffer.get()); + uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevices[0].getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); + vk::UniqueDeviceMemory deviceMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); + + // copy the vertex and color data into that device memory + uint8_t *pData = static_cast(device->mapMemory(deviceMemory.get(), 0, memoryRequirements.size)); + memcpy(pData, coloredCubeData, sizeof(coloredCubeData)); + device->unmapMemory(deviceMemory.get()); + + // and bind the device memory to the vertex buffer + device->bindBufferMemory(vertexBuffer.get(), deviceMemory.get(), 0); + + vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo(vk::SemaphoreCreateFlags())); + vk::ResultValue currentBuffer = device->acquireNextImageKHR(swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); + assert(currentBuffer.result == vk::Result::eSuccess); + assert(currentBuffer.value < framebuffers.size()); + + vk::ClearValue clearValues[2]; + clearValues[0].color = vk::ClearColorValue(std::array({ 0.2f, 0.2f, 0.2f, 0.2f })); + clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); + + commandBuffers[0]->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); + + vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), vk::Extent2D(width, height)), 2, clearValues); + commandBuffers[0]->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); + + VkDeviceSize offset = 0; + commandBuffers[0]->bindVertexBuffers(0, vertexBuffer.get(), offset); + + commandBuffers[0]->endRenderPass(); + commandBuffers[0]->end(); + vk::su::submitAndWait(device, graphicsQueue, commandBuffers[0]); + + // Note: No need to explicitly destroy the vertexBuffer, deviceMemory, or semaphore, as the destroy functions are called + // by the destructor of the UniqueBuffer, UniqueDeviceMemory, and UniqueSemaphore, respectively, on leaving this scope. + + /* VULKAN_KEY_END */ + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(window); +#else +#pragma error "unhandled platform" +#endif + } + catch (vk::SystemError err) + { + std::cout << "vk::SystemError: " << err.what() << std::endl; + exit(-1); + } + catch (std::runtime_error err) + { + std::cout << "std::runtime_error: " << err.what() << std::endl; + exit(-1); + } + catch (...) + { + std::cout << "unknown error\n"; + exit(-1); + } + return 0; +} diff --git a/samples/13_InitVertexBuffer/CMakeLists.txt b/samples/13_InitVertexBuffer/CMakeLists.txt new file mode 100644 index 0000000..0a3e955 --- /dev/null +++ b/samples/13_InitVertexBuffer/CMakeLists.txt @@ -0,0 +1,40 @@ +# 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. + +cmake_minimum_required(VERSION 3.2) + +project(13_InitVertexBuffer) + +set(HEADERS + ../utils/geometries.hpp + ../utils/utils.hpp +) + +set(SOURCES + 13_InitVertexBuffer.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(13_InitVertexBuffer + ${HEADERS} + ${SOURCES} +) + +set_target_properties(13_InitVertexBuffer PROPERTIES FOLDER "Samples") +target_include_directories(13_InitVertexBuffer PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(13_InitVertexBuffer PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/14_InitPipeline/14_InitPipeline.cpp b/samples/14_InitPipeline/14_InitPipeline.cpp new file mode 100644 index 0000000..3f633df --- /dev/null +++ b/samples/14_InitPipeline/14_InitPipeline.cpp @@ -0,0 +1,190 @@ +// 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. +// +// VulkanHpp Samples : 14_InitPipeline +// Initialize graphics pipeline + +#include "../utils/geometries.hpp" +#include "../utils/math.hpp" +#include "../utils/shaders.hpp" +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" +#include "SPIRV/GlslangToSpv.h" +#include + +static char const* AppName = "14_InitPipeline"; +static char const* EngineName = "Vulkan.hpp"; + +int main(int /*argc*/, char * /*argv[]*/) +{ + try + { + vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions()); +#if !defined(NDEBUG) + vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); +#endif + + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + assert(!physicalDevices.empty()); + vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); + + uint32_t width = 500; + uint32_t height = 500; +#if defined(VK_USE_PLATFORM_WIN32_KHR) + HWND window = vk::su::initializeWindow(AppName, AppName, width, height); + vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); +#else +#pragma error "unhandled platform" +#endif + + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); + + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())), vk::Format::eD16Unorm); + + vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device); + vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); + + glslang::InitializeProcess(); + vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText); + vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText); + glslang::FinalizeProcess(); + + /* VULKAN_KEY_START */ + + 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, sizeof(coloredCubeData[0])); + 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(), // flags + 1, // vertexBindingDescriptionCount + &vertexInputBindingDescription, // pVertexBindingDescription + 2, // vertexAttributeDescriptionCount + vertexInputAttributeDescriptions // pVertexAttributeDescriptions + ); + + vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList); + + vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(vk::PipelineViewportStateCreateFlags(), 1, nullptr, 1, nullptr); + + vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo + ( + vk::PipelineRasterizationStateCreateFlags(), // flags + false, // depthClampEnable + false, // rasterizerDiscardEnable + vk::PolygonMode::eFill, // polygonMode + vk::CullModeFlagBits::eBack, // cullMode + vk::FrontFace::eClockwise, // frontFace + false, // depthBiasEnable + 0.0f, // depthBiasConstantFactor + 0.0f, // depthBiasClamp + 0.0f, // depthBiasSlopeFactor + 1.0f // lineWidth + ); + + vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo; + + vk::StencilOpState stencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways); + vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo + ( + vk::PipelineDepthStencilStateCreateFlags(), // flags + true, // depthTestEnable + true, // depthWriteEnable + vk::CompareOp::eLessOrEqual, // depthCompareOp + false, // depthBoundTestEnable + false, // stencilTestEnable + stencilOpState, // front + stencilOpState // back + ); + + vk::ColorComponentFlags colorComponentFlags(vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA); + vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState + ( + false, // blendEnable + vk::BlendFactor::eZero, // srcColorBlendFactor + vk::BlendFactor::eZero, // dstColorBlendFactor + vk::BlendOp::eAdd, // colorBlendOp + vk::BlendFactor::eZero, // srcAlphaBlendFactor + vk::BlendFactor::eZero, // dstAlphaBlendFactor + vk::BlendOp::eAdd, // alphaBlendOp + colorComponentFlags // colorWriteMask + ); + vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo + ( + vk::PipelineColorBlendStateCreateFlags(), // flags + false, // logicOpEnable + vk::LogicOp::eNoOp, // logicOp + 1, // attachmentCount + &pipelineColorBlendAttachmentState, // pAttachments + { { (1.0f, 1.0f, 1.0f, 1.0f) } } // blendConstants + ); + + vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; + vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates); + + vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo + ( + vk::PipelineCreateFlags(), // flags + 2, // stageCount + pipelineShaderStageCreateInfos, // pStages + &pipelineVertexInputStateCreateInfo, // pVertexInputState + &pipelineInputAssemblyStateCreateInfo, // pInputAssemblyState + nullptr, // pTessellationState + &pipelineViewportStateCreateInfo, // pViewportState + &pipelineRasterizationStateCreateInfo, // pRasterizationState + &pipelineMultisampleStateCreateInfo, // pMultisampleState + &pipelineDepthStencilStateCreateInfo, // pDepthStencilState + &pipelineColorBlendStateCreateInfo, // pColorBlendState + &pipelineDynamicStateCreateInfo, // pDynamicState + pipelineLayout.get(), // layout + renderPass.get() // renderPass + ); + + vk::UniquePipeline pipeline = device->createGraphicsPipelineUnique(nullptr, graphicsPipelineCreateInfo); + + /* VULKAN_KEY_END */ + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(window); +#else +#pragma error "unhandled platform" +#endif + } + catch (vk::SystemError err) + { + std::cout << "vk::SystemError: " << err.what() << std::endl; + exit(-1); + } + catch (std::runtime_error err) + { + std::cout << "std::runtime_error: " << err.what() << std::endl; + exit(-1); + } + catch (...) + { + std::cout << "unknown error\n"; + exit(-1); + } + return 0; +} diff --git a/samples/14_InitPipeline/CMakeLists.txt b/samples/14_InitPipeline/CMakeLists.txt new file mode 100644 index 0000000..cc416b4 --- /dev/null +++ b/samples/14_InitPipeline/CMakeLists.txt @@ -0,0 +1,44 @@ +# 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. + +cmake_minimum_required(VERSION 3.2) + +project(14_InitPipeline) + +set(HEADERS + ../utils/geometries.hpp + ../utils/math.hpp + ../utils/shaders.hpp + ../utils/utils.hpp +) + +set(SOURCES + 14_InitPipeline.cpp + ../utils/math.cpp + ../utils/shaders.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(14_InitPipeline + ${HEADERS} + ${SOURCES} +) + +set_target_properties(14_InitPipeline PROPERTIES FOLDER "Samples") +target_include_directories(14_InitPipeline PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(14_InitPipeline PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/15_DrawCube/15_DrawCube.cpp b/samples/15_DrawCube/15_DrawCube.cpp new file mode 100644 index 0000000..ea13065 --- /dev/null +++ b/samples/15_DrawCube/15_DrawCube.cpp @@ -0,0 +1,171 @@ +// 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. +// +// VulkanHpp Samples : 15_DrawCube +// Draw a cube + +#include "../utils/geometries.hpp" +#include "../utils/math.hpp" +#include "../utils/shaders.hpp" +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" +#include "SPIRV/GlslangToSpv.h" +#include + +static char const* AppName = "15_DrawCube"; +static char const* EngineName = "Vulkan.hpp"; + +int main(int /*argc*/, char * /*argv[]*/) +{ + try + { + vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions()); +#if !defined(NDEBUG) + vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); +#endif + + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + assert(!physicalDevices.empty()); + vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); + + uint32_t width = 500; + uint32_t height = 500; +#if defined(VK_USE_PLATFORM_WIN32_KHR) + HWND window = vk::su::initializeWindow(AppName, AppName, width, height); + vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); +#else +#pragma error "unhandled platform" +#endif + + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); + + vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); + std::vector commandBuffers = device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)); + + vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); + vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); + + vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())); + vk::UniqueSwapchainKHR swapChain = vk::su::createSwapChain(physicalDevices[0], surface, device, width, height, colorFormat, graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); + std::vector swapChainImageViews = vk::su::createSwapChainImageViews(device, swapChain, colorFormat); + + vk::Format depthFormat = vk::Format::eD16Unorm; + vk::UniqueImage depthImage = vk::su::createImage(device, depthFormat, width, height); + vk::UniqueDeviceMemory depthMemory = vk::su::allocateMemory(device, memoryProperties, device->getImageMemoryRequirements(depthImage.get()), vk::MemoryPropertyFlagBits::eDeviceLocal); + device->bindImageMemory(depthImage.get(), depthMemory.get(), 0); + vk::UniqueImageView depthViewImage = vk::su::createImageView(device, depthImage, depthFormat); + + glm::mat4x4 mvpc = vk::su::createModelViewProjectionClipMatrix(); + vk::UniqueBuffer uniformBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(mvpc), vk::BufferUsageFlagBits::eUniformBuffer)); + vk::UniqueDeviceMemory uniformMemory = vk::su::allocateMemory(device, physicalDevices[0].getMemoryProperties(), device->getBufferMemoryRequirements(uniformBuffer.get()), vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); + vk::su::copyToDevice(device, uniformMemory, mvpc); + device->bindBufferMemory(uniformBuffer.get(), uniformMemory.get(), 0); + + vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device); + vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); + + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())), vk::Format::eD16Unorm); + + glslang::InitializeProcess(); + vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText); + vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText); + glslang::FinalizeProcess(); + + std::vector framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainImageViews, depthViewImage, width, height); + + vk::UniqueBuffer vertexBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer)); + vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements(vertexBuffer.get()); + vk::UniqueDeviceMemory vertexDeviceMemory = vk::su::allocateMemory(device, memoryProperties, memoryRequirements, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); + vk::su::copyToDevice(device, vertexDeviceMemory, coloredCubeData, sizeof(coloredCubeData) / sizeof(coloredCubeData[0])); + device->bindBufferMemory(vertexBuffer.get(), vertexDeviceMemory.get(), 0); + + vk::DescriptorPoolSize poolSize(vk::DescriptorType::eUniformBuffer, 1); + vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 1, &poolSize)); + std::vector descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get())); + vk::DescriptorBufferInfo descriptorBufferInfo(uniformBuffer.get(), 0, sizeof(mvpc)); + device->updateDescriptorSets(vk::WriteDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &descriptorBufferInfo), nullptr); + + vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); + vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, sizeof(coloredCubeData[0]), pipelineLayout, renderPass); + + /* VULKAN_KEY_START */ + + // Get the index of the next available swapchain image: + vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); + vk::ResultValue currentBuffer = device->acquireNextImageKHR(swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); + assert(currentBuffer.result == vk::Result::eSuccess); + assert(currentBuffer.value < framebuffers.size()); + + commandBuffers[0]->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); + + vk::ClearValue clearValues[2]; + clearValues[0].color = vk::ClearColorValue(std::array({ 0.2f, 0.2f, 0.2f, 0.2f })); + clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); + vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), vk::Extent2D(width, height)), 2, clearValues); + commandBuffers[0]->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); + commandBuffers[0]->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); + commandBuffers[0]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[0].get(), nullptr); + + vk::Viewport viewport(0.0f, 0.0f, static_cast(width), static_cast(height), 0.0f, 1.0f); + commandBuffers[0]->setViewport(0, viewport); + + vk::Rect2D scissor(vk::Offset2D(0, 0), vk::Extent2D(width, height)); + commandBuffers[0]->setScissor(0, scissor); + + vk::DeviceSize offset = 0; + commandBuffers[0]->bindVertexBuffers(0, vertexBuffer.get(), offset); + + commandBuffers[0]->draw(12 * 3, 1, 0, 0); + commandBuffers[0]->endRenderPass(); + commandBuffers[0]->end(); + + vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); + + vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); + vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffers[0].get()); + graphicsQueue.submit(submitInfo, drawFence.get()); + + while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) + ; + + presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChain.get(), ¤tBuffer.value)); + Sleep(1000); + + /* VULKAN_KEY_END */ + + device->waitIdle(); +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(window); +#else +#pragma error "unhandled platform" +#endif + } + catch (vk::SystemError err) + { + std::cout << "vk::SystemError: " << err.what() << std::endl; + exit(-1); + } + catch (std::runtime_error err) + { + std::cout << "std::runtime_error: " << err.what() << std::endl; + exit(-1); + } + catch (...) + { + std::cout << "unknown error\n"; + exit(-1); + } + return 0; +} diff --git a/samples/15_DrawCube/CMakeLists.txt b/samples/15_DrawCube/CMakeLists.txt new file mode 100644 index 0000000..340c547 --- /dev/null +++ b/samples/15_DrawCube/CMakeLists.txt @@ -0,0 +1,44 @@ +# 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. + +cmake_minimum_required(VERSION 3.2) + +project(15_DrawCube) + +set(HEADERS + ../utils/geometries.hpp + ../utils/math.hpp + ../utils/shaders.hpp + ../utils/utils.hpp +) + +set(SOURCES + 15_DrawCube.cpp + ../utils/math.cpp + ../utils/shaders.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(15_DrawCube + ${HEADERS} + ${SOURCES} +) + +set_target_properties(15_DrawCube PROPERTIES FOLDER "Samples") +target_include_directories(15_DrawCube PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(15_DrawCube PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/utils/geometries.hpp b/samples/utils/geometries.hpp new file mode 100644 index 0000000..bfa9d93 --- /dev/null +++ b/samples/utils/geometries.hpp @@ -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 }, +}; + diff --git a/samples/utils/math.cpp b/samples/utils/math.cpp new file mode 100644 index 0000000..1b9daaf --- /dev/null +++ b/samples/utils/math.cpp @@ -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; + } + } +} diff --git a/samples/utils/math.hpp b/samples/utils/math.hpp new file mode 100644 index 0000000..24f1207 --- /dev/null +++ b/samples/utils/math.hpp @@ -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 + +namespace vk +{ + namespace su + { + glm::mat4x4 createModelViewProjectionClipMatrix(); + } +} diff --git a/samples/utils/shaders.cpp b/samples/utils/shaders.cpp new file mode 100644 index 0000000..554ca12 --- /dev/null +++ b/samples/utils/shaders.cpp @@ -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 &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 shaderSPV; + bool ok = GLSLtoSPV(shaderStage, shaderText, shaderSPV); + assert(ok); + + return device->createShaderModuleUnique(vk::ShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), shaderSPV.size() * sizeof(unsigned int), shaderSPV.data())); + } + + } +} diff --git a/samples/utils/shaders.hpp b/samples/utils/shaders.hpp new file mode 100644 index 0000000..c6e1724 --- /dev/null +++ b/samples/utils/shaders.hpp @@ -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 +#include + +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 &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; +} +)"; + diff --git a/samples/utils/utils.cpp b/samples/utils/utils.cpp index b4a195f..14cfbf7 100644 --- a/samples/utils/utils.cpp +++ b/samples/utils/utils.cpp @@ -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 createFramebuffers(vk::UniqueDevice &device, vk::UniqueRenderPass &renderPass, std::vector const& imageViews, vk::UniqueImageView &depthImageView, int width, int height) + { + vk::ImageView attachments[2]; + attachments[1] = depthImageView.get(); + + std::vector 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 const& extensions) { std::vector 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::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 createSwapChainImageViews(vk::UniqueDevice &device, vk::UniqueSwapchainKHR &swapChain, vk::Format format) + { + std::vector images = device->getSwapchainImagesKHR(swapChain.get()); + std::vector 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 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 getInstanceExtensions() { std::vector 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) { diff --git a/samples/utils/utils.hpp b/samples/utils/utils.hpp index 6425975..423e833 100644 --- a/samples/utils/utils.hpp +++ b/samples/utils/utils.hpp @@ -32,6 +32,20 @@ namespace vk return static_cast(value); } + template + void copyToDevice(vk::UniqueDevice &device, vk::UniqueDeviceMemory &memory, T const* pData, size_t count) + { + uint8_t* deviceData = static_cast(device->mapMemory(memory.get(), 0, count * sizeof(T))); + memcpy(deviceData, pData, count * sizeof(T)); + device->unmapMemory(memory.get()); + } + + template + void copyToDevice(vk::UniqueDevice &device, vk::UniqueDeviceMemory &memory, T const& data) + { + copyToDevice(device, memory, &data, 1); + } + template 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 const& extensions = {}); + std::vector createFramebuffers(vk::UniqueDevice &device, vk::UniqueRenderPass &renderPass, std::vector 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 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 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 const& queueFamilyProperties); std::pair findGraphicsAndPresentQueueFamilyIndex(vk::PhysicalDevice physicalDevice, vk::UniqueSurfaceKHR & surface); + uint32_t findMemoryType(vk::PhysicalDeviceMemoryProperties const& memoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirementsMask); std::vector getDeviceExtensions(); + vk::ImageTiling getImageTiling(vk::FormatProperties const& formatProperties); std::vector getInstanceExtensions(); vk::Format pickColorFormat(std::vector 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);