├── .gitattributes ├── .gitignore ├── LICENSE.txt ├── README.md ├── hellovulkan ├── .gitignore ├── build │ ├── HelloVulkan_2013.sln │ ├── HelloVulkan_2013.vcxproj │ ├── HelloVulkan_2015.sln │ ├── HelloVulkan_2015.vcxproj │ └── Windows10SDKVS13_x64.props ├── premake │ └── premake5.lua ├── src │ ├── ImageIO.cpp │ ├── ImageIO.h │ ├── Main.cpp │ ├── RubyTexture.h │ ├── Shaders.h │ ├── Utility.cpp │ ├── Utility.h │ ├── VulkanQuad.cpp │ ├── VulkanQuad.h │ ├── VulkanSample.cpp │ ├── VulkanSample.h │ ├── VulkanTexturedQuad.cpp │ ├── VulkanTexturedQuad.h │ ├── Window.cpp │ ├── Window.h │ ├── basic.frag │ ├── basic.spv │ ├── textured.frag │ ├── textured.spv │ ├── tri.vert │ └── vs.spv └── tools │ ├── binaryToHeader.py │ └── sourceToHeader.py └── premake ├── LICENSE.txt ├── amd_premake_util.lua └── premake5.exe /.gitattributes: -------------------------------------------------------------------------------- 1 | # Vulkan is a cross-platform API. 2 | # Deal with different line endings on different operating systems. 3 | * text=auto 4 | 5 | # Explicitly declare text files you want to always be normalized and converted 6 | # to native line endings on checkout. 7 | *.h text 8 | *.cpp text 9 | *.inl text 10 | *.frag text 11 | *.vert text 12 | *.txt text 13 | *.lua text 14 | *.md text 15 | *.py text 16 | 17 | # Declare files that will always have CRLF line endings on checkout. 18 | *.vcxproj text eol=crlf 19 | *.filters text eol=crlf 20 | *.props text eol=crlf 21 | *.sln text eol=crlf 22 | *.bat text eol=crlf 23 | 24 | # Denote all files that are binary and should not be modified. 25 | *.pdf binary 26 | *.jpg binary 27 | *.png binary 28 | *.spv binary 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /hellovulkan/build/HelloVulkan_2015.VC.db 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Hello Vulkan 2 | ============ 3 | 4 | Welcome to a Vulkan™ "Hello Triangle" sample which shows how to set up a window, set up a Vulkan context, and render a triangle. This sample is designed to help you get started with Vulkan and does not use any wrappers or helper libraries - pure Vulkan all the way. 5 | 6 | License 7 | ------- 8 | 9 | MIT: see `LICENSE.txt` for details. 10 | 11 | System requirements 12 | ------------------- 13 | 14 | * AMD Radeon™ GCN-based GPU (HD 7000 series or newer) 15 | * Or other Vulkan™ compatible discrete GPU 16 | * 64-bit Windows® 7 (SP1 with the [Platform Update](https://msdn.microsoft.com/en-us/library/windows/desktop/jj863687.aspx)), Windows® 8.1, or Windows® 10 17 | * Visual Studio® 2013 or Visual Studio® 2015 18 | * Graphics driver with Vulkan support 19 | * For example, AMD Radeon Software Crimson Edition 16.5.2 or later 20 | * The [Vulkan SDK](https://vulkan.lunarg.com) must be installed 21 | 22 | Building 23 | -------- 24 | 25 | Visual Studio files can be found in the `hellovulkan\build` directory. 26 | 27 | If you need to regenerate the Visual Studio files, open a command prompt in the `hellovulkan\premake` directory and run `..\..\premake\premake5.exe vs2015` (or `..\..\premake\premake5.exe vs2013` for Visual Studio 2013.) 28 | 29 | Vulkan also supports Linux®, of course, and Premake can generate GNU Makefiles. However, at this time, the sample itself is Windows specific (because the helper code in Window.h/.cpp is Windows specific). 30 | 31 | Third-party software 32 | ------------------ 33 | 34 | * Premake is distributed under the terms of the BSD License. See `premake\LICENSE.txt`. 35 | 36 | Known issues 37 | ------------ 38 | 39 | The sample uses `PRESENT_MODE_FIFO` to run with VSync. On the NVIDIA 365.19 driver, FIFO is ignored and the sample will exit after a very brief period of time. You can increase the number of frames rendered to ensure it remains visible for a couple of seconds. 40 | 41 | Attribution 42 | ----------- 43 | 44 | * AMD, the AMD Arrow logo, Radeon, and combinations thereof are either registered trademarks or trademarks of Advanced Micro Devices, Inc. in the United States and/or other countries. 45 | * Microsoft, Visual Studio, and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. 46 | * Linux is the registered trademark of Linus Torvalds in the U.S. and other countries. 47 | * Vulkan and the Vulkan logo are trademarks of the Khronos Group, Inc. 48 | -------------------------------------------------------------------------------- /hellovulkan/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, etc. 2 | 3 | # User-specific files 4 | *.suo 5 | *.user 6 | 7 | # Build results 8 | [Dd]esktop_*/ 9 | HelloVulkan_Debug_*.* 10 | HelloVulkan_Release_*.* 11 | 12 | # Visual Studo 2015 cache/options directory 13 | .vs/ 14 | 15 | # Visual C++ cache files 16 | ipch/ 17 | *.aps 18 | *.ncb 19 | *.opensdf 20 | *.sdf 21 | *.cachefile 22 | *.opendb 23 | 24 | # Visual Studio profiler 25 | *.psess 26 | *.vsp 27 | *.vspx 28 | 29 | # Installshield output folder 30 | [Ee]xpress/ 31 | 32 | # Backup & report files from converting an old project file 33 | # to a newer Visual Studio version. Backup files are not needed, 34 | # because we have git ;-) 35 | _UpgradeReport_Files/ 36 | Backup*/ 37 | UpgradeLog*.XML 38 | UpgradeLog*.htm 39 | -------------------------------------------------------------------------------- /hellovulkan/build/HelloVulkan_2013.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloVulkan", "HelloVulkan_2013.vcxproj", "{4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x64 = Debug|x64 9 | Release|x64 = Release|x64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}.Debug|x64.ActiveCfg = Debug|x64 13 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}.Debug|x64.Build.0 = Debug|x64 14 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}.Release|x64.ActiveCfg = Release|x64 15 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}.Release|x64.Build.0 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /hellovulkan/build/HelloVulkan_2013.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00} 15 | true 16 | Win32Proj 17 | HelloVulkan 18 | HelloVulkan 19 | 20 | 21 | 22 | Application 23 | true 24 | Unicode 25 | v120 26 | 27 | 28 | Application 29 | false 30 | Unicode 31 | v120 32 | true 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | true 48 | ..\bin\ 49 | Desktop_2013\x64\Debug\ 50 | HelloVulkan_Debug_2013 51 | .exe 52 | 53 | 54 | false 55 | ..\bin\ 56 | Desktop_2013\x64\Release\ 57 | HelloVulkan_Release_2013 58 | .exe 59 | 60 | 61 | 62 | NotUsing 63 | Level4 64 | true 65 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;DEBUG;_WINDOWS;%(PreprocessorDefinitions) 66 | $(VULKAN_SDK)\include;%(AdditionalIncludeDirectories) 67 | ProgramDatabase 68 | Disabled 69 | Fast 70 | 71 | 72 | Windows 73 | true 74 | $(VULKAN_SDK)\lib\vulkan-1.lib;%(AdditionalDependencies) 75 | true 76 | 77 | 78 | 79 | 80 | NotUsing 81 | Level4 82 | true 83 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;PROFILE;_WINDOWS;%(PreprocessorDefinitions) 84 | $(VULKAN_SDK)\include;%(AdditionalIncludeDirectories) 85 | ProgramDatabase 86 | Full 87 | true 88 | true 89 | false 90 | true 91 | Fast 92 | 93 | 94 | Windows 95 | true 96 | true 97 | true 98 | $(VULKAN_SDK)\lib\vulkan-1.lib;%(AdditionalDependencies) 99 | true 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /hellovulkan/build/HelloVulkan_2015.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelloVulkan", "HelloVulkan_2015.vcxproj", "{4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x64 = Debug|x64 9 | Release|x64 = Release|x64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}.Debug|x64.ActiveCfg = Debug|x64 13 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}.Debug|x64.Build.0 = Debug|x64 14 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}.Release|x64.ActiveCfg = Release|x64 15 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00}.Release|x64.Build.0 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /hellovulkan/build/HelloVulkan_2015.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {4ABD8B07-B672-04FD-3F67-FED3AB1BFB00} 15 | true 16 | Win32Proj 17 | HelloVulkan 18 | HelloVulkan 19 | 8.1 20 | 21 | 22 | 23 | Application 24 | true 25 | Unicode 26 | v140 27 | 28 | 29 | Application 30 | false 31 | Unicode 32 | v140 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | true 47 | ..\bin\ 48 | Desktop_2015\x64\Debug\ 49 | HelloVulkan_Debug_2015 50 | .exe 51 | 52 | 53 | false 54 | ..\bin\ 55 | Desktop_2015\x64\Release\ 56 | HelloVulkan_Release_2015 57 | .exe 58 | 59 | 60 | 61 | NotUsing 62 | Level4 63 | true 64 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;DEBUG;_WINDOWS;%(PreprocessorDefinitions) 65 | $(VULKAN_SDK)\include;%(AdditionalIncludeDirectories) 66 | ProgramDatabase 67 | Disabled 68 | Fast 69 | 70 | 71 | Windows 72 | true 73 | $(VULKAN_SDK)\lib\vulkan-1.lib;%(AdditionalDependencies) 74 | true 75 | 76 | 77 | 78 | 79 | NotUsing 80 | Level4 81 | true 82 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;PROFILE;_WINDOWS;%(PreprocessorDefinitions) 83 | $(VULKAN_SDK)\include;%(AdditionalIncludeDirectories) 84 | ProgramDatabase 85 | Full 86 | true 87 | true 88 | false 89 | true 90 | Fast 91 | 92 | 93 | Windows 94 | true 95 | true 96 | true 97 | $(VULKAN_SDK)\lib\vulkan-1.lib;%(AdditionalDependencies) 98 | true 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /hellovulkan/build/Windows10SDKVS13_x64.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(ProgramFiles)\Windows Kits\10\bin\x86;$(ExecutablePath) 7 | $(ProgramFiles)\Windows Kits\10\Include\10.0.10240.0\um;$(ProgramFiles)\Windows Kits\10\Include\10.0.10240.0\shared;$(ProgramFiles)\Windows Kits\10\Include\10.0.10240.0\winrt;$(IncludePath) 8 | $(ProgramFiles)\Windows Kits\10\lib\10.0.10240.0\um\x64;$(LibraryPath) 9 | $(ProgramFiles)\Windows Kits\10\Include\10.0.10240.0\um;$(ProgramFiles)\Windows Kits\10\Include\10.0.10240.0\shared;$(ProgramFiles)\Windows Kits\10\Include\10.0.10240.0\winrt;$(ExcludePath) 10 | 11 | 12 | -------------------------------------------------------------------------------- /hellovulkan/premake/premake5.lua: -------------------------------------------------------------------------------- 1 | _AMD_SAMPLE_NAME = "HelloVulkan" 2 | 3 | dofile ("../../premake/amd_premake_util.lua") 4 | 5 | workspace (_AMD_SAMPLE_NAME) 6 | configurations { "Debug", "Release" } 7 | platforms { "x64" } 8 | location "../build" 9 | filename (_AMD_SAMPLE_NAME .. _AMD_VS_SUFFIX) 10 | startproject (_AMD_SAMPLE_NAME) 11 | 12 | filter "platforms:x64" 13 | system "Windows" 14 | architecture "x64" 15 | 16 | project (_AMD_SAMPLE_NAME) 17 | kind "WindowedApp" 18 | language "C++" 19 | location "../build" 20 | filename (_AMD_SAMPLE_NAME .. _AMD_VS_SUFFIX) 21 | uuid "4ABD8B07-B672-04FD-3F67-FED3AB1BFB00" 22 | targetdir "../bin" 23 | objdir "../build/%{_AMD_SAMPLE_DIR_LAYOUT}" 24 | warnings "Extra" 25 | floatingpoint "Fast" 26 | 27 | -- Specify WindowsTargetPlatformVersion here for VS2015 28 | windowstarget (_AMD_WIN_SDK_VERSION) 29 | 30 | files { "../src/**.h", "../src/**.cpp" } 31 | links { "$(VULKAN_SDK)/lib/vulkan-1.lib" } 32 | includedirs { "$(VULKAN_SDK)/include" } 33 | 34 | defines { "_CRT_SECURE_NO_WARNINGS" } 35 | 36 | filter "configurations:Debug" 37 | defines { "WIN32", "_DEBUG", "DEBUG", "_WINDOWS" } 38 | flags { "Symbols", "FatalWarnings", "Unicode", "WinMain" } 39 | targetsuffix ("_Debug" .. _AMD_VS_SUFFIX) 40 | 41 | filter "configurations:Release" 42 | defines { "WIN32", "NDEBUG", "PROFILE", "_WINDOWS" } 43 | flags { "LinkTimeOptimization", "Symbols", "FatalWarnings", "Unicode", "WinMain" } 44 | targetsuffix ("_Release" .. _AMD_VS_SUFFIX) 45 | optimize "On" 46 | -------------------------------------------------------------------------------- /hellovulkan/src/ImageIO.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include "ImageIO.h" 24 | 25 | #include 26 | #include 27 | #include 28 | // for _com_error 29 | #include 30 | 31 | #include "Utility.h" 32 | #define SAFE_WIC(expr) do {const auto r = expr; if (FAILED(r)) {_com_error err (r); OutputDebugString (err.ErrorMessage()); __debugbreak ();} } while (0,0) 33 | 34 | using namespace Microsoft::WRL; 35 | 36 | #undef LoadImage 37 | 38 | namespace { 39 | std::vector LoadInternal(ComPtr factory, ComPtr stream, 40 | const int rowAlignment, int* outputWidth, int* outputHeight) 41 | { 42 | ComPtr decoder; 43 | factory->CreateDecoderFromStream(stream.Get(), nullptr, 44 | WICDecodeMetadataCacheOnDemand, &decoder); 45 | 46 | ComPtr frame; 47 | decoder->GetFrame(0, &frame); 48 | 49 | ComPtr converter; 50 | factory->CreateFormatConverter(&converter); 51 | converter->Initialize( 52 | frame.Get(), GUID_WICPixelFormat32bppRGBA, 53 | WICBitmapDitherTypeNone, nullptr, 0.f, 54 | WICBitmapPaletteTypeMedianCut); 55 | 56 | UINT width, height; 57 | converter->GetSize(&width, &height); 58 | 59 | std::vector result( 60 | RoundToNextMultiple(width, static_cast (rowAlignment)) * height * 4); 61 | 62 | SAFE_WIC(converter->CopyPixels(nullptr, 63 | RoundToNextMultiple(width, static_cast (rowAlignment)) * 4, 64 | static_cast (result.size()), result.data())); 65 | 66 | if (outputWidth) { 67 | *outputWidth = static_cast (width); 68 | } 69 | 70 | if (outputHeight) { 71 | *outputHeight = static_cast (height); 72 | } 73 | 74 | return result; 75 | } 76 | } 77 | 78 | std::vector LoadImageFromFile (const char* path, const int rowAlignment, 79 | int* outputWidth, int* outputHeight) 80 | { 81 | ComPtr factory; 82 | HRESULT hr = CoCreateInstance ( 83 | CLSID_WICImagingFactory, 84 | NULL, 85 | CLSCTX_INPROC_SERVER, 86 | IID_PPV_ARGS (&factory) 87 | ); 88 | 89 | if (FAILED(hr)) { 90 | throw std::runtime_error ("Could not create WIC factory"); 91 | } 92 | 93 | ComPtr decoder; 94 | 95 | std::vector pathWchar (::strlen (path) + 1); 96 | mbstowcs (pathWchar.data (), path, pathWchar.size ()); 97 | 98 | ComPtr stream; 99 | factory->CreateStream(&stream); 100 | stream->InitializeFromFilename(pathWchar.data (), GENERIC_READ); 101 | 102 | return LoadInternal(factory, stream, rowAlignment, outputWidth, outputHeight); 103 | 104 | } 105 | 106 | std::vector LoadImageFromMemory(const void* data, const std::size_t size, 107 | const int rowAlignment, int* outputWidth, int* outputHeight) 108 | { 109 | ComPtr factory; 110 | HRESULT hr = CoCreateInstance( 111 | CLSID_WICImagingFactory, 112 | NULL, 113 | CLSCTX_INPROC_SERVER, 114 | IID_PPV_ARGS(&factory) 115 | ); 116 | 117 | if (FAILED (hr)) { 118 | throw std::runtime_error ("Could not create WIC factory"); 119 | } 120 | 121 | ComPtr stream; 122 | factory->CreateStream(&stream); 123 | 124 | // This is fine here as the memory will live on when the stream is long gone 125 | stream->InitializeFromMemory(static_cast (const_cast (data)), 126 | static_cast (size)); 127 | 128 | return LoadInternal(factory, stream, rowAlignment, outputWidth, outputHeight); 129 | } 130 | -------------------------------------------------------------------------------- /hellovulkan/src/ImageIO.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #ifndef AMD_VULKAN_SAMPLE_IMAGE_IO_H_ 24 | #define AMD_VULKAN_SAMPLE_IMAGE_IO_H_ 25 | 26 | #include 27 | #include 28 | 29 | #ifdef LoadImage 30 | #undef LoadImage 31 | #endif 32 | 33 | std::vector LoadImageFromFile (const char* path, const int rowAlignment, 34 | int* width, int* height); 35 | 36 | std::vector LoadImageFromMemory(const void* data, const std::size_t size, const int rowAlignment, 37 | int* width, int* height); 38 | 39 | #endif -------------------------------------------------------------------------------- /hellovulkan/src/Main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include "VulkanQuad.h" 24 | #include "VulkanTexturedQuad.h" 25 | 26 | int WinMain( 27 | _In_ HINSTANCE /* hInstance */, 28 | _In_opt_ HINSTANCE /* hPrevInstance */, 29 | _In_ LPSTR /* lpCmdLine */, 30 | _In_ int /* nCmdShow */ 31 | ) 32 | { 33 | AMD::VulkanSample* sample = nullptr; 34 | 35 | const auto sampleId = 0; 36 | 37 | switch (sampleId) 38 | { 39 | case 0: sample = new AMD::VulkanQuad; break; 40 | case 1: sample = new AMD::VulkanTexturedQuad; break; 41 | } 42 | 43 | if (sample == nullptr || sample->IsInitialized() == false) 44 | { 45 | return 1; 46 | } 47 | 48 | sample->Run(512); 49 | delete sample; 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /hellovulkan/src/Shaders.h: -------------------------------------------------------------------------------- 1 | const unsigned char BasicFragmentShader [] = { 2 | 0x3 , 0x2 , 0x23, 0x7 , 0x0 , 0x0 , 0x1 , 0x0 , 0x1 , 0x0 , 0x8 , 0x0 , 0x13, 3 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x11, 0x0 , 0x2 , 0x0 , 0x1 , 0x0 , 4 | 0x0 , 0x0 , 0xb , 0x0 , 0x6 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x47, 0x4c, 0x53, 5 | 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x0 , 0x0 , 0x0 , 0x0 , 6 | 0xe , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0xf , 7 | 0x0 , 0x7 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x6d, 0x61, 8 | 0x69, 0x6e, 0x0 , 0x0 , 0x0 , 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 0xc , 0x0 , 0x0 , 9 | 0x0 , 0x10, 0x0 , 0x3 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x7 , 0x0 , 0x0 , 0x0 , 10 | 0x3 , 0x0 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x90, 0x1 , 0x0 , 0x0 , 0x4 , 11 | 0x0 , 0x9 , 0x0 , 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 12 | 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 13 | 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x0 , 0x0 , 0x4 , 0x0 , 0x9 , 0x0 , 14 | 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 15 | 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 16 | 0x30, 0x70, 0x61, 0x63, 0x6b, 0x0 , 0x5 , 0x0 , 0x4 , 0x0 , 0x4 , 0x0 , 0x0 , 17 | 0x0 , 0x6d, 0x61, 0x69, 0x6e, 0x0 , 0x0 , 0x0 , 0x0 , 0x5 , 0x0 , 0x5 , 0x0 , 18 | 0x9 , 0x0 , 0x0 , 0x0 , 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x6f, 0x6c, 19 | 0x6f, 0x72, 0x0 , 0x5 , 0x0 , 0x3 , 0x0 , 0xc , 0x0 , 0x0 , 0x0 , 0x75, 0x76, 20 | 0x0 , 0x0 , 0x47, 0x0 , 0x4 , 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 0x1e, 0x0 , 0x0 , 21 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x47, 0x0 , 0x4 , 0x0 , 0xc , 0x0 , 0x0 , 0x0 , 22 | 0x1e, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x13, 0x0 , 0x2 , 0x0 , 0x2 , 23 | 0x0 , 0x0 , 0x0 , 0x21, 0x0 , 0x3 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 24 | 0x0 , 0x0 , 0x16, 0x0 , 0x3 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x0 , 25 | 0x0 , 0x17, 0x0 , 0x4 , 0x0 , 0x7 , 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 26 | 0x4 , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x4 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x3 , 27 | 0x0 , 0x0 , 0x0 , 0x7 , 0x0 , 0x0 , 0x0 , 0x3b, 0x0 , 0x4 , 0x0 , 0x8 , 0x0 , 28 | 0x0 , 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x17, 0x0 , 0x4 , 29 | 0x0 , 0xa , 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 30 | 0x20, 0x0 , 0x4 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0xa , 31 | 0x0 , 0x0 , 0x0 , 0x3b, 0x0 , 0x4 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0xc , 0x0 , 32 | 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x2b, 0x0 , 0x4 , 0x0 , 0x6 , 0x0 , 0x0 , 33 | 0x0 , 0xe , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2b, 0x0 , 0x4 , 0x0 , 34 | 0x6 , 0x0 , 0x0 , 0x0 , 0xf , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x80, 0x3f, 0x36, 35 | 0x0 , 0x5 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 36 | 0x0 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0xf8, 0x0 , 0x2 , 0x0 , 0x5 , 0x0 , 0x0 , 37 | 0x0 , 0x3d, 0x0 , 0x4 , 0x0 , 0xa , 0x0 , 0x0 , 0x0 , 0xd , 0x0 , 0x0 , 0x0 , 38 | 0xc , 0x0 , 0x0 , 0x0 , 0x51, 0x0 , 0x5 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x10, 39 | 0x0 , 0x0 , 0x0 , 0xd , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x51, 0x0 , 40 | 0x5 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x11, 0x0 , 0x0 , 0x0 , 0xd , 0x0 , 0x0 , 41 | 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x50, 0x0 , 0x7 , 0x0 , 0x7 , 0x0 , 0x0 , 0x0 , 42 | 0x12, 0x0 , 0x0 , 0x0 , 0x10, 0x0 , 0x0 , 0x0 , 0x11, 0x0 , 0x0 , 0x0 , 0xe , 43 | 0x0 , 0x0 , 0x0 , 0xf , 0x0 , 0x0 , 0x0 , 0x3e, 0x0 , 0x3 , 0x0 , 0x9 , 0x0 , 44 | 0x0 , 0x0 , 0x12, 0x0 , 0x0 , 0x0 , 0xfd, 0x0 , 0x1 , 0x0 , 0x38, 0x0 , 0x1 , 45 | 0x0 , 46 | }; 47 | const unsigned char BasicVertexShader [] = { 48 | 0x3 , 0x2 , 0x23, 0x7 , 0x0 , 0x0 , 0x1 , 0x0 , 0x1 , 0x0 , 0x8 , 0x0 , 0x21, 49 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x11, 0x0 , 0x2 , 0x0 , 0x1 , 0x0 , 50 | 0x0 , 0x0 , 0x11, 0x0 , 0x2 , 0x0 , 0x20, 0x0 , 0x0 , 0x0 , 0xb , 0x0 , 0x6 , 51 | 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 52 | 0x2e, 0x34, 0x35, 0x30, 0x0 , 0x0 , 0x0 , 0x0 , 0xe , 0x0 , 0x3 , 0x0 , 0x0 , 53 | 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0xf , 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 54 | 0x0 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x6d, 0x61, 0x69, 0x6e, 0x0 , 0x0 , 0x0 , 55 | 0x0 , 0xd , 0x0 , 0x0 , 0x0 , 0x12, 0x0 , 0x0 , 0x0 , 0x1d, 0x0 , 0x0 , 0x0 , 56 | 0x1f, 0x0 , 0x0 , 0x0 , 0x3 , 0x0 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x90, 57 | 0x1 , 0x0 , 0x0 , 0x4 , 0x0 , 0x9 , 0x0 , 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 58 | 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 59 | 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x0 , 0x0 , 60 | 0x4 , 0x0 , 0x9 , 0x0 , 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 61 | 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 62 | 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x0 , 0x5 , 0x0 , 0x4 , 63 | 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x6d, 0x61, 0x69, 0x6e, 0x0 , 0x0 , 0x0 , 0x0 , 64 | 0x5 , 0x0 , 0x6 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x67, 0x6c, 0x5f, 0x50, 0x65, 65 | 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x0 , 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 66 | 0x6 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x67, 0x6c, 0x5f, 67 | 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x0 , 0x6 , 0x0 , 0x7 , 0x0 , 68 | 0xb , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x67, 0x6c, 0x5f, 0x50, 0x6f, 69 | 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x0 , 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 70 | 0x7 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x67, 0x6c, 0x5f, 71 | 0x43, 0x6c, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x0 , 72 | 0x5 , 0x0 , 0x3 , 0x0 , 0xd , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x5 , 73 | 0x0 , 0x3 , 0x0 , 0x12, 0x0 , 0x0 , 0x0 , 0x70, 0x6f, 0x73, 0x0 , 0x5 , 0x0 , 74 | 0x4 , 0x0 , 0x1d, 0x0 , 0x0 , 0x0 , 0x6f, 0x75, 0x74, 0x55, 0x76, 0x0 , 0x0 , 75 | 0x0 , 0x5 , 0x0 , 0x4 , 0x0 , 0x1f, 0x0 , 0x0 , 0x0 , 0x69, 0x6e, 0x55, 0x76, 76 | 0x0 , 0x0 , 0x0 , 0x0 , 0x48, 0x0 , 0x5 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x0 , 77 | 0x0 , 0x0 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x48, 0x0 , 78 | 0x5 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0xb , 0x0 , 0x0 , 79 | 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x48, 0x0 , 0x5 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 80 | 0x2 , 0x0 , 0x0 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x47, 81 | 0x0 , 0x3 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x47, 0x0 , 82 | 0x4 , 0x0 , 0x12, 0x0 , 0x0 , 0x0 , 0x1e, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 83 | 0x0 , 0x47, 0x0 , 0x4 , 0x0 , 0x1d, 0x0 , 0x0 , 0x0 , 0x1e, 0x0 , 0x0 , 0x0 , 84 | 0x0 , 0x0 , 0x0 , 0x0 , 0x47, 0x0 , 0x4 , 0x0 , 0x1f, 0x0 , 0x0 , 0x0 , 0x1e, 85 | 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x13, 0x0 , 0x2 , 0x0 , 0x2 , 0x0 , 86 | 0x0 , 0x0 , 0x21, 0x0 , 0x3 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 0x0 , 87 | 0x0 , 0x16, 0x0 , 0x3 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x0 , 0x0 , 88 | 0x17, 0x0 , 0x4 , 0x0 , 0x7 , 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x4 , 89 | 0x0 , 0x0 , 0x0 , 0x15, 0x0 , 0x4 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 90 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2b, 0x0 , 0x4 , 0x0 , 0x8 , 0x0 , 0x0 , 91 | 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x1c, 0x0 , 0x4 , 0x0 , 92 | 0xa , 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 0x1e, 93 | 0x0 , 0x5 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x7 , 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 94 | 0x0 , 0x0 , 0xa , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x4 , 0x0 , 0xc , 0x0 , 0x0 , 95 | 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x3b, 0x0 , 0x4 , 0x0 , 96 | 0xc , 0x0 , 0x0 , 0x0 , 0xd , 0x0 , 0x0 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x15, 97 | 0x0 , 0x4 , 0x0 , 0xe , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 98 | 0x0 , 0x0 , 0x2b, 0x0 , 0x4 , 0x0 , 0xe , 0x0 , 0x0 , 0x0 , 0xf , 0x0 , 0x0 , 99 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x17, 0x0 , 0x4 , 0x0 , 0x10, 0x0 , 0x0 , 0x0 , 100 | 0x6 , 0x0 , 0x0 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x4 , 0x0 , 0x11, 101 | 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x10, 0x0 , 0x0 , 0x0 , 0x3b, 0x0 , 102 | 0x4 , 0x0 , 0x11, 0x0 , 0x0 , 0x0 , 0x12, 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 103 | 0x0 , 0x2b, 0x0 , 0x4 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x14, 0x0 , 0x0 , 0x0 , 104 | 0x0 , 0x0 , 0x80, 0x3f, 0x20, 0x0 , 0x4 , 0x0 , 0x19, 0x0 , 0x0 , 0x0 , 0x3 , 105 | 0x0 , 0x0 , 0x0 , 0x7 , 0x0 , 0x0 , 0x0 , 0x17, 0x0 , 0x4 , 0x0 , 0x1b, 0x0 , 106 | 0x0 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x4 , 107 | 0x0 , 0x1c, 0x0 , 0x0 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x1b, 0x0 , 0x0 , 0x0 , 108 | 0x3b, 0x0 , 0x4 , 0x0 , 0x1c, 0x0 , 0x0 , 0x0 , 0x1d, 0x0 , 0x0 , 0x0 , 0x3 , 109 | 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x4 , 0x0 , 0x1e, 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 110 | 0x0 , 0x0 , 0x1b, 0x0 , 0x0 , 0x0 , 0x3b, 0x0 , 0x4 , 0x0 , 0x1e, 0x0 , 0x0 , 111 | 0x0 , 0x1f, 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x36, 0x0 , 0x5 , 0x0 , 112 | 0x2 , 0x0 , 0x0 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3 , 113 | 0x0 , 0x0 , 0x0 , 0xf8, 0x0 , 0x2 , 0x0 , 0x5 , 0x0 , 0x0 , 0x0 , 0x3d, 0x0 , 114 | 0x4 , 0x0 , 0x10, 0x0 , 0x0 , 0x0 , 0x13, 0x0 , 0x0 , 0x0 , 0x12, 0x0 , 0x0 , 115 | 0x0 , 0x51, 0x0 , 0x5 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x15, 0x0 , 0x0 , 0x0 , 116 | 0x13, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x51, 0x0 , 0x5 , 0x0 , 0x6 , 117 | 0x0 , 0x0 , 0x0 , 0x16, 0x0 , 0x0 , 0x0 , 0x13, 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 118 | 0x0 , 0x0 , 0x51, 0x0 , 0x5 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x17, 0x0 , 0x0 , 119 | 0x0 , 0x13, 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x50, 0x0 , 0x7 , 0x0 , 120 | 0x7 , 0x0 , 0x0 , 0x0 , 0x18, 0x0 , 0x0 , 0x0 , 0x15, 0x0 , 0x0 , 0x0 , 0x16, 121 | 0x0 , 0x0 , 0x0 , 0x17, 0x0 , 0x0 , 0x0 , 0x14, 0x0 , 0x0 , 0x0 , 0x41, 0x0 , 122 | 0x5 , 0x0 , 0x19, 0x0 , 0x0 , 0x0 , 0x1a, 0x0 , 0x0 , 0x0 , 0xd , 0x0 , 0x0 , 123 | 0x0 , 0xf , 0x0 , 0x0 , 0x0 , 0x3e, 0x0 , 0x3 , 0x0 , 0x1a, 0x0 , 0x0 , 0x0 , 124 | 0x18, 0x0 , 0x0 , 0x0 , 0x3d, 0x0 , 0x4 , 0x0 , 0x1b, 0x0 , 0x0 , 0x0 , 0x20, 125 | 0x0 , 0x0 , 0x0 , 0x1f, 0x0 , 0x0 , 0x0 , 0x3e, 0x0 , 0x3 , 0x0 , 0x1d, 0x0 , 126 | 0x0 , 0x0 , 0x20, 0x0 , 0x0 , 0x0 , 0xfd, 0x0 , 0x1 , 0x0 , 0x38, 0x0 , 0x1 , 127 | 0x0 , 128 | }; 129 | const unsigned char TexturedFragmentShader [] = { 130 | 0x3 , 0x2 , 0x23, 0x7 , 0x0 , 0x0 , 0x1 , 0x0 , 0x1 , 0x0 , 0x8 , 0x0 , 0x19, 131 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x11, 0x0 , 0x2 , 0x0 , 0x1 , 0x0 , 132 | 0x0 , 0x0 , 0xb , 0x0 , 0x6 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x47, 0x4c, 0x53, 133 | 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x0 , 0x0 , 0x0 , 0x0 , 134 | 0xe , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0xf , 135 | 0x0 , 0x7 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x6d, 0x61, 136 | 0x69, 0x6e, 0x0 , 0x0 , 0x0 , 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 0x16, 0x0 , 0x0 , 137 | 0x0 , 0x10, 0x0 , 0x3 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x7 , 0x0 , 0x0 , 0x0 , 138 | 0x3 , 0x0 , 0x3 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x90, 0x1 , 0x0 , 0x0 , 0x4 , 139 | 0x0 , 0x9 , 0x0 , 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 140 | 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 141 | 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x0 , 0x0 , 0x4 , 0x0 , 0x9 , 0x0 , 142 | 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6e, 143 | 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 144 | 0x30, 0x70, 0x61, 0x63, 0x6b, 0x0 , 0x5 , 0x0 , 0x4 , 0x0 , 0x4 , 0x0 , 0x0 , 145 | 0x0 , 0x6d, 0x61, 0x69, 0x6e, 0x0 , 0x0 , 0x0 , 0x0 , 0x5 , 0x0 , 0x5 , 0x0 , 146 | 0x9 , 0x0 , 0x0 , 0x0 , 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x6f, 0x6c, 147 | 0x6f, 0x72, 0x0 , 0x5 , 0x0 , 0x6 , 0x0 , 0xc , 0x0 , 0x0 , 0x0 , 0x63, 0x6f, 148 | 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x0 , 0x0 , 0x0 , 149 | 0x0 , 0x5 , 0x0 , 0x6 , 0x0 , 0x10, 0x0 , 0x0 , 0x0 , 0x63, 0x6f, 0x6c, 0x6f, 150 | 0x72, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x0 , 0x0 , 0x0 , 0x0 , 0x5 , 151 | 0x0 , 0x3 , 0x0 , 0x16, 0x0 , 0x0 , 0x0 , 0x75, 0x76, 0x0 , 0x0 , 0x47, 0x0 , 152 | 0x4 , 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 0x1e, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 153 | 0x0 , 0x47, 0x0 , 0x4 , 0x0 , 0xc , 0x0 , 0x0 , 0x0 , 0x22, 0x0 , 0x0 , 0x0 , 154 | 0x0 , 0x0 , 0x0 , 0x0 , 0x47, 0x0 , 0x4 , 0x0 , 0xc , 0x0 , 0x0 , 0x0 , 0x21, 155 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x47, 0x0 , 0x4 , 0x0 , 0x10, 0x0 , 156 | 0x0 , 0x0 , 0x22, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x47, 0x0 , 0x4 , 157 | 0x0 , 0x10, 0x0 , 0x0 , 0x0 , 0x21, 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 158 | 0x47, 0x0 , 0x4 , 0x0 , 0x16, 0x0 , 0x0 , 0x0 , 0x1e, 0x0 , 0x0 , 0x0 , 0x0 , 159 | 0x0 , 0x0 , 0x0 , 0x13, 0x0 , 0x2 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x21, 0x0 , 160 | 0x3 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x16, 0x0 , 0x3 , 161 | 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x0 , 0x0 , 0x17, 0x0 , 0x4 , 0x0 , 162 | 0x7 , 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x4 , 0x0 , 0x0 , 0x0 , 0x20, 163 | 0x0 , 0x4 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x7 , 0x0 , 164 | 0x0 , 0x0 , 0x3b, 0x0 , 0x4 , 0x0 , 0x8 , 0x0 , 0x0 , 0x0 , 0x9 , 0x0 , 0x0 , 165 | 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0x19, 0x0 , 0x9 , 0x0 , 0xa , 0x0 , 0x0 , 0x0 , 166 | 0x6 , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 167 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 168 | 0x0 , 0x0 , 0x20, 0x0 , 0x4 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 169 | 0x0 , 0xa , 0x0 , 0x0 , 0x0 , 0x3b, 0x0 , 0x4 , 0x0 , 0xb , 0x0 , 0x0 , 0x0 , 170 | 0xc , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x1a, 0x0 , 0x2 , 0x0 , 0xe , 171 | 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 0x4 , 0x0 , 0xf , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 172 | 0x0 , 0x0 , 0xe , 0x0 , 0x0 , 0x0 , 0x3b, 0x0 , 0x4 , 0x0 , 0xf , 0x0 , 0x0 , 173 | 0x0 , 0x10, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x1b, 0x0 , 0x3 , 0x0 , 174 | 0x12, 0x0 , 0x0 , 0x0 , 0xa , 0x0 , 0x0 , 0x0 , 0x17, 0x0 , 0x4 , 0x0 , 0x14, 175 | 0x0 , 0x0 , 0x0 , 0x6 , 0x0 , 0x0 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x20, 0x0 , 176 | 0x4 , 0x0 , 0x15, 0x0 , 0x0 , 0x0 , 0x1 , 0x0 , 0x0 , 0x0 , 0x14, 0x0 , 0x0 , 177 | 0x0 , 0x3b, 0x0 , 0x4 , 0x0 , 0x15, 0x0 , 0x0 , 0x0 , 0x16, 0x0 , 0x0 , 0x0 , 178 | 0x1 , 0x0 , 0x0 , 0x0 , 0x36, 0x0 , 0x5 , 0x0 , 0x2 , 0x0 , 0x0 , 0x0 , 0x4 , 179 | 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3 , 0x0 , 0x0 , 0x0 , 0xf8, 0x0 , 180 | 0x2 , 0x0 , 0x5 , 0x0 , 0x0 , 0x0 , 0x3d, 0x0 , 0x4 , 0x0 , 0xa , 0x0 , 0x0 , 181 | 0x0 , 0xd , 0x0 , 0x0 , 0x0 , 0xc , 0x0 , 0x0 , 0x0 , 0x3d, 0x0 , 0x4 , 0x0 , 182 | 0xe , 0x0 , 0x0 , 0x0 , 0x11, 0x0 , 0x0 , 0x0 , 0x10, 0x0 , 0x0 , 0x0 , 0x56, 183 | 0x0 , 0x5 , 0x0 , 0x12, 0x0 , 0x0 , 0x0 , 0x13, 0x0 , 0x0 , 0x0 , 0xd , 0x0 , 184 | 0x0 , 0x0 , 0x11, 0x0 , 0x0 , 0x0 , 0x3d, 0x0 , 0x4 , 0x0 , 0x14, 0x0 , 0x0 , 185 | 0x0 , 0x17, 0x0 , 0x0 , 0x0 , 0x16, 0x0 , 0x0 , 0x0 , 0x57, 0x0 , 0x5 , 0x0 , 186 | 0x7 , 0x0 , 0x0 , 0x0 , 0x18, 0x0 , 0x0 , 0x0 , 0x13, 0x0 , 0x0 , 0x0 , 0x17, 187 | 0x0 , 0x0 , 0x0 , 0x3e, 0x0 , 0x3 , 0x0 , 0x9 , 0x0 , 0x0 , 0x0 , 0x18, 0x0 , 188 | 0x0 , 0x0 , 0xfd, 0x0 , 0x1 , 0x0 , 0x38, 0x0 , 0x1 , 0x0 , 189 | }; 190 | -------------------------------------------------------------------------------- /hellovulkan/src/Utility.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include "Utility.h" 24 | 25 | #include 26 | 27 | /////////////////////////////////////////////////////////////////////////////// 28 | std::vector ReadFile(const char* filename) 29 | { 30 | std::vector result; 31 | std::uint8_t buffer[4096]; 32 | 33 | auto handle = std::fopen(filename, "rb"); 34 | 35 | for (;;) 36 | { 37 | const auto bytesRead = std::fread(buffer, 1, sizeof(buffer), handle); 38 | 39 | result.insert(result.end(), buffer, buffer + bytesRead); 40 | 41 | if (bytesRead < sizeof(buffer)) 42 | { 43 | break; 44 | } 45 | } 46 | 47 | std::fclose(handle); 48 | 49 | return result; 50 | } 51 | -------------------------------------------------------------------------------- /hellovulkan/src/Utility.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #ifndef AMD_VULKAN_SAMPLE_UTILITY_H_ 24 | #define AMD_VULKAN_SAMPLE_UTILITY_H_ 25 | 26 | #include 27 | #include 28 | 29 | /////////////////////////////////////////////////////////////////////////////// 30 | template 31 | T RoundToNextMultiple(const T a, const T multiple) 32 | { 33 | return ((a + multiple - 1) / multiple) * multiple; 34 | } 35 | 36 | std::vector ReadFile(const char* filename); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /hellovulkan/src/VulkanQuad.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include "VulkanQuad.h" 24 | 25 | #include "Shaders.h" 26 | #include "Utility.h" 27 | #include "Window.h" 28 | 29 | #include 30 | 31 | namespace AMD { 32 | /////////////////////////////////////////////////////////////////////////////// 33 | void VulkanQuad::ShutdownImpl () 34 | { 35 | vkDestroyPipeline (device_, pipeline_, nullptr); 36 | vkDestroyPipelineLayout (device_, pipelineLayout_, nullptr); 37 | 38 | vkDestroyBuffer (device_, vertexBuffer_, nullptr); 39 | vkDestroyBuffer (device_, indexBuffer_, nullptr); 40 | vkFreeMemory (device_, deviceMemory_, nullptr); 41 | 42 | vkDestroyShaderModule (device_, vertexShader_, nullptr); 43 | vkDestroyShaderModule (device_, fragmentShader_, nullptr); 44 | 45 | VulkanSample::ShutdownImpl (); 46 | } 47 | 48 | /////////////////////////////////////////////////////////////////////////////// 49 | void VulkanQuad::RenderImpl (VkCommandBuffer commandBuffer) 50 | { 51 | VulkanSample::RenderImpl (commandBuffer); 52 | 53 | vkCmdBindPipeline (commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 54 | pipeline_); 55 | VkDeviceSize offsets [] = { 0 }; 56 | vkCmdBindIndexBuffer (commandBuffer, indexBuffer_, 0, VK_INDEX_TYPE_UINT32); 57 | vkCmdBindVertexBuffers (commandBuffer, 0, 1, &vertexBuffer_, offsets); 58 | vkCmdDrawIndexed (commandBuffer, 6, 1, 0, 0, 0); 59 | } 60 | 61 | /////////////////////////////////////////////////////////////////////////////// 62 | void VulkanQuad::InitializeImpl (VkCommandBuffer uploadCommandBuffer) 63 | { 64 | VulkanSample::InitializeImpl (uploadCommandBuffer); 65 | 66 | CreatePipelineStateObject (); 67 | CreateMeshBuffers (uploadCommandBuffer); 68 | } 69 | 70 | namespace { 71 | struct MemoryTypeInfo 72 | { 73 | bool deviceLocal = false; 74 | bool hostVisible = false; 75 | bool hostCoherent = false; 76 | bool hostCached = false; 77 | bool lazilyAllocated = false; 78 | 79 | struct Heap 80 | { 81 | uint64_t size = 0; 82 | bool deviceLocal = false; 83 | }; 84 | 85 | Heap heap; 86 | int index; 87 | }; 88 | 89 | /////////////////////////////////////////////////////////////////////////////// 90 | std::vector EnumerateHeaps (VkPhysicalDevice device) 91 | { 92 | VkPhysicalDeviceMemoryProperties memoryProperties = {}; 93 | vkGetPhysicalDeviceMemoryProperties (device, &memoryProperties); 94 | 95 | std::vector heaps; 96 | 97 | for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; ++i) 98 | { 99 | MemoryTypeInfo::Heap info; 100 | info.size = memoryProperties.memoryHeaps [i].size; 101 | info.deviceLocal = (memoryProperties.memoryHeaps [i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0; 102 | 103 | heaps.push_back (info); 104 | } 105 | 106 | std::vector result; 107 | 108 | for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) 109 | { 110 | MemoryTypeInfo typeInfo; 111 | 112 | typeInfo.deviceLocal = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0; 113 | typeInfo.hostVisible = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0; 114 | typeInfo.hostCoherent = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; 115 | typeInfo.hostCached = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0; 116 | typeInfo.lazilyAllocated = (memoryProperties.memoryTypes [i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0; 117 | 118 | typeInfo.heap = heaps [memoryProperties.memoryTypes [i].heapIndex]; 119 | 120 | typeInfo.index = static_cast (i); 121 | 122 | result.push_back (typeInfo); 123 | } 124 | 125 | return result; 126 | } 127 | 128 | /////////////////////////////////////////////////////////////////////////////// 129 | VkDeviceMemory AllocateMemory (const std::vector& memoryInfos, 130 | VkDevice device, const int size, bool* isHostCoherent = nullptr) 131 | { 132 | // We take the first HOST_VISIBLE memory 133 | for (auto& memoryInfo : memoryInfos) 134 | { 135 | if (memoryInfo.hostVisible) 136 | { 137 | VkMemoryAllocateInfo memoryAllocateInfo = {}; 138 | memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 139 | memoryAllocateInfo.memoryTypeIndex = memoryInfo.index; 140 | memoryAllocateInfo.allocationSize = size; 141 | 142 | VkDeviceMemory deviceMemory; 143 | vkAllocateMemory (device, &memoryAllocateInfo, nullptr, 144 | &deviceMemory); 145 | 146 | if (isHostCoherent) 147 | { 148 | *isHostCoherent = memoryInfo.hostCoherent; 149 | } 150 | 151 | return deviceMemory; 152 | } 153 | } 154 | 155 | return VK_NULL_HANDLE; 156 | } 157 | 158 | /////////////////////////////////////////////////////////////////////////////// 159 | VkBuffer AllocateBuffer (VkDevice device, const int size, 160 | const VkBufferUsageFlagBits bits) 161 | { 162 | VkBufferCreateInfo bufferCreateInfo = {}; 163 | bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 164 | bufferCreateInfo.size = static_cast (size); 165 | bufferCreateInfo.usage = bits; 166 | 167 | VkBuffer result; 168 | vkCreateBuffer (device, &bufferCreateInfo, nullptr, &result); 169 | return result; 170 | } 171 | 172 | /////////////////////////////////////////////////////////////////////////////// 173 | VkPipelineLayout CreatePipelineLayout (VkDevice device) 174 | { 175 | VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {}; 176 | pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 177 | 178 | VkPipelineLayout result; 179 | vkCreatePipelineLayout (device, &pipelineLayoutCreateInfo, nullptr, 180 | &result); 181 | 182 | return result; 183 | } 184 | 185 | /////////////////////////////////////////////////////////////////////////////// 186 | VkShaderModule LoadShader (VkDevice device, const void* shaderContents, 187 | const size_t size) 188 | { 189 | VkShaderModuleCreateInfo shaderModuleCreateInfo = {}; 190 | shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 191 | 192 | shaderModuleCreateInfo.pCode = static_cast (shaderContents); 193 | shaderModuleCreateInfo.codeSize = size; 194 | 195 | VkShaderModule result; 196 | vkCreateShaderModule (device, &shaderModuleCreateInfo, nullptr, &result); 197 | 198 | return result; 199 | } 200 | 201 | /////////////////////////////////////////////////////////////////////////////// 202 | VkPipeline CreatePipeline (VkDevice device, VkRenderPass renderPass, VkPipelineLayout layout, 203 | VkShaderModule vertexShader, VkShaderModule fragmentShader, 204 | VkExtent2D viewportSize) 205 | { 206 | VkVertexInputBindingDescription vertexInputBindingDescription; 207 | vertexInputBindingDescription.binding = 0; 208 | vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 209 | vertexInputBindingDescription.stride = sizeof (float) * 5; 210 | 211 | VkVertexInputAttributeDescription vertexInputAttributeDescription [2] = {}; 212 | vertexInputAttributeDescription [0].binding = vertexInputBindingDescription.binding; 213 | vertexInputAttributeDescription [0].format = VK_FORMAT_R32G32B32_SFLOAT; 214 | vertexInputAttributeDescription [0].location = 0; 215 | vertexInputAttributeDescription [0].offset = 0; 216 | 217 | vertexInputAttributeDescription [1].binding = vertexInputBindingDescription.binding; 218 | vertexInputAttributeDescription [1].format = VK_FORMAT_R32G32_SFLOAT; 219 | vertexInputAttributeDescription [1].location = 1; 220 | vertexInputAttributeDescription [1].offset = sizeof (float) * 3; 221 | 222 | VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = {}; 223 | pipelineVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 224 | pipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = std::extent::value; 225 | pipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescription; 226 | pipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = 1; 227 | pipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = &vertexInputBindingDescription; 228 | 229 | VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = {}; 230 | pipelineInputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 231 | pipelineInputAssemblyStateCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 232 | 233 | VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {}; 234 | pipelineViewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 235 | 236 | VkViewport viewport; 237 | viewport.height = static_cast (viewportSize.height); 238 | viewport.width = static_cast (viewportSize.width); 239 | viewport.x = 0; 240 | viewport.y = 0; 241 | viewport.minDepth = 0; 242 | viewport.maxDepth = 1; 243 | 244 | pipelineViewportStateCreateInfo.viewportCount = 1; 245 | pipelineViewportStateCreateInfo.pViewports = &viewport; 246 | 247 | VkRect2D rect; 248 | rect.extent = viewportSize; 249 | rect.offset.x = 0; 250 | rect.offset.y = 0; 251 | 252 | pipelineViewportStateCreateInfo.scissorCount = 1; 253 | pipelineViewportStateCreateInfo.pScissors = ▭ 254 | 255 | VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {}; 256 | pipelineColorBlendAttachmentState.colorWriteMask = 0xF; 257 | pipelineColorBlendAttachmentState.blendEnable = VK_FALSE; 258 | 259 | VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {}; 260 | pipelineColorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 261 | 262 | pipelineColorBlendStateCreateInfo.attachmentCount = 1; 263 | pipelineColorBlendStateCreateInfo.pAttachments = &pipelineColorBlendAttachmentState; 264 | 265 | VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = {}; 266 | pipelineRasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 267 | pipelineRasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL; 268 | pipelineRasterizationStateCreateInfo.cullMode = VK_CULL_MODE_NONE; 269 | pipelineRasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 270 | pipelineRasterizationStateCreateInfo.depthClampEnable = VK_FALSE; 271 | pipelineRasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE; 272 | pipelineRasterizationStateCreateInfo.depthBiasEnable = VK_FALSE; 273 | pipelineRasterizationStateCreateInfo.lineWidth = 1.0f; 274 | 275 | VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {}; 276 | pipelineDepthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 277 | pipelineDepthStencilStateCreateInfo.depthTestEnable = VK_FALSE; 278 | pipelineDepthStencilStateCreateInfo.depthWriteEnable = VK_FALSE; 279 | pipelineDepthStencilStateCreateInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS; 280 | pipelineDepthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE; 281 | pipelineDepthStencilStateCreateInfo.back.failOp = VK_STENCIL_OP_KEEP; 282 | pipelineDepthStencilStateCreateInfo.back.passOp = VK_STENCIL_OP_KEEP; 283 | pipelineDepthStencilStateCreateInfo.back.compareOp = VK_COMPARE_OP_ALWAYS; 284 | pipelineDepthStencilStateCreateInfo.stencilTestEnable = VK_FALSE; 285 | pipelineDepthStencilStateCreateInfo.front = pipelineDepthStencilStateCreateInfo.back; 286 | 287 | VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {}; 288 | pipelineMultisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 289 | pipelineMultisampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 290 | 291 | VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfos [2] = {}; 292 | pipelineShaderStageCreateInfos [0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 293 | pipelineShaderStageCreateInfos [0].module = vertexShader; 294 | pipelineShaderStageCreateInfos [0].pName = "main"; 295 | pipelineShaderStageCreateInfos [0].stage = VK_SHADER_STAGE_VERTEX_BIT; 296 | 297 | pipelineShaderStageCreateInfos [1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 298 | pipelineShaderStageCreateInfos [1].module = fragmentShader; 299 | pipelineShaderStageCreateInfos [1].pName = "main"; 300 | pipelineShaderStageCreateInfos [1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 301 | 302 | VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {}; 303 | graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 304 | 305 | graphicsPipelineCreateInfo.layout = layout; 306 | graphicsPipelineCreateInfo.pVertexInputState = &pipelineVertexInputStateCreateInfo; 307 | graphicsPipelineCreateInfo.pInputAssemblyState = &pipelineInputAssemblyStateCreateInfo; 308 | graphicsPipelineCreateInfo.renderPass = renderPass; 309 | graphicsPipelineCreateInfo.pViewportState = &pipelineViewportStateCreateInfo; 310 | graphicsPipelineCreateInfo.pColorBlendState = &pipelineColorBlendStateCreateInfo; 311 | graphicsPipelineCreateInfo.pRasterizationState = &pipelineRasterizationStateCreateInfo; 312 | graphicsPipelineCreateInfo.pDepthStencilState = &pipelineDepthStencilStateCreateInfo; 313 | graphicsPipelineCreateInfo.pMultisampleState = &pipelineMultisampleStateCreateInfo; 314 | graphicsPipelineCreateInfo.pStages = pipelineShaderStageCreateInfos; 315 | graphicsPipelineCreateInfo.stageCount = 2; 316 | 317 | VkPipeline pipeline; 318 | vkCreateGraphicsPipelines (device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, 319 | nullptr, &pipeline); 320 | 321 | return pipeline; 322 | } 323 | } 324 | 325 | /////////////////////////////////////////////////////////////////////////////// 326 | void VulkanQuad::CreateMeshBuffers (VkCommandBuffer /*uploadCommandBuffer*/) 327 | { 328 | struct Vertex 329 | { 330 | float position[3]; 331 | float uv[2]; 332 | }; 333 | 334 | static const Vertex vertices[4] = { 335 | // Upper Left 336 | { { -1.0f, 1.0f, 0 }, { 0, 0 } }, 337 | // Upper Right 338 | { { 1.0f, 1.0f, 0 }, { 1, 0 } }, 339 | // Bottom right 340 | { { 1.0f, -1.0f, 0 }, { 1, 1 } }, 341 | // Bottom left 342 | { { -1.0f, -1.0f, 0 }, { 0, 1 } } 343 | }; 344 | 345 | static const int indices[6] = { 346 | 0, 1, 2, 2, 3, 0 347 | }; 348 | 349 | auto memoryHeaps = EnumerateHeaps (physicalDevice_); 350 | indexBuffer_ = AllocateBuffer(device_, sizeof(indices), 351 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); 352 | vertexBuffer_ = AllocateBuffer (device_, sizeof (vertices), 353 | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 354 | VkMemoryRequirements vertexBufferMemoryRequirements = {}; 355 | vkGetBufferMemoryRequirements(device_, vertexBuffer_, 356 | &vertexBufferMemoryRequirements); 357 | VkMemoryRequirements indexBufferMemoryRequirements = {}; 358 | vkGetBufferMemoryRequirements(device_, indexBuffer_, 359 | &indexBufferMemoryRequirements); 360 | 361 | VkDeviceSize bufferSize = vertexBufferMemoryRequirements.size; 362 | // We want to place the index buffer behind the vertex buffer. Need to take 363 | // the alignment into account to find the next suitable location 364 | VkDeviceSize indexBufferOffset = RoundToNextMultiple(bufferSize, 365 | indexBufferMemoryRequirements.alignment); 366 | 367 | bufferSize = indexBufferOffset + indexBufferMemoryRequirements.size; 368 | bool memoryIsHostCoherent = false; 369 | deviceMemory_ = AllocateMemory(memoryHeaps, device_, 370 | static_cast(bufferSize), &memoryIsHostCoherent); 371 | 372 | vkBindBufferMemory (device_, vertexBuffer_, deviceMemory_, 0); 373 | vkBindBufferMemory (device_, indexBuffer_, deviceMemory_, 374 | indexBufferOffset); 375 | 376 | void* mapping = nullptr; 377 | vkMapMemory (device_, deviceMemory_, 0, VK_WHOLE_SIZE, 378 | 0, &mapping); 379 | ::memcpy (mapping, vertices, sizeof (vertices)); 380 | 381 | ::memcpy (static_cast (mapping) + indexBufferOffset, 382 | indices, sizeof (indices)); 383 | 384 | if (!memoryIsHostCoherent) 385 | { 386 | VkMappedMemoryRange mappedMemoryRange = {}; 387 | mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 388 | mappedMemoryRange.memory = deviceMemory_; 389 | mappedMemoryRange.offset = 0; 390 | mappedMemoryRange.size = VK_WHOLE_SIZE; 391 | 392 | vkFlushMappedMemoryRanges (device_, 1, &mappedMemoryRange); 393 | } 394 | 395 | vkUnmapMemory (device_, deviceMemory_); 396 | } 397 | 398 | /////////////////////////////////////////////////////////////////////////////// 399 | void VulkanQuad::CreatePipelineStateObject () 400 | { 401 | vertexShader_ = LoadShader (device_, BasicVertexShader, sizeof (BasicVertexShader)); 402 | fragmentShader_ = LoadShader (device_, BasicFragmentShader, sizeof (BasicFragmentShader)); 403 | 404 | pipelineLayout_ = CreatePipelineLayout (device_); 405 | VkExtent2D extent = { 406 | static_cast (window_->GetWidth ()), 407 | static_cast (window_->GetHeight ()) 408 | }; 409 | pipeline_ = CreatePipeline(device_, renderPass_, pipelineLayout_, 410 | vertexShader_, fragmentShader_, extent); 411 | } 412 | } 413 | -------------------------------------------------------------------------------- /hellovulkan/src/VulkanQuad.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #ifndef AMD_VULKAN_SAMPLE_QUAD_H_ 24 | #define AMD_VULKAN_SAMPLE_QUAD_H_ 25 | 26 | #include "VulkanSample.h" 27 | 28 | namespace AMD 29 | { 30 | class VulkanQuad : public VulkanSample 31 | { 32 | private: 33 | void CreatePipelineStateObject (); 34 | void CreateMeshBuffers (VkCommandBuffer uploadCommandList); 35 | void RenderImpl (VkCommandBuffer commandList) override; 36 | void InitializeImpl (VkCommandBuffer uploadCommandList) override; 37 | void ShutdownImpl () override; 38 | 39 | VkDeviceMemory deviceMemory_ = VK_NULL_HANDLE; 40 | VkBuffer vertexBuffer_ = VK_NULL_HANDLE; 41 | VkBuffer indexBuffer_ = VK_NULL_HANDLE; 42 | 43 | VkShaderModule vertexShader_ = VK_NULL_HANDLE; 44 | VkShaderModule fragmentShader_ = VK_NULL_HANDLE; 45 | 46 | VkPipeline pipeline_ = VK_NULL_HANDLE; 47 | VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE; 48 | }; 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /hellovulkan/src/VulkanSample.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include "VulkanSample.h" 24 | 25 | #include 26 | #include 27 | 28 | #include "Utility.h" 29 | #include "Window.h" 30 | 31 | #include 32 | 33 | #ifdef max 34 | #undef max 35 | #endif 36 | 37 | #ifdef min 38 | #undef min 39 | #endif 40 | 41 | #pragma warning( disable : 4100 ) // disable unreferenced formal parameter warnings 42 | 43 | namespace AMD 44 | { 45 | struct VulkanSample::ImportTable 46 | { 47 | #define GET_INSTANCE_ENTRYPOINT(i, w) w = reinterpret_cast(vkGetInstanceProcAddr(i, #w)) 48 | #define GET_DEVICE_ENTRYPOINT(i, w) w = reinterpret_cast(vkGetDeviceProcAddr(i, #w)) 49 | 50 | ImportTable() = default; 51 | 52 | ImportTable(VkInstance instance, VkDevice device) 53 | { 54 | #ifdef _DEBUG 55 | GET_INSTANCE_ENTRYPOINT(instance, vkCreateDebugReportCallbackEXT); 56 | GET_INSTANCE_ENTRYPOINT(instance, vkDebugReportMessageEXT); 57 | GET_INSTANCE_ENTRYPOINT(instance, vkDestroyDebugReportCallbackEXT); 58 | #endif 59 | } 60 | 61 | #undef GET_INSTANCE_ENTRYPOINT 62 | #undef GET_DEVICE_ENTRYPOINT 63 | 64 | #ifdef _DEBUG 65 | PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr; 66 | PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT = nullptr; 67 | PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr; 68 | #endif 69 | }; 70 | 71 | namespace 72 | { 73 | /////////////////////////////////////////////////////////////////////////////// 74 | VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback( 75 | VkDebugReportFlagsEXT /*flags*/, 76 | VkDebugReportObjectTypeEXT /*objectType*/, 77 | uint64_t /*object*/, 78 | size_t /*location*/, 79 | int32_t /*messageCode*/, 80 | const char* /*pLayerPrefix*/, 81 | const char* pMessage, 82 | void* /*pUserData*/) 83 | { 84 | OutputDebugStringA(pMessage); 85 | OutputDebugStringA("\n"); 86 | return VK_FALSE; 87 | } 88 | 89 | /////////////////////////////////////////////////////////////////////////////// 90 | std::vector GetDebugInstanceLayerNames() 91 | { 92 | uint32_t layerCount = 0; 93 | vkEnumerateInstanceLayerProperties(&layerCount, 94 | nullptr); 95 | 96 | std::vector instanceLayers{ layerCount }; 97 | vkEnumerateInstanceLayerProperties(&layerCount, 98 | instanceLayers.data()); 99 | 100 | std::vector result; 101 | for (const auto& p : instanceLayers) 102 | { 103 | if (strcmp(p.layerName, "VK_LAYER_LUNARG_standard_validation") == 0) 104 | { 105 | result.push_back("VK_LAYER_LUNARG_standard_validation"); 106 | } 107 | } 108 | 109 | return result; 110 | } 111 | 112 | /////////////////////////////////////////////////////////////////////////////// 113 | std::vector GetDebugInstanceExtensionNames() 114 | { 115 | uint32_t extensionCount = 0; 116 | vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, 117 | nullptr); 118 | 119 | std::vector instanceExtensions{ extensionCount }; 120 | vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, 121 | instanceExtensions.data()); 122 | 123 | std::vector result; 124 | for (const auto& e : instanceExtensions) 125 | { 126 | if (strcmp(e.extensionName, "VK_EXT_debug_report") == 0) 127 | { 128 | result.push_back("VK_EXT_debug_report"); 129 | } 130 | } 131 | 132 | return result; 133 | } 134 | 135 | /////////////////////////////////////////////////////////////////////////////// 136 | std::vector GetDebugDeviceLayerNames(VkPhysicalDevice device) 137 | { 138 | uint32_t layerCount = 0; 139 | vkEnumerateDeviceLayerProperties(device, &layerCount, nullptr); 140 | 141 | std::vector deviceLayers{ layerCount }; 142 | vkEnumerateDeviceLayerProperties(device, &layerCount, deviceLayers.data()); 143 | 144 | std::vector result; 145 | for (const auto& p : deviceLayers) 146 | { 147 | if (strcmp(p.layerName, "VK_LAYER_LUNARG_standard_validation") == 0) 148 | { 149 | result.push_back("VK_LAYER_LUNARG_standard_validation"); 150 | } 151 | } 152 | 153 | return result; 154 | } 155 | 156 | /////////////////////////////////////////////////////////////////////////////// 157 | void FindPhysicalDeviceWithGraphicsQueue(const std::vector& physicalDevices, 158 | VkPhysicalDevice* outputDevice, int* outputGraphicsQueueIndex) 159 | { 160 | for (auto physicalDevice : physicalDevices) 161 | { 162 | uint32_t queueFamilyPropertyCount = 0; 163 | 164 | vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, 165 | &queueFamilyPropertyCount, nullptr); 166 | 167 | std::vector queueFamilyProperties{ queueFamilyPropertyCount }; 168 | vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, 169 | &queueFamilyPropertyCount, queueFamilyProperties.data()); 170 | 171 | int i = 0; 172 | for (const auto& queueFamilyProperty : queueFamilyProperties) 173 | { 174 | if (queueFamilyProperty.queueFlags & VK_QUEUE_GRAPHICS_BIT) 175 | { 176 | if (outputDevice) 177 | { 178 | *outputDevice = physicalDevice; 179 | } 180 | 181 | if (outputGraphicsQueueIndex) 182 | { 183 | *outputGraphicsQueueIndex = i; 184 | } 185 | 186 | return; 187 | } 188 | 189 | ++i; 190 | } 191 | } 192 | } 193 | 194 | /////////////////////////////////////////////////////////////////////////////// 195 | VkInstance CreateInstance() 196 | { 197 | VkInstanceCreateInfo instanceCreateInfo = {}; 198 | instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 199 | 200 | std::vector instanceExtensions = 201 | { 202 | "VK_KHR_surface", "VK_KHR_win32_surface" 203 | }; 204 | 205 | #ifdef _DEBUG 206 | auto debugInstanceExtensionNames = GetDebugInstanceExtensionNames(); 207 | instanceExtensions.insert(instanceExtensions.end(), 208 | debugInstanceExtensionNames.begin(), debugInstanceExtensionNames.end()); 209 | #endif 210 | 211 | instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); 212 | instanceCreateInfo.enabledExtensionCount = static_cast (instanceExtensions.size()); 213 | 214 | std::vector instanceLayers; 215 | 216 | #ifdef _DEBUG 217 | auto debugInstanceLayerNames = GetDebugInstanceLayerNames(); 218 | instanceLayers.insert(instanceLayers.end(), 219 | debugInstanceLayerNames.begin(), debugInstanceLayerNames.end()); 220 | #endif 221 | 222 | instanceCreateInfo.ppEnabledLayerNames = instanceLayers.data(); 223 | instanceCreateInfo.enabledLayerCount = static_cast (instanceLayers.size()); 224 | 225 | VkApplicationInfo applicationInfo = {}; 226 | applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 227 | applicationInfo.apiVersion = VK_API_VERSION_1_0; 228 | applicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); 229 | applicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); 230 | applicationInfo.pApplicationName = "AMD Vulkan Sample application"; 231 | applicationInfo.pEngineName = "AMD Vulkan Sample Engine"; 232 | 233 | instanceCreateInfo.pApplicationInfo = &applicationInfo; 234 | 235 | VkInstance instance = VK_NULL_HANDLE; 236 | vkCreateInstance(&instanceCreateInfo, nullptr, &instance); 237 | 238 | return instance; 239 | } 240 | 241 | /////////////////////////////////////////////////////////////////////////////// 242 | void CreateDeviceAndQueue(VkInstance instance, VkDevice* outputDevice, 243 | VkQueue* outputQueue, int* outputQueueIndex, 244 | VkPhysicalDevice* outputPhysicalDevice) 245 | { 246 | uint32_t physicalDeviceCount = 0; 247 | vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr); 248 | 249 | std::vector devices{ physicalDeviceCount }; 250 | vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, 251 | devices.data()); 252 | 253 | VkPhysicalDevice physicalDevice = nullptr; 254 | int graphicsQueueIndex = -1; 255 | 256 | FindPhysicalDeviceWithGraphicsQueue(devices, &physicalDevice, &graphicsQueueIndex); 257 | 258 | assert(physicalDevice); 259 | 260 | VkDeviceQueueCreateInfo deviceQueueCreateInfo = {}; 261 | deviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 262 | deviceQueueCreateInfo.queueCount = 1; 263 | deviceQueueCreateInfo.queueFamilyIndex = graphicsQueueIndex; 264 | 265 | static const float queuePriorities[] = { 1.0f }; 266 | deviceQueueCreateInfo.pQueuePriorities = queuePriorities; 267 | 268 | VkDeviceCreateInfo deviceCreateInfo = {}; 269 | deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 270 | deviceCreateInfo.queueCreateInfoCount = 1; 271 | deviceCreateInfo.pQueueCreateInfos = &deviceQueueCreateInfo; 272 | 273 | std::vector deviceLayers; 274 | 275 | #ifdef _DEBUG 276 | auto debugDeviceLayerNames = GetDebugDeviceLayerNames(physicalDevice); 277 | deviceLayers.insert(deviceLayers.end(), 278 | debugDeviceLayerNames.begin(), debugDeviceLayerNames.end()); 279 | #endif 280 | 281 | deviceCreateInfo.ppEnabledLayerNames = deviceLayers.data(); 282 | deviceCreateInfo.enabledLayerCount = static_cast (deviceLayers.size()); 283 | 284 | // Our SPIR-V requests this, so we need to enable it here 285 | VkPhysicalDeviceFeatures enabledFeatures = {}; 286 | enabledFeatures.shaderClipDistance = true; 287 | 288 | deviceCreateInfo.pEnabledFeatures = &enabledFeatures; 289 | 290 | std::vector deviceExtensions = 291 | { 292 | "VK_KHR_swapchain" 293 | }; 294 | 295 | deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data(); 296 | deviceCreateInfo.enabledExtensionCount = static_cast (deviceExtensions.size()); 297 | 298 | VkDevice device = nullptr; 299 | vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device); 300 | assert(device); 301 | 302 | VkQueue queue = nullptr; 303 | vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue); 304 | assert(queue); 305 | 306 | if (outputQueue) 307 | { 308 | *outputQueue = queue; 309 | } 310 | 311 | if (outputDevice) 312 | { 313 | *outputDevice = device; 314 | } 315 | 316 | if (outputQueueIndex) 317 | { 318 | *outputQueueIndex = graphicsQueueIndex; 319 | } 320 | 321 | if (outputPhysicalDevice) 322 | { 323 | *outputPhysicalDevice = physicalDevice; 324 | } 325 | } 326 | 327 | struct SwapchainFormatColorSpace 328 | { 329 | VkFormat format; 330 | VkColorSpaceKHR colorSpace; 331 | }; 332 | 333 | /////////////////////////////////////////////////////////////////////////////// 334 | SwapchainFormatColorSpace GetSwapchainFormatAndColorspace(VkPhysicalDevice physicalDevice, 335 | VkSurfaceKHR surface, VulkanSample::ImportTable* importTable) 336 | { 337 | uint32_t surfaceFormatCount = 0; 338 | vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, 339 | surface, &surfaceFormatCount, nullptr); 340 | 341 | std::vector surfaceFormats{ surfaceFormatCount }; 342 | vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, 343 | surface, &surfaceFormatCount, surfaceFormats.data()); 344 | 345 | SwapchainFormatColorSpace result; 346 | 347 | if (surfaceFormatCount == 1 && surfaceFormats.front().format == VK_FORMAT_UNDEFINED) 348 | { 349 | result.format = VK_FORMAT_R8G8B8A8_UNORM; 350 | } 351 | else 352 | { 353 | result.format = surfaceFormats.front().format; 354 | } 355 | 356 | result.colorSpace = surfaceFormats.front().colorSpace; 357 | 358 | return result; 359 | } 360 | 361 | /////////////////////////////////////////////////////////////////////////////// 362 | VkRenderPass CreateRenderPass(VkDevice device, VkFormat swapchainFormat) 363 | { 364 | VkAttachmentDescription attachmentDescription = {}; 365 | attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; 366 | attachmentDescription.format = swapchainFormat; 367 | attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 368 | attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 369 | attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 370 | attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 371 | attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 372 | attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 373 | 374 | VkAttachmentReference attachmentReference = {}; 375 | attachmentReference.attachment = 0; 376 | attachmentReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 377 | 378 | VkSubpassDescription subpassDescription = {}; 379 | subpassDescription.inputAttachmentCount = 0; 380 | subpassDescription.pColorAttachments = &attachmentReference; 381 | subpassDescription.colorAttachmentCount = 1; 382 | subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 383 | 384 | VkRenderPassCreateInfo renderPassCreateInfo = {}; 385 | renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 386 | renderPassCreateInfo.attachmentCount = 1; 387 | renderPassCreateInfo.subpassCount = 1; 388 | renderPassCreateInfo.pSubpasses = &subpassDescription; 389 | renderPassCreateInfo.pAttachments = &attachmentDescription; 390 | 391 | VkRenderPass result = nullptr; 392 | vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, 393 | &result); 394 | 395 | return result; 396 | } 397 | 398 | /////////////////////////////////////////////////////////////////////////////// 399 | void CreateFramebuffers(VkDevice device, VkRenderPass renderPass, 400 | const int width, const int height, 401 | const int count, const VkImageView* imageViews, VkFramebuffer* framebuffers) 402 | { 403 | for (int i = 0; i < count; ++i) 404 | { 405 | VkFramebufferCreateInfo framebufferCreateInfo = {}; 406 | framebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 407 | framebufferCreateInfo.attachmentCount = 1; 408 | framebufferCreateInfo.pAttachments = &imageViews[i]; 409 | framebufferCreateInfo.height = height; 410 | framebufferCreateInfo.width = width; 411 | framebufferCreateInfo.layers = 1; 412 | framebufferCreateInfo.renderPass = renderPass; 413 | 414 | vkCreateFramebuffer(device, &framebufferCreateInfo, nullptr, 415 | &framebuffers[i]); 416 | } 417 | } 418 | 419 | /////////////////////////////////////////////////////////////////////////////// 420 | void CreateSwapchainImageViews(VkDevice device, VkFormat format, 421 | const int count, const VkImage* images, VkImageView* imageViews) 422 | { 423 | for (int i = 0; i < count; ++i) 424 | { 425 | VkImageViewCreateInfo imageViewCreateInfo = {}; 426 | imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 427 | imageViewCreateInfo.image = images[i]; 428 | imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; 429 | imageViewCreateInfo.format = format; 430 | imageViewCreateInfo.subresourceRange.levelCount = 1; 431 | imageViewCreateInfo.subresourceRange.layerCount = 1; 432 | imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 433 | 434 | vkCreateImageView(device, &imageViewCreateInfo, nullptr, 435 | &imageViews[i]); 436 | } 437 | } 438 | 439 | /////////////////////////////////////////////////////////////////////////////// 440 | VkSwapchainKHR CreateSwapchain(VkPhysicalDevice physicalDevice, VkDevice device, 441 | VkSurfaceKHR surface, const int surfaceWidth, const int surfaceHeight, 442 | const int backbufferCount, VulkanSample::ImportTable* importTable, 443 | VkFormat* swapchainFormat) 444 | { 445 | VkSurfaceCapabilitiesKHR surfaceCapabilities; 446 | vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, 447 | surface, &surfaceCapabilities); 448 | 449 | uint32_t presentModeCount; 450 | vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, 451 | surface, &presentModeCount, nullptr); 452 | 453 | std::vector presentModes{ presentModeCount }; 454 | 455 | vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, 456 | surface, &presentModeCount, presentModes.data()); 457 | 458 | VkExtent2D swapChainSize = {}; 459 | swapChainSize = surfaceCapabilities.currentExtent; 460 | assert(static_cast (swapChainSize.width) == surfaceWidth); 461 | assert(static_cast (swapChainSize.height) == surfaceHeight); 462 | 463 | uint32_t swapChainImageCount = backbufferCount; 464 | assert(swapChainImageCount >= surfaceCapabilities.minImageCount); 465 | 466 | // 0 indicates unlimited number of images 467 | if (surfaceCapabilities.maxImageCount != 0) 468 | { 469 | assert(swapChainImageCount < surfaceCapabilities.maxImageCount); 470 | } 471 | 472 | VkSurfaceTransformFlagBitsKHR surfaceTransformFlags; 473 | 474 | if (surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) 475 | { 476 | surfaceTransformFlags = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 477 | } 478 | else 479 | { 480 | surfaceTransformFlags = surfaceCapabilities.currentTransform; 481 | } 482 | 483 | auto swapchainFormatColorSpace = GetSwapchainFormatAndColorspace(physicalDevice, surface, 484 | importTable); 485 | 486 | VkSwapchainCreateInfoKHR swapchainCreateInfo = {}; 487 | swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 488 | swapchainCreateInfo.surface = surface; 489 | swapchainCreateInfo.minImageCount = swapChainImageCount; 490 | swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 491 | swapchainCreateInfo.preTransform = surfaceTransformFlags; 492 | swapchainCreateInfo.imageColorSpace = swapchainFormatColorSpace.colorSpace; 493 | swapchainCreateInfo.imageFormat = swapchainFormatColorSpace.format; 494 | swapchainCreateInfo.pQueueFamilyIndices = nullptr; 495 | swapchainCreateInfo.queueFamilyIndexCount = 0; 496 | swapchainCreateInfo.clipped = VK_TRUE; 497 | swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE; 498 | swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 499 | swapchainCreateInfo.imageExtent = swapChainSize; 500 | swapchainCreateInfo.imageArrayLayers = 1; 501 | swapchainCreateInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; 502 | 503 | VkSwapchainKHR swapchain; 504 | vkCreateSwapchainKHR(device, &swapchainCreateInfo, 505 | nullptr, &swapchain); 506 | 507 | if (swapchainFormat) 508 | { 509 | *swapchainFormat = swapchainFormatColorSpace.format; 510 | } 511 | 512 | return swapchain; 513 | } 514 | 515 | /////////////////////////////////////////////////////////////////////////////// 516 | VkSurfaceKHR CreateSurface(VkInstance instance, HWND hwnd) 517 | { 518 | VkWin32SurfaceCreateInfoKHR win32surfaceCreateInfo = {}; 519 | win32surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; 520 | win32surfaceCreateInfo.hwnd = hwnd; 521 | win32surfaceCreateInfo.hinstance = ::GetModuleHandle(nullptr); 522 | 523 | VkSurfaceKHR surface = nullptr; 524 | vkCreateWin32SurfaceKHR(instance, &win32surfaceCreateInfo, nullptr, 525 | &surface); 526 | 527 | return surface; 528 | } 529 | 530 | #ifdef _DEBUG 531 | /////////////////////////////////////////////////////////////////////////////// 532 | VkDebugReportCallbackEXT SetupDebugCallback(VkInstance instance, VulkanSample::ImportTable* importTable) 533 | { 534 | if (importTable->vkCreateDebugReportCallbackEXT) 535 | { 536 | VkDebugReportCallbackCreateInfoEXT callbackCreateInfo = {}; 537 | callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 538 | callbackCreateInfo.flags = 539 | VK_DEBUG_REPORT_ERROR_BIT_EXT | 540 | VK_DEBUG_REPORT_WARNING_BIT_EXT | 541 | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 542 | callbackCreateInfo.pfnCallback = &DebugReportCallback; 543 | 544 | VkDebugReportCallbackEXT callback; 545 | importTable->vkCreateDebugReportCallbackEXT(instance, &callbackCreateInfo, nullptr, &callback); 546 | return callback; 547 | } 548 | else 549 | { 550 | return VK_NULL_HANDLE; 551 | } 552 | } 553 | 554 | /////////////////////////////////////////////////////////////////////////////// 555 | void CleanupDebugCallback(VkInstance instance, VkDebugReportCallbackEXT callback, 556 | VulkanSample::ImportTable* importTable) 557 | { 558 | if (importTable->vkDestroyDebugReportCallbackEXT) 559 | { 560 | importTable->vkDestroyDebugReportCallbackEXT(instance, callback, nullptr); 561 | } 562 | } 563 | #endif 564 | 565 | } // namespace 566 | 567 | /////////////////////////////////////////////////////////////////////////////// 568 | VulkanSample::VulkanSample() 569 | { 570 | instance_ = CreateInstance(); 571 | if (instance_ == VK_NULL_HANDLE) 572 | { 573 | // just bail out if the user does not have a compatible Vulkan driver 574 | return; 575 | } 576 | 577 | VkPhysicalDevice physicalDevice; 578 | CreateDeviceAndQueue(instance_, &device_, &queue_, &queueFamilyIndex_, 579 | &physicalDevice); 580 | physicalDevice_ = physicalDevice; 581 | 582 | importTable_.reset(new ImportTable{ instance_, device_ }); 583 | 584 | #ifdef _DEBUG 585 | debugCallback_ = SetupDebugCallback(instance_, importTable_.get()); 586 | #endif 587 | 588 | window_.reset(new Window{ "Hello Vulkan", 1280, 720 }); 589 | 590 | surface_ = CreateSurface(instance_, window_->GetHWND()); 591 | 592 | VkBool32 presentSupported; 593 | vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, 594 | 0, surface_, &presentSupported); 595 | assert(presentSupported); 596 | 597 | VkFormat swapchainFormat = VK_FORMAT_UNDEFINED; 598 | swapchain_ = CreateSwapchain(physicalDevice, device_, surface_, 599 | window_->GetWidth(), window_->GetHeight(), QUEUE_SLOT_COUNT, 600 | importTable_.get(), &swapchainFormat); 601 | 602 | assert(swapchain_); 603 | 604 | uint32_t swapchainImageCount = 0; 605 | vkGetSwapchainImagesKHR(device_, swapchain_, 606 | &swapchainImageCount, nullptr); 607 | assert(static_cast (swapchainImageCount) == QUEUE_SLOT_COUNT); 608 | 609 | vkGetSwapchainImagesKHR(device_, swapchain_, 610 | &swapchainImageCount, swapchainImages_); 611 | 612 | renderPass_ = CreateRenderPass(device_, swapchainFormat); 613 | 614 | CreateSwapchainImageViews(device_, swapchainFormat, 615 | QUEUE_SLOT_COUNT, swapchainImages_, swapChainImageViews_); 616 | CreateFramebuffers(device_, renderPass_, window_->GetWidth(), window_->GetHeight(), 617 | QUEUE_SLOT_COUNT, swapChainImageViews_, framebuffer_); 618 | 619 | VkCommandPoolCreateInfo commandPoolCreateInfo = {}; 620 | commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 621 | commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex_; 622 | commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; 623 | 624 | vkCreateCommandPool(device_, &commandPoolCreateInfo, nullptr, 625 | &commandPool_); 626 | 627 | VkCommandBufferAllocateInfo commandBufferAllocateInfo = {}; 628 | commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 629 | commandBufferAllocateInfo.commandBufferCount = QUEUE_SLOT_COUNT + 1; 630 | commandBufferAllocateInfo.commandPool = commandPool_; 631 | commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 632 | 633 | VkCommandBuffer commandBuffers[QUEUE_SLOT_COUNT + 1]; 634 | 635 | vkAllocateCommandBuffers(device_, &commandBufferAllocateInfo, 636 | commandBuffers); 637 | 638 | for (int i = 0; i < QUEUE_SLOT_COUNT; ++i) 639 | { 640 | commandBuffers_[i] = commandBuffers[i]; 641 | } 642 | 643 | setupCommandBuffer_ = commandBuffers[QUEUE_SLOT_COUNT]; 644 | 645 | for (int i = 0; i < QUEUE_SLOT_COUNT; ++i) 646 | { 647 | VkFenceCreateInfo fenceCreateInfo = {}; 648 | fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 649 | // We need this so we can wait for them on the first try 650 | fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; 651 | 652 | vkCreateFence(device_, &fenceCreateInfo, nullptr, &frameFences_[i]); 653 | } 654 | } 655 | 656 | /////////////////////////////////////////////////////////////////////////////// 657 | VulkanSample::~VulkanSample() 658 | { 659 | } 660 | 661 | /////////////////////////////////////////////////////////////////////////////// 662 | void VulkanSample::ShutdownImpl() 663 | { 664 | for (int i = 0; i < QUEUE_SLOT_COUNT; ++i) 665 | { 666 | vkDestroyFence(device_, frameFences_[i], nullptr); 667 | } 668 | 669 | vkDestroyRenderPass(device_, renderPass_, nullptr); 670 | 671 | for (int i = 0; i < QUEUE_SLOT_COUNT; ++i) 672 | { 673 | vkDestroyFramebuffer(device_, framebuffer_[i], nullptr); 674 | vkDestroyImageView(device_, swapChainImageViews_[i], nullptr); 675 | } 676 | 677 | vkDestroyCommandPool(device_, commandPool_, nullptr); 678 | 679 | vkDestroySwapchainKHR(device_, swapchain_, nullptr); 680 | vkDestroySurfaceKHR(instance_, surface_, nullptr); 681 | 682 | #ifdef _DEBUG 683 | CleanupDebugCallback(instance_, debugCallback_, importTable_.get()); 684 | #endif 685 | 686 | vkDestroyDevice(device_, nullptr); 687 | vkDestroyInstance(instance_, nullptr); 688 | } 689 | 690 | /////////////////////////////////////////////////////////////////////////////// 691 | void VulkanSample::Run(const int frameCount) 692 | { 693 | if (IsInitialized() == false) 694 | { 695 | // just bail out if the user does not have a compatible Vulkan driver 696 | return; 697 | } 698 | 699 | vkResetFences(device_, 1, &frameFences_[0]); 700 | { 701 | VkCommandBufferBeginInfo beginInfo = {}; 702 | beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 703 | 704 | vkBeginCommandBuffer(setupCommandBuffer_, &beginInfo); 705 | 706 | InitializeImpl(setupCommandBuffer_); 707 | 708 | vkEndCommandBuffer(setupCommandBuffer_); 709 | 710 | VkSubmitInfo submitInfo = {}; 711 | submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 712 | submitInfo.commandBufferCount = 1; 713 | submitInfo.pCommandBuffers = &setupCommandBuffer_; 714 | vkQueueSubmit(queue_, 1, &submitInfo, frameFences_[0]); 715 | } 716 | 717 | vkWaitForFences(device_, 1, &frameFences_[0], VK_TRUE, UINT64_MAX); 718 | 719 | VkSemaphoreCreateInfo semaphoreCreateInfo = {}; 720 | semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 721 | 722 | VkSemaphore imageAcquiredSemaphore; 723 | vkCreateSemaphore(device_, &semaphoreCreateInfo, 724 | nullptr, &imageAcquiredSemaphore); 725 | 726 | VkSemaphore renderingCompleteSemaphore; 727 | vkCreateSemaphore(device_, &semaphoreCreateInfo, 728 | nullptr, &renderingCompleteSemaphore); 729 | 730 | for (int i = 0; i < frameCount; ++i) 731 | { 732 | vkAcquireNextImageKHR( 733 | device_, swapchain_, UINT64_MAX, imageAcquiredSemaphore, 734 | VK_NULL_HANDLE, ¤tBackBuffer_); 735 | 736 | vkWaitForFences(device_, 1, &frameFences_[currentBackBuffer_], VK_TRUE, 737 | UINT64_MAX); 738 | vkResetFences(device_, 1, &frameFences_[currentBackBuffer_]); 739 | 740 | VkCommandBufferBeginInfo beginInfo = {}; 741 | beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 742 | 743 | vkBeginCommandBuffer(commandBuffers_[currentBackBuffer_], &beginInfo); 744 | 745 | VkRenderPassBeginInfo renderPassBeginInfo = {}; 746 | renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 747 | renderPassBeginInfo.framebuffer = framebuffer_[currentBackBuffer_]; 748 | renderPassBeginInfo.renderArea.extent.width = window_->GetWidth(); 749 | renderPassBeginInfo.renderArea.extent.height = window_->GetHeight(); 750 | renderPassBeginInfo.renderPass = renderPass_; 751 | 752 | VkClearValue clearValue = {}; 753 | 754 | clearValue.color.float32[0] = 0.042f; 755 | clearValue.color.float32[1] = 0.042f; 756 | clearValue.color.float32[2] = 0.042f; 757 | clearValue.color.float32[3] = 1.0f; 758 | 759 | renderPassBeginInfo.pClearValues = &clearValue; 760 | renderPassBeginInfo.clearValueCount = 1; 761 | 762 | vkCmdBeginRenderPass(commandBuffers_[currentBackBuffer_], 763 | &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 764 | 765 | RenderImpl(commandBuffers_[currentBackBuffer_]); 766 | 767 | vkCmdEndRenderPass(commandBuffers_[currentBackBuffer_]); 768 | vkEndCommandBuffer(commandBuffers_[currentBackBuffer_]); 769 | 770 | // Submit rendering work to the graphics queue 771 | const VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 772 | VkSubmitInfo submitInfo = {}; 773 | submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 774 | submitInfo.waitSemaphoreCount = 1; 775 | submitInfo.pWaitSemaphores = &imageAcquiredSemaphore; 776 | submitInfo.pWaitDstStageMask = &waitDstStageMask; 777 | submitInfo.commandBufferCount = 1; 778 | submitInfo.pCommandBuffers = &commandBuffers_[currentBackBuffer_]; 779 | submitInfo.signalSemaphoreCount = 1; 780 | submitInfo.pSignalSemaphores = &renderingCompleteSemaphore; 781 | vkQueueSubmit(queue_, 1, &submitInfo, VK_NULL_HANDLE); 782 | 783 | // Submit present operation to present queue 784 | VkPresentInfoKHR presentInfo = {}; 785 | presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 786 | presentInfo.waitSemaphoreCount = 1; 787 | presentInfo.pWaitSemaphores = &renderingCompleteSemaphore; 788 | presentInfo.swapchainCount = 1; 789 | presentInfo.pSwapchains = &swapchain_; 790 | presentInfo.pImageIndices = ¤tBackBuffer_; 791 | vkQueuePresentKHR(queue_, &presentInfo); 792 | 793 | vkQueueSubmit(queue_, 0, nullptr, frameFences_[currentBackBuffer_]); 794 | }; 795 | 796 | // Wait for all rendering to finish 797 | vkWaitForFences(device_, 3, frameFences_, VK_TRUE, UINT64_MAX); 798 | 799 | vkDestroySemaphore(device_, imageAcquiredSemaphore, nullptr); 800 | vkDestroySemaphore(device_, renderingCompleteSemaphore, nullptr); 801 | 802 | ShutdownImpl(); 803 | } 804 | 805 | /////////////////////////////////////////////////////////////////////////////// 806 | void VulkanSample::InitializeImpl(VkCommandBuffer /*commandBuffer*/) 807 | { 808 | } 809 | 810 | /////////////////////////////////////////////////////////////////////////////// 811 | void VulkanSample::RenderImpl(VkCommandBuffer /*commandBuffer*/) 812 | { 813 | } 814 | 815 | } // namespace AMD 816 | -------------------------------------------------------------------------------- /hellovulkan/src/VulkanSample.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #ifndef AMD_VULKAN_SAMPLE_H_ 24 | #define AMD_VULKAN_SAMPLE_H_ 25 | 26 | #define VK_USE_PLATFORM_WIN32_KHR 27 | #include 28 | #include 29 | 30 | namespace AMD 31 | { 32 | class Window; 33 | 34 | /////////////////////////////////////////////////////////////////////////////// 35 | class VulkanSample 36 | { 37 | public: 38 | VulkanSample(const VulkanSample&) = delete; 39 | VulkanSample& operator= (const VulkanSample&) = delete; 40 | 41 | VulkanSample(); 42 | virtual ~VulkanSample(); 43 | 44 | bool IsInitialized() { return (instance_ != VK_NULL_HANDLE && device_ != VK_NULL_HANDLE); } 45 | void Run(const int frameCount); 46 | struct ImportTable; 47 | 48 | protected: 49 | int GetQueueSlot() const 50 | { 51 | return currentBackBuffer_; 52 | } 53 | 54 | static const int QUEUE_SLOT_COUNT = 3; 55 | 56 | static int GetQueueSlotCount() 57 | { 58 | return QUEUE_SLOT_COUNT; 59 | } 60 | 61 | VkViewport viewport_; 62 | 63 | VkSwapchainKHR swapchain_ = VK_NULL_HANDLE; 64 | VkInstance instance_ = VK_NULL_HANDLE; 65 | VkDevice device_ = VK_NULL_HANDLE; 66 | VkPhysicalDevice physicalDevice_ = VK_NULL_HANDLE; 67 | VkQueue queue_ = VK_NULL_HANDLE; 68 | 69 | VkSurfaceKHR surface_ = VK_NULL_HANDLE; 70 | 71 | std::unique_ptr importTable_; 72 | 73 | VkFence frameFences_[QUEUE_SLOT_COUNT]; 74 | VkImage swapchainImages_[QUEUE_SLOT_COUNT]; 75 | VkImageView swapChainImageViews_[QUEUE_SLOT_COUNT]; 76 | VkFramebuffer framebuffer_[QUEUE_SLOT_COUNT]; 77 | 78 | VkRenderPass renderPass_ = VK_NULL_HANDLE; 79 | 80 | int queueFamilyIndex_ = -1; 81 | 82 | std::unique_ptr window_; 83 | 84 | virtual void InitializeImpl(VkCommandBuffer commandBuffer); 85 | virtual void RenderImpl(VkCommandBuffer commandBuffer); 86 | virtual void ShutdownImpl(); 87 | 88 | private: 89 | VkCommandPool commandPool_; 90 | VkCommandBuffer commandBuffers_[QUEUE_SLOT_COUNT]; 91 | VkCommandBuffer setupCommandBuffer_; 92 | uint32_t currentBackBuffer_ = 0; 93 | 94 | #ifdef _DEBUG 95 | VkDebugReportCallbackEXT debugCallback_; 96 | #endif 97 | }; 98 | 99 | } // namespace AMD 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /hellovulkan/src/VulkanTexturedQuad.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include "VulkanTexturedQuad.h" 24 | 25 | #include "Shaders.h" 26 | #include "Utility.h" 27 | #include "Window.h" 28 | 29 | #include "RubyTexture.h" 30 | #include "ImageIO.h" 31 | 32 | #include 33 | 34 | namespace AMD 35 | { 36 | /////////////////////////////////////////////////////////////////////////////// 37 | void VulkanTexturedQuad::ShutdownImpl() 38 | { 39 | vkDestroyPipeline(device_, pipeline_, nullptr); 40 | vkDestroyPipelineLayout(device_, pipelineLayout_, nullptr); 41 | 42 | vkDestroyBuffer(device_, vertexBuffer_, nullptr); 43 | vkDestroyBuffer(device_, indexBuffer_, nullptr); 44 | vkFreeMemory(device_, deviceBufferMemory_, nullptr); 45 | 46 | vkDestroyImageView (device_, rubyImageView_, nullptr); 47 | vkDestroyImage (device_, rubyImage_, nullptr); 48 | vkFreeMemory (device_, deviceImageMemory_, nullptr); 49 | 50 | vkDestroyBuffer (device_, uploadImageBuffer_, nullptr); 51 | vkFreeMemory (device_, uploadImageMemory_, nullptr); 52 | 53 | vkDestroyBuffer (device_, uploadBufferBuffer_, nullptr); 54 | vkFreeMemory (device_, uploadBufferMemory_, nullptr); 55 | 56 | vkDestroyDescriptorSetLayout (device_, descriptorSetLayout_, nullptr); 57 | vkDestroyDescriptorPool (device_, descriptorPool_, nullptr); 58 | 59 | vkDestroySampler (device_, sampler_, nullptr); 60 | 61 | vkDestroyShaderModule(device_, vertexShader_, nullptr); 62 | vkDestroyShaderModule(device_, fragmentShader_, nullptr); 63 | 64 | VulkanSample::ShutdownImpl(); 65 | } 66 | 67 | /////////////////////////////////////////////////////////////////////////////// 68 | void VulkanTexturedQuad::RenderImpl(VkCommandBuffer commandBuffer) 69 | { 70 | VulkanSample::RenderImpl(commandBuffer); 71 | 72 | VkViewport viewports [1] = {}; 73 | viewports [0].width = static_cast (window_->GetWidth ()); 74 | viewports [0].height = static_cast (window_->GetHeight ()); 75 | viewports [0].minDepth = 0; 76 | viewports [0].maxDepth = 1; 77 | 78 | vkCmdSetViewport (commandBuffer, 0, 1, viewports); 79 | 80 | VkRect2D scissors [1] = {}; 81 | scissors [0].extent.width = window_->GetWidth (); 82 | scissors [0].extent.height = window_->GetHeight (); 83 | vkCmdSetScissor (commandBuffer, 0, 1, scissors); 84 | 85 | vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 86 | pipeline_); 87 | VkDeviceSize offsets[] = { 0 }; 88 | vkCmdBindIndexBuffer(commandBuffer, indexBuffer_, 0, VK_INDEX_TYPE_UINT32); 89 | vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer_, offsets); 90 | 91 | vkCmdBindDescriptorSets (commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 92 | pipelineLayout_, 0, 1, &descriptorSet_, 0, nullptr); 93 | 94 | vkCmdDrawIndexed(commandBuffer, 6, 1, 0, 0, 0); 95 | } 96 | 97 | /////////////////////////////////////////////////////////////////////////////// 98 | void VulkanTexturedQuad::InitializeImpl(VkCommandBuffer uploadCommandBuffer) 99 | { 100 | VulkanSample::InitializeImpl(uploadCommandBuffer); 101 | 102 | CreateSampler (); 103 | CreateTexture (uploadCommandBuffer); 104 | CreateDescriptors (); 105 | CreatePipelineStateObject(); 106 | CreateMeshBuffers(uploadCommandBuffer); 107 | } 108 | 109 | namespace 110 | { 111 | struct MemoryTypeInfo 112 | { 113 | bool deviceLocal = false; 114 | bool hostVisible = false; 115 | bool hostCoherent = false; 116 | bool hostCached = false; 117 | bool lazilyAllocated = false; 118 | 119 | struct Heap 120 | { 121 | uint64_t size = 0; 122 | bool deviceLocal = false; 123 | }; 124 | 125 | Heap heap; 126 | int index; 127 | }; 128 | 129 | /////////////////////////////////////////////////////////////////////////////// 130 | std::vector EnumerateHeaps(VkPhysicalDevice device) 131 | { 132 | VkPhysicalDeviceMemoryProperties memoryProperties = {}; 133 | vkGetPhysicalDeviceMemoryProperties(device, &memoryProperties); 134 | 135 | std::vector heaps; 136 | 137 | for (uint32_t i = 0; i < memoryProperties.memoryHeapCount; ++i) 138 | { 139 | MemoryTypeInfo::Heap info; 140 | info.size = memoryProperties.memoryHeaps[i].size; 141 | info.deviceLocal = (memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0; 142 | 143 | heaps.push_back(info); 144 | } 145 | 146 | std::vector result; 147 | 148 | for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) 149 | { 150 | MemoryTypeInfo typeInfo; 151 | 152 | typeInfo.deviceLocal = (memoryProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0; 153 | typeInfo.hostVisible = (memoryProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0; 154 | typeInfo.hostCoherent = (memoryProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; 155 | typeInfo.hostCached = (memoryProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0; 156 | typeInfo.lazilyAllocated = (memoryProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0; 157 | 158 | typeInfo.heap = heaps[memoryProperties.memoryTypes[i].heapIndex]; 159 | 160 | typeInfo.index = static_cast (i); 161 | 162 | result.push_back(typeInfo); 163 | } 164 | 165 | return result; 166 | } 167 | 168 | enum MemoryProperties 169 | { 170 | MT_DeviceLocal = 1, 171 | MT_HostVisible = 2 172 | }; 173 | 174 | /////////////////////////////////////////////////////////////////////////////// 175 | VkDeviceMemory AllocateMemory(const std::vector& memoryInfos, 176 | VkDevice device, const int size, const uint32_t memoryBits, 177 | unsigned int memoryProperties, bool* isHostCoherent = nullptr) 178 | { 179 | for (auto& memoryInfo : memoryInfos) 180 | { 181 | if (((1 << memoryInfo.index) & memoryBits) == 0) { 182 | continue; 183 | } 184 | 185 | if ((memoryProperties & MT_DeviceLocal) && !memoryInfo.deviceLocal) 186 | { 187 | continue; 188 | } 189 | 190 | if ((memoryProperties & MT_HostVisible) && !memoryInfo.hostVisible) 191 | { 192 | continue; 193 | } 194 | 195 | if (isHostCoherent) 196 | { 197 | *isHostCoherent = memoryInfo.hostCoherent; 198 | } 199 | 200 | VkMemoryAllocateInfo memoryAllocateInfo = {}; 201 | memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 202 | memoryAllocateInfo.memoryTypeIndex = memoryInfo.index; 203 | memoryAllocateInfo.allocationSize = size; 204 | 205 | VkDeviceMemory deviceMemory; 206 | vkAllocateMemory(device, &memoryAllocateInfo, nullptr, 207 | &deviceMemory); 208 | return deviceMemory; 209 | } 210 | 211 | return VK_NULL_HANDLE; 212 | } 213 | 214 | /////////////////////////////////////////////////////////////////////////////// 215 | VkBuffer AllocateBuffer(VkDevice device, const int size, 216 | const VkBufferUsageFlags bits) 217 | { 218 | VkBufferCreateInfo bufferCreateInfo = {}; 219 | bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 220 | bufferCreateInfo.size = static_cast (size); 221 | bufferCreateInfo.usage = bits; 222 | 223 | VkBuffer result; 224 | vkCreateBuffer(device, &bufferCreateInfo, nullptr, &result); 225 | return result; 226 | } 227 | 228 | /////////////////////////////////////////////////////////////////////////////// 229 | VkPipelineLayout CreatePipelineLayout(VkDevice device) 230 | { 231 | VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {}; 232 | pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 233 | 234 | VkPipelineLayout result; 235 | vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, 236 | &result); 237 | 238 | return result; 239 | } 240 | 241 | /////////////////////////////////////////////////////////////////////////////// 242 | VkShaderModule LoadShader(VkDevice device, const void* shaderContents, 243 | const size_t size) 244 | { 245 | VkShaderModuleCreateInfo shaderModuleCreateInfo = {}; 246 | shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 247 | 248 | shaderModuleCreateInfo.pCode = static_cast (shaderContents); 249 | shaderModuleCreateInfo.codeSize = size; 250 | 251 | VkShaderModule result; 252 | vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, &result); 253 | 254 | return result; 255 | } 256 | 257 | /////////////////////////////////////////////////////////////////////////////// 258 | VkPipeline CreatePipeline(VkDevice device, VkRenderPass renderPass, VkPipelineLayout layout, 259 | VkShaderModule vertexShader, VkShaderModule fragmentShader) 260 | { 261 | VkVertexInputBindingDescription vertexInputBindingDescription; 262 | vertexInputBindingDescription.binding = 0; 263 | vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 264 | vertexInputBindingDescription.stride = sizeof(float) * 5; 265 | 266 | VkVertexInputAttributeDescription vertexInputAttributeDescription[2] = {}; 267 | vertexInputAttributeDescription[0].binding = vertexInputBindingDescription.binding; 268 | vertexInputAttributeDescription[0].format = VK_FORMAT_R32G32B32_SFLOAT; 269 | vertexInputAttributeDescription[0].location = 0; 270 | vertexInputAttributeDescription[0].offset = 0; 271 | 272 | vertexInputAttributeDescription[1].binding = vertexInputBindingDescription.binding; 273 | vertexInputAttributeDescription[1].format = VK_FORMAT_R32G32_SFLOAT; 274 | vertexInputAttributeDescription[1].location = 1; 275 | vertexInputAttributeDescription[1].offset = sizeof(float) * 3; 276 | 277 | VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = {}; 278 | pipelineVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 279 | pipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = std::extent::value; 280 | pipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescription; 281 | pipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = 1; 282 | pipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = &vertexInputBindingDescription; 283 | 284 | VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = {}; 285 | pipelineInputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 286 | pipelineInputAssemblyStateCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 287 | 288 | VkDynamicState dynamicStates [] = { 289 | VK_DYNAMIC_STATE_VIEWPORT, 290 | VK_DYNAMIC_STATE_SCISSOR 291 | }; 292 | 293 | VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {}; 294 | dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 295 | dynamicStateCreateInfo.dynamicStateCount = 2; 296 | dynamicStateCreateInfo.pDynamicStates = dynamicStates; 297 | 298 | VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {}; 299 | pipelineViewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 300 | pipelineViewportStateCreateInfo.viewportCount = 1; 301 | pipelineViewportStateCreateInfo.scissorCount = 1; 302 | 303 | VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {}; 304 | pipelineColorBlendAttachmentState.colorWriteMask = 0xF; 305 | pipelineColorBlendAttachmentState.blendEnable = VK_FALSE; 306 | 307 | VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {}; 308 | pipelineColorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 309 | 310 | pipelineColorBlendStateCreateInfo.attachmentCount = 1; 311 | pipelineColorBlendStateCreateInfo.pAttachments = &pipelineColorBlendAttachmentState; 312 | 313 | VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = {}; 314 | pipelineRasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 315 | pipelineRasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL; 316 | pipelineRasterizationStateCreateInfo.cullMode = VK_CULL_MODE_NONE; 317 | pipelineRasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 318 | pipelineRasterizationStateCreateInfo.depthClampEnable = VK_FALSE; 319 | pipelineRasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE; 320 | pipelineRasterizationStateCreateInfo.depthBiasEnable = VK_FALSE; 321 | pipelineRasterizationStateCreateInfo.lineWidth = 1.0f; 322 | 323 | VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {}; 324 | pipelineDepthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 325 | pipelineDepthStencilStateCreateInfo.depthTestEnable = VK_FALSE; 326 | pipelineDepthStencilStateCreateInfo.depthWriteEnable = VK_FALSE; 327 | pipelineDepthStencilStateCreateInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS; 328 | pipelineDepthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE; 329 | pipelineDepthStencilStateCreateInfo.back.failOp = VK_STENCIL_OP_KEEP; 330 | pipelineDepthStencilStateCreateInfo.back.passOp = VK_STENCIL_OP_KEEP; 331 | pipelineDepthStencilStateCreateInfo.back.compareOp = VK_COMPARE_OP_ALWAYS; 332 | pipelineDepthStencilStateCreateInfo.stencilTestEnable = VK_FALSE; 333 | pipelineDepthStencilStateCreateInfo.front = pipelineDepthStencilStateCreateInfo.back; 334 | 335 | VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {}; 336 | pipelineMultisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 337 | pipelineMultisampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 338 | 339 | VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfos[2] = {}; 340 | pipelineShaderStageCreateInfos[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 341 | pipelineShaderStageCreateInfos[0].module = vertexShader; 342 | pipelineShaderStageCreateInfos[0].pName = "main"; 343 | pipelineShaderStageCreateInfos[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 344 | 345 | pipelineShaderStageCreateInfos[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 346 | pipelineShaderStageCreateInfos[1].module = fragmentShader; 347 | pipelineShaderStageCreateInfos[1].pName = "main"; 348 | pipelineShaderStageCreateInfos[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 349 | 350 | VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {}; 351 | graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 352 | 353 | graphicsPipelineCreateInfo.layout = layout; 354 | graphicsPipelineCreateInfo.pVertexInputState = &pipelineVertexInputStateCreateInfo; 355 | graphicsPipelineCreateInfo.pInputAssemblyState = &pipelineInputAssemblyStateCreateInfo; 356 | graphicsPipelineCreateInfo.renderPass = renderPass; 357 | graphicsPipelineCreateInfo.pViewportState = &pipelineViewportStateCreateInfo; 358 | graphicsPipelineCreateInfo.pColorBlendState = &pipelineColorBlendStateCreateInfo; 359 | graphicsPipelineCreateInfo.pRasterizationState = &pipelineRasterizationStateCreateInfo; 360 | graphicsPipelineCreateInfo.pDepthStencilState = &pipelineDepthStencilStateCreateInfo; 361 | graphicsPipelineCreateInfo.pMultisampleState = &pipelineMultisampleStateCreateInfo; 362 | graphicsPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo; 363 | graphicsPipelineCreateInfo.pStages = pipelineShaderStageCreateInfos; 364 | graphicsPipelineCreateInfo.stageCount = 2; 365 | 366 | VkPipeline pipeline; 367 | vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, 368 | nullptr, &pipeline); 369 | 370 | return pipeline; 371 | } 372 | } // namespace 373 | 374 | /////////////////////////////////////////////////////////////////////////////// 375 | void VulkanTexturedQuad::CreateMeshBuffers(VkCommandBuffer uploadCommandBuffer) 376 | { 377 | struct Vertex 378 | { 379 | float position[3]; 380 | float uv[2]; 381 | }; 382 | 383 | static const Vertex vertices[4] = 384 | { 385 | // Upper Left 386 | { { -1.0f, 1.0f, 0 }, { 0, 1 } }, 387 | // Upper Right 388 | { { 1.0f, 1.0f, 0 }, { 1, 1 } }, 389 | // Bottom right 390 | { { 1.0f, -1.0f, 0 }, { 1, 0 } }, 391 | // Bottom left 392 | { { -1.0f, -1.0f, 0 }, { 0, 0 } } 393 | }; 394 | 395 | static const int indices[6] = 396 | { 397 | 0, 1, 2, 2, 3, 0 398 | }; 399 | 400 | auto memoryHeaps = EnumerateHeaps(physicalDevice_); 401 | 402 | indexBuffer_ = AllocateBuffer(device_, sizeof(indices), 403 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); 404 | vertexBuffer_ = AllocateBuffer(device_, sizeof(vertices), 405 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 406 | 407 | VkMemoryRequirements vertexBufferMemoryRequirements = {}; 408 | vkGetBufferMemoryRequirements(device_, vertexBuffer_, 409 | &vertexBufferMemoryRequirements); 410 | VkMemoryRequirements indexBufferMemoryRequirements = {}; 411 | vkGetBufferMemoryRequirements(device_, indexBuffer_, 412 | &indexBufferMemoryRequirements); 413 | 414 | VkDeviceSize bufferSize = vertexBufferMemoryRequirements.size; 415 | // We want to place the index buffer behind the vertex buffer. Need to take 416 | // the alignment into account to find the next suitable location 417 | VkDeviceSize indexBufferOffset = RoundToNextMultiple(bufferSize, 418 | indexBufferMemoryRequirements.alignment); 419 | 420 | bufferSize = indexBufferOffset + indexBufferMemoryRequirements.size; 421 | deviceBufferMemory_ = AllocateMemory(memoryHeaps, device_, 422 | static_cast(bufferSize), 423 | vertexBufferMemoryRequirements.memoryTypeBits & indexBufferMemoryRequirements.memoryTypeBits, 424 | MT_DeviceLocal); 425 | 426 | vkBindBufferMemory(device_, vertexBuffer_, deviceBufferMemory_, 0); 427 | vkBindBufferMemory(device_, indexBuffer_, deviceBufferMemory_, 428 | indexBufferOffset); 429 | 430 | uploadBufferBuffer_ = AllocateBuffer (device_, static_cast (bufferSize), 431 | VK_BUFFER_USAGE_TRANSFER_SRC_BIT); 432 | VkMemoryRequirements uploadBufferMemoryRequirements = {}; 433 | vkGetBufferMemoryRequirements (device_, uploadBufferBuffer_, 434 | &uploadBufferMemoryRequirements); 435 | 436 | bool memoryIsHostCoherent = false; 437 | uploadBufferMemory_ = AllocateMemory(memoryHeaps, device_, 438 | static_cast(uploadBufferMemoryRequirements.size), 439 | vertexBufferMemoryRequirements.memoryTypeBits & indexBufferMemoryRequirements.memoryTypeBits, 440 | MT_HostVisible, &memoryIsHostCoherent); 441 | 442 | vkBindBufferMemory (device_, uploadBufferBuffer_, uploadBufferMemory_, 0); 443 | 444 | void* mapping = nullptr; 445 | vkMapMemory(device_, uploadBufferMemory_, 0, VK_WHOLE_SIZE, 446 | 0, &mapping); 447 | ::memcpy(mapping, vertices, sizeof(vertices)); 448 | 449 | ::memcpy(static_cast (mapping) + indexBufferOffset, 450 | indices, sizeof(indices)); 451 | 452 | if (!memoryIsHostCoherent) 453 | { 454 | VkMappedMemoryRange mappedMemoryRange = {}; 455 | mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 456 | mappedMemoryRange.memory = uploadBufferMemory_; 457 | mappedMemoryRange.offset = 0; 458 | mappedMemoryRange.size = VK_WHOLE_SIZE; 459 | 460 | vkFlushMappedMemoryRanges (device_, 1, &mappedMemoryRange); 461 | } 462 | 463 | vkUnmapMemory(device_, uploadBufferMemory_); 464 | 465 | VkBufferCopy vertexCopy = {}; 466 | vertexCopy.size = sizeof (vertices); 467 | 468 | VkBufferCopy indexCopy = {}; 469 | indexCopy.size = sizeof (indices); 470 | indexCopy.srcOffset = indexBufferOffset; 471 | 472 | vkCmdCopyBuffer (uploadCommandBuffer, uploadBufferBuffer_, vertexBuffer_, 473 | 1, &vertexCopy); 474 | vkCmdCopyBuffer (uploadCommandBuffer, uploadBufferBuffer_, indexBuffer_, 475 | 1, &indexCopy); 476 | 477 | VkBufferMemoryBarrier uploadBarriers[2] = {}; 478 | uploadBarriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 479 | uploadBarriers[0].buffer = vertexBuffer_; 480 | uploadBarriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 481 | uploadBarriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 482 | uploadBarriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 483 | uploadBarriers[0].dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; 484 | uploadBarriers[0].size = VK_WHOLE_SIZE; 485 | 486 | uploadBarriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 487 | uploadBarriers[1].buffer = indexBuffer_; 488 | uploadBarriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 489 | uploadBarriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 490 | uploadBarriers[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 491 | uploadBarriers[1].dstAccessMask = VK_ACCESS_INDEX_READ_BIT; 492 | uploadBarriers[1].size = VK_WHOLE_SIZE; 493 | 494 | vkCmdPipelineBarrier (uploadCommandBuffer, 495 | VK_PIPELINE_STAGE_TRANSFER_BIT, 496 | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 497 | 0, 0, nullptr, 2, uploadBarriers, 498 | 0, nullptr); 499 | } 500 | 501 | /////////////////////////////////////////////////////////////////////////////// 502 | void VulkanTexturedQuad::CreateTexture (VkCommandBuffer uploadCommandList) 503 | { 504 | int width, height; 505 | auto image = LoadImageFromMemory (RubyTexture, sizeof (RubyTexture), 506 | 1, &width, &height); 507 | 508 | VkImageCreateInfo imageCreateInfo = {}; 509 | imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 510 | imageCreateInfo.pNext = nullptr; 511 | imageCreateInfo.queueFamilyIndexCount = 1; 512 | uint32_t queueFamilyIndex = static_cast (queueFamilyIndex_); 513 | imageCreateInfo.pQueueFamilyIndices = &queueFamilyIndex; 514 | imageCreateInfo.mipLevels = 1; 515 | imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; 516 | imageCreateInfo.arrayLayers = 1; 517 | imageCreateInfo.extent.depth = 1; 518 | imageCreateInfo.extent.height = height; 519 | imageCreateInfo.extent.width = width; 520 | imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 521 | imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; 522 | imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; 523 | imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; 524 | imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 525 | 526 | vkCreateImage (device_, &imageCreateInfo, nullptr, &rubyImage_); 527 | 528 | VkMemoryRequirements requirements = {}; 529 | vkGetImageMemoryRequirements (device_, rubyImage_, 530 | &requirements); 531 | 532 | VkDeviceSize requiredSizeForImage = requirements.size; 533 | 534 | auto memoryHeaps = EnumerateHeaps (physicalDevice_); 535 | deviceImageMemory_ = AllocateMemory (memoryHeaps, device_, static_cast (requiredSizeForImage), 536 | requirements.memoryTypeBits, 537 | MT_DeviceLocal); 538 | 539 | vkBindImageMemory (device_, rubyImage_, deviceImageMemory_, 0); 540 | 541 | VkBufferCreateInfo bufferCreateInfo = {}; 542 | bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 543 | bufferCreateInfo.pNext = nullptr; 544 | bufferCreateInfo.queueFamilyIndexCount = 1; 545 | bufferCreateInfo.pQueueFamilyIndices = &queueFamilyIndex; 546 | bufferCreateInfo.size = requiredSizeForImage; 547 | bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; 548 | 549 | vkCreateBuffer (device_, &bufferCreateInfo, nullptr, &uploadImageBuffer_); 550 | 551 | vkGetBufferMemoryRequirements (device_, uploadImageBuffer_, &requirements); 552 | 553 | VkDeviceSize requiredSizeForBuffer = requirements.size; 554 | 555 | bool memoryIsHostCoherent = false; 556 | uploadImageMemory_ = AllocateMemory (memoryHeaps, device_, 557 | static_cast (requiredSizeForBuffer), requirements.memoryTypeBits, 558 | MT_HostVisible, &memoryIsHostCoherent); 559 | 560 | vkBindBufferMemory (device_, uploadImageBuffer_, uploadImageMemory_, 0); 561 | 562 | void* data = nullptr; 563 | vkMapMemory (device_, uploadImageMemory_, 0, VK_WHOLE_SIZE, 564 | 0, &data); 565 | ::memcpy (data, image.data (), image.size ()); 566 | 567 | if (!memoryIsHostCoherent) 568 | { 569 | VkMappedMemoryRange mappedMemoryRange = {}; 570 | mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 571 | mappedMemoryRange.memory = uploadImageMemory_; 572 | mappedMemoryRange.offset = 0; 573 | mappedMemoryRange.size = VK_WHOLE_SIZE; 574 | 575 | vkFlushMappedMemoryRanges (device_, 1, &mappedMemoryRange); 576 | } 577 | 578 | vkUnmapMemory (device_, uploadImageMemory_); 579 | 580 | VkBufferImageCopy bufferImageCopy = {}; 581 | bufferImageCopy.imageExtent.width = width; 582 | bufferImageCopy.imageExtent.height = height; 583 | bufferImageCopy.imageExtent.depth = 1; 584 | bufferImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 585 | bufferImageCopy.imageSubresource.mipLevel = 0; 586 | bufferImageCopy.imageSubresource.layerCount = 1; 587 | 588 | VkImageMemoryBarrier imageBarrier = {}; 589 | imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 590 | imageBarrier.pNext = nullptr; 591 | imageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 592 | imageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 593 | imageBarrier.srcAccessMask = 0; 594 | imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 595 | imageBarrier.image = rubyImage_; 596 | imageBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 597 | imageBarrier.subresourceRange.layerCount = 1; 598 | imageBarrier.subresourceRange.levelCount = 1; 599 | 600 | vkCmdPipelineBarrier (uploadCommandList, 601 | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 602 | VK_PIPELINE_STAGE_TRANSFER_BIT, 603 | 0, 0, nullptr, 0, nullptr, 604 | 1, &imageBarrier); 605 | 606 | vkCmdCopyBufferToImage (uploadCommandList, uploadImageBuffer_, 607 | rubyImage_, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 608 | 1, &bufferImageCopy); 609 | 610 | imageBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 611 | imageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 612 | imageBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 613 | imageBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 614 | 615 | vkCmdPipelineBarrier (uploadCommandList, 616 | VK_PIPELINE_STAGE_TRANSFER_BIT, 617 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 618 | 0, 0, nullptr, 0, nullptr, 619 | 1, &imageBarrier); 620 | 621 | VkImageViewCreateInfo imageViewCreateInfo = {}; 622 | imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 623 | imageViewCreateInfo.format = imageCreateInfo.format; 624 | imageViewCreateInfo.image = rubyImage_; 625 | imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 626 | imageViewCreateInfo.subresourceRange.levelCount = 1; 627 | imageViewCreateInfo.subresourceRange.layerCount = 1; 628 | imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; 629 | 630 | vkCreateImageView (device_, &imageViewCreateInfo, nullptr, &rubyImageView_); 631 | } 632 | 633 | /////////////////////////////////////////////////////////////////////////////// 634 | void VulkanTexturedQuad::CreateSampler () 635 | { 636 | VkSamplerCreateInfo samplerCreateInfo = {}; 637 | samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 638 | samplerCreateInfo.magFilter = VK_FILTER_LINEAR; 639 | samplerCreateInfo.minFilter = VK_FILTER_LINEAR; 640 | 641 | vkCreateSampler (device_, &samplerCreateInfo, nullptr, &sampler_); 642 | } 643 | 644 | /////////////////////////////////////////////////////////////////////////////// 645 | void VulkanTexturedQuad::CreateDescriptors () 646 | { 647 | VkDescriptorSetLayoutBinding descriptorSetLayoutBinding[2] = {}; 648 | descriptorSetLayoutBinding[0].binding = 0; 649 | descriptorSetLayoutBinding[0].descriptorCount = 1; 650 | descriptorSetLayoutBinding[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; 651 | descriptorSetLayoutBinding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 652 | descriptorSetLayoutBinding[1].binding = 1; 653 | descriptorSetLayoutBinding[1].descriptorCount = 1; 654 | descriptorSetLayoutBinding[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; 655 | descriptorSetLayoutBinding[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 656 | descriptorSetLayoutBinding[1].pImmutableSamplers = &sampler_; 657 | 658 | VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo[1] = {}; 659 | descriptorSetLayoutCreateInfo[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 660 | descriptorSetLayoutCreateInfo[0].bindingCount = 2; 661 | descriptorSetLayoutCreateInfo[0].pBindings = descriptorSetLayoutBinding; 662 | 663 | vkCreateDescriptorSetLayout ( 664 | device_, descriptorSetLayoutCreateInfo, 665 | nullptr, &descriptorSetLayout_); 666 | 667 | VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {}; 668 | pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 669 | pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout_; 670 | pipelineLayoutCreateInfo.setLayoutCount = 1; 671 | 672 | vkCreatePipelineLayout (device_, &pipelineLayoutCreateInfo, 673 | nullptr, &pipelineLayout_); 674 | 675 | VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {}; 676 | descriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 677 | descriptorPoolCreateInfo.maxSets = 1; 678 | 679 | VkDescriptorPoolSize descriptorPoolSize [2] = {}; 680 | descriptorPoolSize[0].descriptorCount = 1; 681 | descriptorPoolSize[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; 682 | descriptorPoolSize[1].descriptorCount = 1; 683 | descriptorPoolSize[1].type = VK_DESCRIPTOR_TYPE_SAMPLER; 684 | 685 | descriptorPoolCreateInfo.poolSizeCount = 2; 686 | descriptorPoolCreateInfo.pPoolSizes = descriptorPoolSize; 687 | 688 | vkCreateDescriptorPool (device_, &descriptorPoolCreateInfo, 689 | nullptr, &descriptorPool_); 690 | 691 | VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {}; 692 | descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 693 | descriptorSetAllocateInfo.pSetLayouts = &descriptorSetLayout_; 694 | descriptorSetAllocateInfo.descriptorSetCount = 1; 695 | descriptorSetAllocateInfo.descriptorPool = descriptorPool_; 696 | 697 | vkAllocateDescriptorSets (device_, &descriptorSetAllocateInfo, &descriptorSet_); 698 | 699 | VkWriteDescriptorSet writeDescriptorSets[1] = {}; 700 | writeDescriptorSets[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 701 | writeDescriptorSets[0].dstSet = descriptorSet_; 702 | writeDescriptorSets[0].descriptorCount = 1; 703 | writeDescriptorSets[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; 704 | writeDescriptorSets[0].dstBinding = 0; 705 | 706 | VkDescriptorImageInfo descriptorImageInfo[1] = {}; 707 | descriptorImageInfo[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 708 | descriptorImageInfo[0].imageView = rubyImageView_; 709 | 710 | writeDescriptorSets[0].pImageInfo = &descriptorImageInfo[0]; 711 | 712 | vkUpdateDescriptorSets (device_, 1, writeDescriptorSets, 0, nullptr); 713 | } 714 | 715 | /////////////////////////////////////////////////////////////////////////////// 716 | void VulkanTexturedQuad::CreatePipelineStateObject() 717 | { 718 | vertexShader_ = LoadShader(device_, BasicVertexShader, sizeof(BasicVertexShader)); 719 | fragmentShader_ = LoadShader(device_, TexturedFragmentShader, sizeof(TexturedFragmentShader)); 720 | 721 | pipeline_ = CreatePipeline(device_, renderPass_, pipelineLayout_, 722 | vertexShader_, fragmentShader_); 723 | } 724 | } // namespace AMD 725 | -------------------------------------------------------------------------------- /hellovulkan/src/VulkanTexturedQuad.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #ifndef AMD_VULKAN_SAMPLE_TEXTURED_QUAD_H_ 24 | #define AMD_VULKAN_SAMPLE_TEXTURED_QUAD_H_ 25 | 26 | #include "VulkanSample.h" 27 | 28 | namespace AMD 29 | { 30 | class VulkanTexturedQuad : public VulkanSample 31 | { 32 | private: 33 | void CreatePipelineStateObject(); 34 | void CreateMeshBuffers(VkCommandBuffer uploadCommandList); 35 | void CreateTexture(VkCommandBuffer uploadCommandList); 36 | void CreateDescriptors (); 37 | void CreateSampler (); 38 | void RenderImpl(VkCommandBuffer commandList) override; 39 | void InitializeImpl(VkCommandBuffer uploadCommandList) override; 40 | void ShutdownImpl() override; 41 | 42 | VkDeviceMemory deviceBufferMemory_ = VK_NULL_HANDLE; 43 | VkBuffer vertexBuffer_ = VK_NULL_HANDLE; 44 | VkBuffer indexBuffer_ = VK_NULL_HANDLE; 45 | 46 | VkDeviceMemory uploadBufferMemory_ = VK_NULL_HANDLE; 47 | VkBuffer uploadBufferBuffer_ = VK_NULL_HANDLE; 48 | 49 | VkShaderModule vertexShader_ = VK_NULL_HANDLE; 50 | VkShaderModule fragmentShader_ = VK_NULL_HANDLE; 51 | 52 | VkPipeline pipeline_ = VK_NULL_HANDLE; 53 | VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE; 54 | 55 | VkDeviceMemory deviceImageMemory_ = VK_NULL_HANDLE; 56 | VkImage rubyImage_ = VK_NULL_HANDLE; 57 | VkImageView rubyImageView_ = VK_NULL_HANDLE; 58 | 59 | VkDeviceMemory uploadImageMemory_ = VK_NULL_HANDLE; 60 | VkBuffer uploadImageBuffer_ = VK_NULL_HANDLE; 61 | 62 | VkDescriptorPool descriptorPool_ = VK_NULL_HANDLE; 63 | VkDescriptorSet descriptorSet_ = VK_NULL_HANDLE; 64 | VkDescriptorSetLayout descriptorSetLayout_ = VK_NULL_HANDLE; 65 | 66 | VkSampler sampler_ = VK_NULL_HANDLE; 67 | }; 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /hellovulkan/src/Window.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #include "Window.h" 24 | 25 | namespace AMD 26 | { 27 | namespace 28 | { 29 | /////////////////////////////////////////////////////////////////////////////// 30 | LRESULT CALLBACK amdWndProc( 31 | HWND hwnd, 32 | UINT uMsg, 33 | WPARAM wParam, 34 | LPARAM lParam 35 | ) 36 | { 37 | auto ptr = ::GetWindowLongPtr(hwnd, GWLP_USERDATA); 38 | auto window = reinterpret_cast (ptr); 39 | 40 | switch (uMsg) 41 | { 42 | case WM_CLOSE: 43 | window->OnClose(); 44 | return 0; 45 | } 46 | 47 | return ::DefWindowProcA(hwnd, uMsg, wParam, lParam); 48 | } 49 | } // namespace 50 | 51 | /////////////////////////////////////////////////////////////////////////////// 52 | IWindow::~IWindow() 53 | { 54 | } 55 | 56 | /////////////////////////////////////////////////////////////////////////////// 57 | int IWindow::GetWidth() const 58 | { 59 | return GetWidthImpl(); 60 | } 61 | 62 | /////////////////////////////////////////////////////////////////////////////// 63 | int IWindow::GetHeight() const 64 | { 65 | return GetHeightImpl(); 66 | } 67 | 68 | /////////////////////////////////////////////////////////////////////////////// 69 | Window::Window(const std::string& title, const int width, const int height) 70 | : width_ (width) 71 | , height_ (height) 72 | { 73 | DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; 74 | 75 | ::RECT rect; 76 | ::SetRect(&rect, 0, 0, width, height); 77 | ::AdjustWindowRect(&rect, style, FALSE); 78 | 79 | windowClass_.reset(new WindowClass("VulkanSampleWindowClass", amdWndProc)); 80 | 81 | // Create the main window. 82 | hwnd_ = ::CreateWindowA(windowClass_->GetName().c_str(), 83 | title.c_str(), 84 | style, CW_USEDEFAULT, CW_USEDEFAULT, 85 | rect.right - rect.left, rect.bottom - rect.top, (HWND)NULL, 86 | (HMENU)NULL, NULL, (LPVOID)NULL); 87 | 88 | ::SetWindowLongPtr(hwnd_, GWLP_USERDATA, reinterpret_cast (this)); 89 | 90 | // Show the window and paint its contents. 91 | ::ShowWindow(hwnd_, SW_SHOWDEFAULT); 92 | ::UpdateWindow(hwnd_); 93 | } 94 | 95 | /////////////////////////////////////////////////////////////////////////////// 96 | bool IWindow::IsClosed() const 97 | { 98 | return IsClosedImpl(); 99 | } 100 | 101 | /////////////////////////////////////////////////////////////////////////////// 102 | HWND Window::GetHWND () const 103 | { 104 | return hwnd_; 105 | } 106 | 107 | ///////////////////////////////////////////////////////////////////////// 108 | WindowClass::WindowClass(const std::string& name, ::WNDPROC procedure) 109 | : name_(name) 110 | { 111 | ::WNDCLASSA wc; 112 | 113 | // Register the window class for the main window. 114 | wc.style = 0; 115 | wc.lpfnWndProc = procedure; 116 | wc.cbClsExtra = 0; 117 | wc.cbWndExtra = 0; 118 | wc.hInstance = NULL; 119 | wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 120 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); 121 | wc.hbrBackground = NULL; 122 | wc.lpszMenuName = NULL; 123 | wc.lpszClassName = name_.c_str(); 124 | 125 | ::RegisterClassA(&wc); 126 | } 127 | 128 | ///////////////////////////////////////////////////////////////////////// 129 | const std::string& WindowClass::GetName() const 130 | { 131 | return name_; 132 | } 133 | 134 | ///////////////////////////////////////////////////////////////////////// 135 | WindowClass::~WindowClass() 136 | { 137 | ::UnregisterClassA(name_.c_str(), 138 | (HINSTANCE)::GetModuleHandle(NULL)); 139 | } 140 | 141 | } // namespace AMD 142 | -------------------------------------------------------------------------------- /hellovulkan/src/Window.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #ifndef AMD_VULKAN_SAMPLE_WINDOW_H_ 24 | #define AMD_VULKAN_SAMPLE_WINDOW_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace AMD 31 | { 32 | /** 33 | * Encapsulate a window class. 34 | * 35 | * Calls ::RegisterClass() on create, and ::UnregisterClass() 36 | * on destruction. 37 | */ 38 | struct WindowClass final 39 | { 40 | public: 41 | WindowClass(const std::string& name, 42 | ::WNDPROC procedure = ::DefWindowProc); 43 | ~WindowClass(); 44 | 45 | const std::string& GetName() const; 46 | 47 | WindowClass(const WindowClass&) = delete; 48 | WindowClass& operator= (const WindowClass&) = delete; 49 | 50 | private: 51 | std::string name_; 52 | }; 53 | 54 | struct IWindow 55 | { 56 | public: 57 | IWindow() = default; 58 | IWindow(const IWindow&) = delete; 59 | IWindow& operator=(const IWindow&) = delete; 60 | 61 | virtual ~IWindow(); 62 | 63 | bool IsClosed() const; 64 | virtual void OnClose() = 0; 65 | 66 | int GetWidth() const; 67 | int GetHeight() const; 68 | 69 | private: 70 | virtual bool IsClosedImpl() const = 0; 71 | virtual int GetWidthImpl() const = 0; 72 | virtual int GetHeightImpl() const = 0; 73 | }; 74 | 75 | class Window : public IWindow 76 | { 77 | public: 78 | Window(const std::string& title, int width, int height); 79 | 80 | HWND GetHWND() const; 81 | 82 | void OnClose() override 83 | { 84 | isClosed_ = true; 85 | } 86 | 87 | private: 88 | bool IsClosedImpl() const override 89 | { 90 | return isClosed_; 91 | } 92 | 93 | int GetWidthImpl() const override 94 | { 95 | return width_; 96 | } 97 | 98 | int GetHeightImpl() const override 99 | { 100 | return height_; 101 | } 102 | 103 | std::unique_ptr windowClass_; 104 | HWND hwnd_ = 0; 105 | bool isClosed_ = false; 106 | int width_ = -1, height_ = -1; 107 | }; 108 | 109 | } // namespace AMD 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /hellovulkan/src/basic.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | layout (location = 0) in vec2 uv; 5 | layout (location = 0) out vec4 outputColor; 6 | 7 | void main() { 8 | outputColor = vec4 (uv,0,1); 9 | } 10 | -------------------------------------------------------------------------------- /hellovulkan/src/basic.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HelloVulkan/2575360ce8cf0393d5797fc80ca4b749a1b01d08/hellovulkan/src/basic.spv -------------------------------------------------------------------------------- /hellovulkan/src/textured.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | layout (location = 0) in vec2 uv; 5 | layout (location = 0) out vec4 outputColor; 6 | 7 | layout (binding = 0) uniform texture2D colorTexture; 8 | layout (binding = 1) uniform sampler colorSampler; 9 | 10 | void main() { 11 | outputColor = texture (sampler2D (colorTexture, colorSampler), uv); 12 | } 13 | -------------------------------------------------------------------------------- /hellovulkan/src/textured.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HelloVulkan/2575360ce8cf0393d5797fc80ca4b749a1b01d08/hellovulkan/src/textured.spv -------------------------------------------------------------------------------- /hellovulkan/src/tri.vert: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | #version 400 24 | #extension GL_ARB_separate_shader_objects : enable 25 | #extension GL_ARB_shading_language_420pack : enable 26 | layout (location = 0) in vec3 pos; 27 | layout (location = 1) in vec2 inUv; 28 | layout (location = 0) out vec2 outUv; 29 | 30 | out gl_PerVertex { 31 | vec4 gl_Position; 32 | }; 33 | 34 | void main() { 35 | gl_Position = vec4(pos,1); 36 | outUv = inUv; 37 | } 38 | -------------------------------------------------------------------------------- /hellovulkan/src/vs.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HelloVulkan/2575360ce8cf0393d5797fc80ca4b749a1b01d08/hellovulkan/src/vs.spv -------------------------------------------------------------------------------- /hellovulkan/tools/binaryToHeader.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import os 3 | import sys 4 | 5 | def BinaryToHeader (binary, variablename): 6 | bytesPerLine = 80 // 6 7 | print ('const unsigned char {} [] = {{'.format (variablename)) 8 | 9 | for i in range (0, len (binary), bytesPerLine): 10 | print ('\t', end='') 11 | # This will automatically cut off at the end 12 | bytesForLine = binary [i:i+bytesPerLine] 13 | for byte in bytesForLine: 14 | print ('{0:4}, '.format (hex (byte)), end='') 15 | print () 16 | print ('};') 17 | 18 | if __name__=='__main__': 19 | BinaryToHeader (open (sys.argv[1], 'rb').read (), sys.argv[2]) 20 | -------------------------------------------------------------------------------- /hellovulkan/tools/sourceToHeader.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def escape(line): 4 | line = line.replace ('"', '\\"') 5 | line = line.replace ('\n', '\\n') 6 | return line 7 | 8 | if __name__=='__main__': 9 | print ('const char {}[] = '.format (sys.argv[2])) 10 | for l in open(sys.argv[1], 'r').readlines(): 11 | print ('"{}"'.format (escape (l))) 12 | print (';') 13 | -------------------------------------------------------------------------------- /premake/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003-2015 Jason Perkins and individual contributors. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of Premake nor the names of its contributors may be 15 | used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /premake/amd_premake_util.lua: -------------------------------------------------------------------------------- 1 | -- amd_premake_util.lua 2 | -- utility code shared by AMD build scripts 3 | 4 | -- _ACTION is a premake global variable and for our usage will be vs2012, vs2013, etc. 5 | -- Strip "vs" from this string to make a suffix for solution and project files. 6 | _AMD_VS_SUFFIX = "_" .. string.gsub(_ACTION, "vs", "") 7 | 8 | -- Specify build output directory structure here: e.g. Desktop_2012\x64\DLL_Debug 9 | _AMD_SAMPLE_DIR_LAYOUT = "Desktop%{_AMD_VS_SUFFIX}/%{cfg.platform}/%{cfg.buildcfg}" 10 | 11 | -- Specify WindowsTargetPlatformVersion here for VS2015 12 | _AMD_WIN_SDK_VERSION = "8.1" 13 | 14 | -------------------------------------------------------------------------------- /premake/premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/HelloVulkan/2575360ce8cf0393d5797fc80ca4b749a1b01d08/premake/premake5.exe --------------------------------------------------------------------------------