From d965a74cc0c5cbe1427da54190467de9418b8307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20S=C3=BC=C3=9Fenbach?= Date: Tue, 9 Apr 2019 15:19:18 +0200 Subject: [PATCH] Add samples ImmutableSampler, InitTexture, InputAttachment (#315) + slightly adjust some other samples. --- samples/11_InitShaders/CMakeLists.txt | 1 + samples/14_InitPipeline/CMakeLists.txt | 1 + samples/15_DrawCube/CMakeLists.txt | 1 + samples/DrawTexturedCube/CMakeLists.txt | 1 + samples/DrawTexturedCube/DrawTexturedCube.cpp | 95 -------- samples/DynamicUniform/CMakeLists.txt | 1 + samples/Events/CMakeLists.txt | 5 - samples/Events/Events.cpp | 9 +- samples/ImmutableSampler/CMakeLists.txt | 45 ++++ samples/ImmutableSampler/ImmutableSampler.cpp | 168 ++++++++++++++ samples/InitTexture/CMakeLists.txt | 45 ++++ samples/InitTexture/InitTexture.cpp | 166 ++++++++++++++ samples/InputAttachment/CMakeLists.txt | 45 ++++ samples/InputAttachment/InputAttachment.cpp | 211 ++++++++++++++++++ samples/utils/geometries.hpp | 53 +++++ samples/utils/shaders.cpp | 102 +-------- samples/utils/shaders.hpp | 44 ++++ samples/utils/utils.cpp | 19 +- 18 files changed, 800 insertions(+), 212 deletions(-) create mode 100644 samples/ImmutableSampler/CMakeLists.txt create mode 100644 samples/ImmutableSampler/ImmutableSampler.cpp create mode 100644 samples/InitTexture/CMakeLists.txt create mode 100644 samples/InitTexture/InitTexture.cpp create mode 100644 samples/InputAttachment/CMakeLists.txt create mode 100644 samples/InputAttachment/InputAttachment.cpp diff --git a/samples/11_InitShaders/CMakeLists.txt b/samples/11_InitShaders/CMakeLists.txt index bf462db..f8b1440 100644 --- a/samples/11_InitShaders/CMakeLists.txt +++ b/samples/11_InitShaders/CMakeLists.txt @@ -25,6 +25,7 @@ set(SOURCES 11_InitShaders.cpp ../utils/shaders.cpp ../utils/utils.cpp + ../../glslang/StandAlone/ResourceLimits.cpp ) source_group(headers FILES ${HEADERS}) diff --git a/samples/14_InitPipeline/CMakeLists.txt b/samples/14_InitPipeline/CMakeLists.txt index bcf3d26..908ab42 100644 --- a/samples/14_InitPipeline/CMakeLists.txt +++ b/samples/14_InitPipeline/CMakeLists.txt @@ -28,6 +28,7 @@ set(SOURCES ../utils/math.cpp ../utils/shaders.cpp ../utils/utils.cpp + ../../glslang/StandAlone/ResourceLimits.cpp ) source_group(headers FILES ${HEADERS}) diff --git a/samples/15_DrawCube/CMakeLists.txt b/samples/15_DrawCube/CMakeLists.txt index 7189603..b7b7470 100644 --- a/samples/15_DrawCube/CMakeLists.txt +++ b/samples/15_DrawCube/CMakeLists.txt @@ -28,6 +28,7 @@ set(SOURCES ../utils/math.cpp ../utils/shaders.cpp ../utils/utils.cpp + ../../glslang/StandAlone/ResourceLimits.cpp ) source_group(headers FILES ${HEADERS}) diff --git a/samples/DrawTexturedCube/CMakeLists.txt b/samples/DrawTexturedCube/CMakeLists.txt index 5204116..a23009c 100644 --- a/samples/DrawTexturedCube/CMakeLists.txt +++ b/samples/DrawTexturedCube/CMakeLists.txt @@ -28,6 +28,7 @@ set(SOURCES ../utils/math.cpp ../utils/shaders.cpp ../utils/utils.cpp + ../../glslang/StandAlone/ResourceLimits.cpp ) source_group(headers FILES ${HEADERS}) diff --git a/samples/DrawTexturedCube/DrawTexturedCube.cpp b/samples/DrawTexturedCube/DrawTexturedCube.cpp index b2e000d..5d4025f 100644 --- a/samples/DrawTexturedCube/DrawTexturedCube.cpp +++ b/samples/DrawTexturedCube/DrawTexturedCube.cpp @@ -26,101 +26,6 @@ static char const* AppName = "DrawTexturedCube"; static char const* EngineName = "Vulkan.hpp"; -// vertex shader with (P)osition and (T)exCoord in and (T)exCoord out -const std::string vertexShaderText_PT_T = R"( -#version 400 - -#extension GL_ARB_separate_shader_objects : enable -#extension GL_ARB_shading_language_420pack : enable - -layout (std140, binding = 0) uniform buffer -{ - mat4 mvp; -} uniformBuffer; - -layout (location = 0) in vec4 pos; -layout (location = 1) in vec2 inTexCoord; - -layout (location = 0) out vec2 outTexCoord; - -void main() -{ - outTexCoord = inTexCoord; - gl_Position = uniformBuffer.mvp * pos; -} -)"; - -// fragment shader with (T)exCoord in and (C)olor out -const std::string fragmentShaderText_T_C = R"( -#version 400 - -#extension GL_ARB_separate_shader_objects : enable -#extension GL_ARB_shading_language_420pack : enable - -layout (binding = 1) uniform sampler2D tex; - -layout (location = 0) in vec2 inTexCoord; - -layout (location = 0) out vec4 outColor; - -void main() -{ - outColor = textureLod(tex, inTexCoord, 0.0f); -} -)"; - -struct VertexPT -{ - float x, y, z, w; // Position data - float u, v; // texture u,v -}; - -static const VertexPT texturedCubeData[] = -{ - // left face - { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, - { -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, - { -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, - { -1.0f, 1.0f, 1.0f, 1.0f, 0.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 }, - // front face - { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.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, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, - { -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, - // top face - { -1.0f, -1.0f, -1.0f, 1.0f, 0.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, -1.0f, -1.0f, 1.0f, 0.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, 0.0f }, - // bottom 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 }, - { -1.0f, 1.0f, 1.0f, 1.0f, 0.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, 0.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, - // right face - { 1.0f, 1.0f, -1.0f, 1.0f, 0.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, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, - { 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, - // back face - { -1.0f, 1.0f, 1.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, 0.0f }, - { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, - { 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, -}; - int main(int /*argc*/, char ** /*argv*/) { try diff --git a/samples/DynamicUniform/CMakeLists.txt b/samples/DynamicUniform/CMakeLists.txt index 204a734..cec6b22 100644 --- a/samples/DynamicUniform/CMakeLists.txt +++ b/samples/DynamicUniform/CMakeLists.txt @@ -28,6 +28,7 @@ set(SOURCES ../utils/math.cpp ../utils/shaders.cpp ../utils/utils.cpp + ../../glslang/StandAlone/ResourceLimits.cpp ) source_group(headers FILES ${HEADERS}) diff --git a/samples/Events/CMakeLists.txt b/samples/Events/CMakeLists.txt index 3a184ea..baed87d 100644 --- a/samples/Events/CMakeLists.txt +++ b/samples/Events/CMakeLists.txt @@ -17,16 +17,11 @@ cmake_minimum_required(VERSION 3.2) project(Events) set(HEADERS - ../utils/geometries.hpp - ../utils/math.hpp - ../utils/shaders.hpp ../utils/utils.hpp ) set(SOURCES Events.cpp - ../utils/math.cpp - ../utils/shaders.cpp ../utils/utils.cpp ) diff --git a/samples/Events/Events.cpp b/samples/Events/Events.cpp index 074c19c..ad29720 100644 --- a/samples/Events/Events.cpp +++ b/samples/Events/Events.cpp @@ -15,9 +15,6 @@ // VulkanHpp Samples : Events // Use basic events -#include "../utils/geometries.hpp" -#include "../utils/math.hpp" -#include "../utils/shaders.hpp" #include "../utils/utils.hpp" #include "vulkan/vulkan.hpp" #include "SPIRV/GlslangToSpv.h" @@ -84,7 +81,7 @@ int main(int /*argc*/, char ** /*argv*/) device->resetFences(fence.get()); // Note that stepping through this code in the debugger is a bad idea because the GPU can TDR waiting for the event. - // Execute the code from vkQueueSubmit through vkSetEvent without breakpoints + // Execute the code from vk::Queue::submit() through vk::Device::setEvent() without breakpoints waitDestinationStageMask = vk::PipelineStageFlagBits::eBottomOfPipe; graphicsQueue.submit(submitInfo, fence.get()); @@ -92,7 +89,7 @@ int main(int /*argc*/, char ** /*argv*/) result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); if (result != vk::Result::eTimeout) { - std::cout << "Didn't get expected timeout in vkWaitForFences, exiting\n"; + std::cout << "Didn't get expected timeout in vk::Device::waitForFences, exiting\n"; exit(-1); } @@ -114,7 +111,7 @@ int main(int /*argc*/, char ** /*argv*/) commandBuffers[0]->setEvent(event.get(), vk::PipelineStageFlagBits::eBottomOfPipe); commandBuffers[0]->end(); - // Look for the event on the CPU. It should be RESET since we haven't sent the command buffer yet. + // Look for the event on the CPU. It should be vk::Result::eEventReset since we haven't sent the command buffer yet. result = device->getEventStatus(event.get()); assert(result == vk::Result::eEventReset); diff --git a/samples/ImmutableSampler/CMakeLists.txt b/samples/ImmutableSampler/CMakeLists.txt new file mode 100644 index 0000000..ce7e445 --- /dev/null +++ b/samples/ImmutableSampler/CMakeLists.txt @@ -0,0 +1,45 @@ +# 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(ImmutableSampler) + +set(HEADERS + ../utils/geometries.hpp + ../utils/math.hpp + ../utils/shaders.hpp + ../utils/utils.hpp +) + +set(SOURCES + ImmutableSampler.cpp + ../utils/math.cpp + ../utils/shaders.cpp + ../utils/utils.cpp + ../../glslang/StandAlone/ResourceLimits.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(ImmutableSampler + ${HEADERS} + ${SOURCES} +) + +set_target_properties(ImmutableSampler PROPERTIES FOLDER "Samples") +target_include_directories(ImmutableSampler PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(ImmutableSampler PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/ImmutableSampler/ImmutableSampler.cpp b/samples/ImmutableSampler/ImmutableSampler.cpp new file mode 100644 index 0000000..2be1172 --- /dev/null +++ b/samples/ImmutableSampler/ImmutableSampler.cpp @@ -0,0 +1,168 @@ +// 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 : ImmutableSampler +// Use an immutable sampler to texture 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 = "ImmutableSampler"; +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::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); + + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.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::su::SwapChainData swapChainData(physicalDevices[0], device, surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc + , graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); + + vk::su::DepthBufferData depthBufferData(physicalDevices[0], device, vk::Format::eD16Unorm, surfaceData.extent); + + vk::su::BufferData uniformBufferData(physicalDevices[0], device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); + vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix()); + + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surfaceData.surface.get())), depthBufferData.format); + + glslang::InitializeProcess(); + vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); + vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C); + glslang::FinalizeProcess(); + + std::vector framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); + + vk::su::BufferData vertexBufferData(physicalDevices[0], device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); + vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); + + /* VULKAN_KEY_START */ + + vk::su::TextureData textureData(physicalDevices[0], device); + + commandBuffers[0]->begin(vk::CommandBufferBeginInfo()); + textureData.setCheckerboardTexture(device, commandBuffers[0]); + + vk::DescriptorSetLayoutBinding bindings[2] = + { + vk::DescriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex), + vk::DescriptorSetLayoutBinding(1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment, &textureData.textureSampler.get()) + }; + vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 2, bindings)); + + // Create pipeline layout + vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); + + // Create a single pool to contain data for our descriptor set + vk::DescriptorPoolSize poolSizes[2] = + { + vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1), + vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1) + }; + vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 2, poolSizes)); + + // Populate descriptor sets + std::vector descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get())); + + vk::DescriptorBufferInfo bufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); + vk::DescriptorImageInfo imageInfo(textureData.textureSampler.get(), textureData.imageData->imageView.get(), vk::ImageLayout::eShaderReadOnlyOptimal); + vk::WriteDescriptorSet writeDescriptorSets[2] = + { + vk::WriteDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo), + vk::WriteDescriptorSet(descriptorSets[0].get(), 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo) + }; + device->updateDescriptorSets(vk::ArrayProxy(2, writeDescriptorSets), nullptr); + + /* VULKAN_KEY_END */ + + vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); + vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, sizeof(texturedCubeData[0]), pipelineLayout, renderPass); + + vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); + vk::ResultValue currentBuffer = device->acquireNextImageKHR(swapChainData.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); + vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 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::DeviceSize offset = 0; + commandBuffers[0]->bindVertexBuffers(0, vertexBufferData.buffer.get(), offset); + + vk::Viewport viewport(0.0f, 0.0f, static_cast(surfaceData.extent.width), static_cast(surfaceData.extent.height), 0.0f, 1.0f); + commandBuffers[0]->setViewport(0, viewport); + + vk::Rect2D scissor(vk::Offset2D(0, 0), surfaceData.extent); + commandBuffers[0]->setScissor(0, scissor); + + commandBuffers[0]->draw(12 * 3, 1, 0, 0); + commandBuffers[0]->endRenderPass(); + commandBuffers[0]->end(); + + vk::su::submitAndWait(device, graphicsQueue, commandBuffers[0]); + + presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), ¤tBuffer.value)); + Sleep(1000); + + device->waitIdle(); +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(surfaceData.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/InitTexture/CMakeLists.txt b/samples/InitTexture/CMakeLists.txt new file mode 100644 index 0000000..4b533c1 --- /dev/null +++ b/samples/InitTexture/CMakeLists.txt @@ -0,0 +1,45 @@ +# 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(InitTexture) + +set(HEADERS + ../utils/geometries.hpp + ../utils/math.hpp + ../utils/shaders.hpp + ../utils/utils.hpp +) + +set(SOURCES + InitTexture.cpp + ../utils/math.cpp + ../utils/shaders.cpp + ../utils/utils.cpp + ../../glslang/StandAlone/ResourceLimits.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(InitTexture + ${HEADERS} + ${SOURCES} +) + +set_target_properties(InitTexture PROPERTIES FOLDER "Samples") +target_include_directories(InitTexture PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(InitTexture PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/InitTexture/InitTexture.cpp b/samples/InitTexture/InitTexture.cpp new file mode 100644 index 0000000..8fe9e9e --- /dev/null +++ b/samples/InitTexture/InitTexture.cpp @@ -0,0 +1,166 @@ +// 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 : InitTexture +// Initialize texture + +#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 = "InitTexture"; +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::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(50, 50)); + + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.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); + + /* VULKAN_KEY_START */ + + vk::Format format = vk::Format::eR8G8B8A8Unorm; + vk::FormatProperties formatProperties = physicalDevices[0].getFormatProperties(format); + + // See if we can use a linear tiled image for a texture, if not, we will need a staging buffer for the texture data + bool needsStaging = !(formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eSampledImage); + + vk::UniqueImage image = device->createImageUnique(vk::ImageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, format, vk::Extent3D(surfaceData.extent, 1), 1, 1, + vk::SampleCountFlagBits::e1, needsStaging ? vk::ImageTiling::eOptimal : vk::ImageTiling::eLinear, + vk::ImageUsageFlagBits::eSampled | (needsStaging ? vk::ImageUsageFlagBits::eTransferDst : vk::ImageUsageFlagBits()), + vk::SharingMode::eExclusive, 0, nullptr, needsStaging ? vk::ImageLayout::eUndefined : vk::ImageLayout::ePreinitialized)); + + vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(image.get()); + uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevices[0].getMemoryProperties(), memoryRequirements.memoryTypeBits, + needsStaging ? vk::MemoryPropertyFlags() : (vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent)); + + // allocate memory + vk::UniqueDeviceMemory imageMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); + + // bind memory + device->bindImageMemory(image.get(), imageMemory.get(), 0); + + vk::UniqueBuffer textureBuffer; + vk::UniqueDeviceMemory textureBufferMemory; + if (needsStaging) + { + // Need a staging buffer to map and copy texture into + textureBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), surfaceData.extent.width * surfaceData.extent.height * 4, vk::BufferUsageFlagBits::eTransferSrc)); + + memoryRequirements = device->getBufferMemoryRequirements(textureBuffer.get()); + memoryTypeIndex = vk::su::findMemoryType(physicalDevices[0].getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); + + // allocate memory + textureBufferMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); + + // bind memory + device->bindBufferMemory(textureBuffer.get(), textureBufferMemory.get(), 0); + } + else + { + vk::SubresourceLayout subresourceLayout = device->getImageSubresourceLayout(image.get(), vk::ImageSubresource(vk::ImageAspectFlagBits::eColor)); + } + + void* data = device->mapMemory(needsStaging ? textureBufferMemory.get() : imageMemory.get(), 0, memoryRequirements.size, vk::MemoryMapFlags()); + + // Checkerboard of 16x16 pixel squares + unsigned char *pImageMemory = static_cast(data); + for (uint32_t row = 0; row < surfaceData.extent.height; row++) + { + for (uint32_t col = 0; col < surfaceData.extent.width; col++) + { + unsigned char rgb = (((row & 0x10) == 0) ^ ((col & 0x10) == 0)) * 255; + pImageMemory[0] = rgb; + pImageMemory[1] = rgb; + pImageMemory[2] = rgb; + pImageMemory[3] = 255; + pImageMemory += 4; + } + } + + device->unmapMemory(needsStaging ? textureBufferMemory.get() : imageMemory.get()); + + commandBuffers[0]->begin(vk::CommandBufferBeginInfo()); + if (needsStaging) + { + // Since we're going to blit to the texture image, set its layout to eTransferDstOptimal + vk::su::setImageLayout(commandBuffers[0], image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer); + vk::BufferImageCopy copyRegion(0, surfaceData.extent.width, surfaceData.extent.height, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), vk::Extent3D(surfaceData.extent, 1)); + commandBuffers[0]->copyBufferToImage(textureBuffer.get(), image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion); + // Set the layout for the texture image from eTransferDstOptimal to SHADER_READ_ONLY + vk::su::setImageLayout(commandBuffers[0], image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader); + } + else + { + // If we can use the linear tiled image as a texture, just do it + vk::su::setImageLayout(commandBuffers[0], image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eFragmentShader); + } + + commandBuffers[0]->end(); + vk::su::submitAndWait(device, graphicsQueue, commandBuffers[0]); + + vk::UniqueSampler sampler = device->createSamplerUnique(vk::SamplerCreateInfo(vk::SamplerCreateFlags(), vk::Filter::eNearest, vk::Filter::eNearest, vk::SamplerMipmapMode::eNearest, + vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, 0.0f, false, 1.0f, false, vk::CompareOp::eNever, 0.0f, 0.0f, + vk::BorderColor::eFloatOpaqueWhite)); + + vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); + vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image.get(), vk::ImageViewType::e2D, format, componentMapping, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); + vk::UniqueImageView imageView = device->createImageViewUnique(imageViewCreateInfo); + + /* VULKAN_KEY_END */ + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(surfaceData.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/InputAttachment/CMakeLists.txt b/samples/InputAttachment/CMakeLists.txt new file mode 100644 index 0000000..85e6349 --- /dev/null +++ b/samples/InputAttachment/CMakeLists.txt @@ -0,0 +1,45 @@ +# 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(InputAttachment) + +set(HEADERS + ../utils/geometries.hpp + ../utils/math.hpp + ../utils/shaders.hpp + ../utils/utils.hpp +) + +set(SOURCES + InputAttachment.cpp + ../utils/math.cpp + ../utils/shaders.cpp + ../utils/utils.cpp + ../../glslang/StandAlone/ResourceLimits.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(InputAttachment + ${HEADERS} + ${SOURCES} +) + +set_target_properties(InputAttachment PROPERTIES FOLDER "Samples") +target_include_directories(InputAttachment PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(InputAttachment PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/InputAttachment/InputAttachment.cpp b/samples/InputAttachment/InputAttachment.cpp new file mode 100644 index 0000000..4c03662 --- /dev/null +++ b/samples/InputAttachment/InputAttachment.cpp @@ -0,0 +1,211 @@ +// 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 : InputAttachment +// Use an input attachment to draw a yellow triangle + +#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 = "InputAttachment"; +static char const* EngineName = "Vulkan.hpp"; + +static std::string vertexShaderText = R"( +#version 450 + +vec2 vertices[3]; + +void main() +{ + vertices[0] = vec2(-1.0f, -1.0f); + vertices[1] = vec2( 1.0f, -1.0f); + vertices[2] = vec2( 0.0f, 1.0f); + + gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0f, 1.0f); +} +)"; + +// Use subpassLoad to read from input attachment +static const char *fragmentShaderText = R"( +#version 450 + +layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputAttachment; + +layout (location = 0) out vec4 outColor; + +void main() +{ + outColor = subpassLoad(inputAttachment); +} +)"; +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::FormatProperties formatProperties = physicalDevices[0].getFormatProperties(vk::Format::eR8G8B8A8Unorm); + if (!(formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eColorAttachment)) + { + std::cout << "vk::Format::eR8G8B8A8Unorm format unsupported for input attachment\n"; + exit(-1); + } + + vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); + + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.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::su::SwapChainData swapChainData(physicalDevices[0], device, surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, + graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); + + /* VULKAN_KEY_START */ + + // Create a framebuffer with 2 attachments, one the color attachment the shaders render into, and the other an input attachment which + // will be cleared to yellow, and then used by the shaders to color the drawn triangle. Final result should be a yellow triangle + + // Create the image that will be used as the input attachment + // The image for the color attachment is the presentable image already created as part of the SwapChainData + vk::UniqueImage inputImage = device->createImageUnique(vk::ImageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, swapChainData.colorFormat, vk::Extent3D(surfaceData.extent, 1), 1, 1, + vk::SampleCountFlagBits::e1, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eInputAttachment | vk::ImageUsageFlagBits::eTransferDst)); + + vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(inputImage.get()); + uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevices[0].getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlags()); + vk::UniqueDeviceMemory inputMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); + device->bindImageMemory(inputImage.get(), inputMemory.get(), 0); + + // Set the image layout to TRANSFER_DST_OPTIMAL to be ready for clear + commandBuffers[0]->begin(vk::CommandBufferBeginInfo()); + vk::su::setImageLayout(commandBuffers[0], inputImage.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, + vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer); + + commandBuffers[0]->clearColorImage(inputImage.get(), vk::ImageLayout::eTransferDstOptimal, vk::ClearColorValue(std::array({ {1.0f, 1.0f, 0.0f, 0.0f} })), + vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS)); + + // Set the image layout to SHADER_READONLY_OPTIMAL for use by the shaders + vk::su::setImageLayout(commandBuffers[0], inputImage.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, + vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader); + + vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); + vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), inputImage.get(), vk::ImageViewType::e2D, swapChainData.colorFormat, componentMapping, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); + vk::UniqueImageView inputAttachmentView = device->createImageViewUnique(imageViewCreateInfo); + + vk::DescriptorSetLayoutBinding layoutBinding(0, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment); + vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 1, &layoutBinding)); + + vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); + + vk::AttachmentDescription attachments[2] = + { + // First attachment is the color attachment - clear at the beginning of the renderpass and transition layout to PRESENT_SRC_KHR at the end of renderpass + vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), swapChainData.colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore, + vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR), + // Second attachment is input attachment. Once cleared it should have width*height yellow pixels. + // Doing a subpassLoad in the fragment shader should give the shader the color at the fragments x,y location from the input attachment + vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), swapChainData.colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eDontCare, + vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eShaderReadOnlyOptimal) + }; + vk::AttachmentReference colorReference(0, vk::ImageLayout::eColorAttachmentOptimal); + vk::AttachmentReference inputReference(1, vk::ImageLayout::eShaderReadOnlyOptimal); + vk::SubpassDescription subPass(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 1, &inputReference, 1, &colorReference); + vk::UniqueRenderPass renderPass = device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachments, 1, &subPass)); + + 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, swapChainData.imageViews, inputAttachmentView, surfaceData.extent); + + vk::DescriptorPoolSize poolSize(vk::DescriptorType::eInputAttachment, 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::DescriptorImageInfo inputImageInfo(nullptr, inputAttachmentView.get(), vk::ImageLayout::eShaderReadOnlyOptimal); + vk::WriteDescriptorSet writeDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eInputAttachment, &inputImageInfo); + device->updateDescriptorSets(vk::ArrayProxy(1, &writeDescriptorSet), nullptr); + + vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); + vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, 0, pipelineLayout, renderPass); + + vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); + + vk::ResultValue result = device->acquireNextImage2KHR(vk::AcquireNextImageInfoKHR(swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get())); + assert(result.result == vk::Result::eSuccess); + uint32_t currentBuffer = result.value; + + vk::ClearValue clearValue; + clearValue.color = vk::ClearColorValue(std::array({ 0.2f, 0.2f, 0.2f, 0.2f })); + commandBuffers[0]->beginRenderPass(vk::RenderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 1, &clearValue), 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(surfaceData.extent.width), static_cast(surfaceData.extent.height), 0.0f, 1.0f); + commandBuffers[0]->setViewport(0, viewport); + + vk::Rect2D scissor(vk::Offset2D(0, 0), surfaceData.extent); + commandBuffers[0]->setScissor(0, scissor); + + commandBuffers[0]->draw(3, 1, 0, 0); + commandBuffers[0]->endRenderPass(); + commandBuffers[0]->end(); + + /* VULKAN_KEY_END */ + + vk::su::submitAndWait(device, graphicsQueue, commandBuffers[0]); + + presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), ¤tBuffer)); + Sleep(1000); + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(surfaceData.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/utils/geometries.hpp b/samples/utils/geometries.hpp index 3efa0b7..dcafd3d 100644 --- a/samples/utils/geometries.hpp +++ b/samples/utils/geometries.hpp @@ -19,6 +19,13 @@ struct VertexPC float r, g, b, a; // Color }; +struct VertexPT +{ + float x, y, z, w; // Position data + float u, v; // texture u,v +}; + + static const VertexPC coloredCubeData[] = { // red face @@ -65,3 +72,49 @@ static const VertexPC coloredCubeData[] = { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f }, }; +static const VertexPT texturedCubeData[] = +{ + // left face + { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, + { -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, + { -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, + { -1.0f, 1.0f, 1.0f, 1.0f, 0.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 }, + // front face + { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.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, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, + { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, + { -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, + // top face + { -1.0f, -1.0f, -1.0f, 1.0f, 0.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, -1.0f, -1.0f, 1.0f, 0.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, 0.0f }, + // bottom 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 }, + { -1.0f, 1.0f, 1.0f, 1.0f, 0.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, 0.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, + // right face + { 1.0f, 1.0f, -1.0f, 1.0f, 0.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, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, + { 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, + // back face + { -1.0f, 1.0f, 1.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, 0.0f }, + { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, + { 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, +}; + diff --git a/samples/utils/shaders.cpp b/samples/utils/shaders.cpp index 26dea06..d53891c 100644 --- a/samples/utils/shaders.cpp +++ b/samples/utils/shaders.cpp @@ -15,6 +15,7 @@ #include "shaders.hpp" #include "vulkan/vulkan.hpp" +#include "glslang/StandAlone/ResourceLimits.h" #include "SPIRV/GlslangToSpv.h" namespace vk @@ -38,102 +39,6 @@ namespace vk } } - 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); @@ -144,13 +49,10 @@ namespace vk 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)) + if (!shader.parse(&glslang::DefaultTBuiltInResource, 100, false, messages)) { puts(shader.getInfoLog()); puts(shader.getInfoDebugLog()); diff --git a/samples/utils/shaders.hpp b/samples/utils/shaders.hpp index c37d81d..d116c79 100644 --- a/samples/utils/shaders.hpp +++ b/samples/utils/shaders.hpp @@ -52,6 +52,31 @@ void main() } )"; +// vertex shader with (P)osition and (T)exCoord in and (T)exCoord out +const std::string vertexShaderText_PT_T = R"( +#version 400 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (std140, binding = 0) uniform buffer +{ + mat4 mvp; +} uniformBuffer; + +layout (location = 0) in vec4 pos; +layout (location = 1) in vec2 inTexCoord; + +layout (location = 0) out vec2 outTexCoord; + +void main() +{ + outTexCoord = inTexCoord; + gl_Position = uniformBuffer.mvp * pos; +} +)"; + + // fragment shader with (C)olor in and (C)olor out const std::string fragmentShaderText_C_C = R"( #version 400 @@ -69,3 +94,22 @@ void main() } )"; +// fragment shader with (T)exCoord in and (C)olor out +const std::string fragmentShaderText_T_C = R"( +#version 400 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (binding = 1) uniform sampler2D tex; + +layout (location = 0) in vec2 inTexCoord; + +layout (location = 0) out vec4 outColor; + +void main() +{ + outColor = texture(tex, inTexCoord); +} +)"; + diff --git a/samples/utils/utils.cpp b/samples/utils/utils.cpp index e7f9a5c..00f614b 100644 --- a/samples/utils/utils.cpp +++ b/samples/utils/utils.cpp @@ -130,13 +130,20 @@ namespace vk vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule.get(), "main") }; - vk::VertexInputBindingDescription vertexInputBindingDescription(0, vertexStride); - vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] = + vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo; + if (0 < vertexStride) { - 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::VertexInputBindingDescription vertexInputBindingDescription(0, vertexStride); + vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] = + { + vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32A32Sfloat, 0), + vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32A32Sfloat, 16) + }; + pipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = 1; + pipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = &vertexInputBindingDescription; + pipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = 2; + pipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions; + } vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList);