andy-thomason / vookoo Goto Github PK
View Code? Open in Web Editor NEWA set of utilities for taking the pain out of Vulkan in header only modern C++
License: MIT License
A set of utilities for taking the pain out of Vulkan in header only modern C++
License: MIT License
When installing Vulkan SDK 1.3.216 or after on MacOS, the following appears:
NOTICE: As of the 1.3.216 SDK release, the Vulkan Portability Enumeration extension is being enforced by the Vulkan loader. Failure to 'opt in' for non-conformant Vulkan implementations will cause applications to fail to find the MoltenVK ICD. See the macOS release notes for more information.
Indeed the code will not run anymore.
Fixing it requires a few changes: adding more layers to the default:
instance_extensions_.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
instance_extensions_.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
and a flag when calling InstanceCreateInfo
:
vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR
Unfortunately, some of these constants are not available with the glfw provided Vulkan headers. Updating the version of glfw is also necessary.
I will create a PR for this issue.
I suggest that we create a vookoo organisation on GitHub with pointers to documentation.
Ideally, the project should have:
The copyright should now be "Vookoo contributors" and we
should name you in the README (you can do this as badges, too).
I'm doing this with extendr right now:
The bundled external/vulkan
headers are 10 months old now, and Vookoo doesn't seem to be updated to use more recent ones.
Attempting to use Vookoo with the latest Vulkan headers fails, for example:
../include/vku/vku.hpp:1190:47: error: could not convert ‘vk::Device::allocateDescriptorSetsUnique(const vk::DescriptorSetAllocateInfo&) const [with Allocator = std::allocator<vk::DescriptorSet>; typename vk::ResultValueType<std::vector<vk::UniqueHandle<vk::DescriptorSet>, Allocator> >::type = std::vector<vk::UniqueHandle<vk::DescriptorSet>, std::allocator<vk::DescriptorSet> >](dsai)’
from ‘vector<[...],allocator<vk::DescriptorSet>>’ to ‘vector<[...],allocator<vk::UniqueHandle<vk::DescriptorSet>>>’
return device.allocateDescriptorSetsUnique(dsai);
Are there any plans on updating to the latest Vulkan version?
PS: Vulkan-Hpp also seems to be a couple of versions behind, but since it generates its own vulkan.hpp with a tool, one can just provide a newer vk.xml.
I've started making use of Vookoo in my own project (so far I had only played on making all the examples work on all my machines) and discovered that there is no support for handling window resize in the vku_framework.
I can get started on this but need a recommendation. @andy-thomason, should this be done within the vku::Window
or should the existing vku::Window
have its destructor called and a new one rebuilt from scratch? I do not have a feel for how light/heavy everything related to creation/destruction of the window is. It seems fairly heavy, yet Vulkan's swapchain recreation is not light to start with. Clearly the destructor/constructor approach is probably easier to implement but if it does a lot of extra work, it may cause stuttering in resize.
In my own project, I had separated the swapchain as an object that handles the framebuffers and handled the whole recreation within an abstraction of my window/surface. Here, those roles are the Window's domain and I could try to do the minimum work within it. My work previously within Qt toolkit is stutter free.
std::aligned_union
is an obsolete standard library feature, and its use causes Vookoo to not compile with a nightly libc++18 in C++2c mode.
/home/conscat/foo/Vookoo/include/vku/vku.hpp:1162:10: error: no template named 'aligned_union' in namespace 'std'
1162 | std::aligned_union<4, VkBool32, uint32_t, int32_t, float, double>::type
| ~~~~~^
Simply changing the compiler flag down to 20 makes this compile again. It was deprecated in 23 and removed in 2c.
https://en.cppreference.com/w/cpp/types/aligned_union
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1413r2.pdf
I think these definitions could be used to substitute the std identifiers, also.
namespace foo {
template <std::size_t S, typename... Ts>
struct aligned_union {
static constexpr std::size_t alignment_value =
std::max({alignof(Ts)...});
struct type {
alignas(alignment_value) char bytes[std::max({S, sizeof(Ts)...})];
};
};
template <typename T>
using aligned_storage [[gnu::aligned(alignof(T))]] = std::byte[sizeof(T)];
}
I'm going to start feeling like I'm nagging. 😃
As I'm replacing my own homegrown library with Vookoo in my own project, I am discovering a few features I had implemented and are not available.
One of them are shader specialization constants. I understand that not many people use them, but for me they allow me to write mini-uber-shaders to handle many of my cases (in scientific visualization, I may have a variable number of attributes and rather than writing one shader per case, the constant specialization allows me to write a single shader handling all cases).
In my own library, I had attached the specialization constants to the shader. In Vookoo, the role of that object is the ShaderModule
right now. The vku::ShaderModule
contains a vk::UniqueShaderModule.
Thus it seems a bit inappropriate to try to attach the specialization directly to the vku::ShaderModule. Since the same UniqueShaderModule
can be used with various values of the specialization constants.
The specialization variable values need to be given when the pipeline is built.
So I see taking one of two approaches:
PipelineMaker::shader()
methodUniqueShaderModule
in ShaderModule with a std::shared_ptr<UniqueShaderModule>
and using a specialize
method to create a lightweight SpecializedShaderModule
that is passed to PipelineMaker::shader()
Any comments/suggestions?
I realize that the vku_framework.hpp was intended as a way to easily get started with the examples.
However, I've been using it in a new project in which I want to be able to run more than one Vulkan driven window. Doing so, I discovered some weaknesses that for the most part can be remedied with a fairly limited amount of work. I am sure I will discover more issues to be worked on but here are the first things that come to mind:
graphicsQueue.submit(...)
. If the wrapper is used, then it is easy to write: graphicsQueueWrapper->submit(...)
. The operator->
of the wrapper returns an object that locks a mutex and has itself an operator->
that returns a pointer to the vk::Queue
. The object lifetime is guaranteed to encompass the time of the submission and then it is unlock right after. From a user's point of view, it comes at no added complexity.vku::Framework
should really behave like a singleton. It is easy to create two vku::Framework
by mistake and get a crash when one's destructor is called. This also helps in having a single mutex per actual queue (the graphics, compute and present queues can all be the same, yet vku::Window
obtains the presentation queue without reference to vku::Framework
while the user must obtain the graphics and compute queues from the vku::Framework
) .As of now, it is the first point that is important to my use case and I have already tested the wrapper solution.
Is that something of interest to other users?
I was wondering if vku could support multisampling as an option to enable.
I was thinking of modifying the vku frame work and following the vulkan tutorial for multisampling. However, it is proving to be rather difficult finding all the necessary interfaces in vku / framework.
Perhaps there is a simpler way?
In the example's cmake file, there's a line
target_include_directories(${order}-${exname} PRIVATE Vulkan::Vulkan)
To my knowledge, target_include_directories
only allows directory paths and not targets as arguments. I needed to move the Vulkan::Vulkan
dependency to target_link_libraries
in order to be able to compile the samples
I tried this library because it follows a similar approach I had followed in one of my projects but also is further along than I am in my project. So I would rather use this library and contribute to improving it than just continue with my code.
I work mostly on MacOS and discovered Vookoo when porting my app to Linux.
I went back to MacOS X and tried to run the Vookoo examples. However they do not run.
I have made some fixes and will submit a pull request for it. Modifications are limited to:
The last one brings my question before I submit a pull request:
Why are there glfw3 includes in this project instead of relying on the glfw3 installed on whatever machine? glfw3 does a correct install with the cmake files and a find_package(glfw3) should work correctly. With a modern CMake (possibly before 3.1.3 as required in the CMakeLists.txt), getting the include directory only requires the use of: target_link_libraries(${order}-${exname} glfw3)
which is in the CMakeLists.txt already.
I can check on Linux but have not yet tried on Windows, so if someone who is better versed in Windows than I am can chime in, I'd appreciate it.
PS: I guess I was also surprised to find in a github project that binary libraries are present in the repository. It is probably the reason why the glfw3 includes are there. However, why not include glfw3's source if Vookoo wants to install without any other external dependencies than Vulkan? This to me would be a satisfactory solution as well (and using git subrepo for including glfw3). The source of glfw3 is fairly small. I can put the git subrepo of glfw3 in my pull request or in a separate pull request.
https://github.com/timprepscius/Vookoo/branches
tjp_remove_forced_multiview__pipeline_maker_options
Hey there,
I've made some changes basically summed up as:
This allows more easily not having VK_KHR_MULTIVIEW_EXTENSION_NAME or Tessellation or GeometryShaders.
You will need to change bits of your code to have:
InstanceMaker im;
im
.extensionMultiview();
DeviceMaker dm;
dm
.extensionMultiview()
.physicalDeviceFeatures()
.enableGeometryShader()
.enableTessellationShader()
.multiviewFeatures()
.enableMultiview();
Framework framework(im, dm);
But your code will actually be more descriptive by doing this as well.
Thank you very much for your code, especially vku.hpp.
As I was putting the gflw source code in external directory, I ran the examples and got the following error for each frame drawn in the uniform example:
00000008 debugCallback: [ VUID-vkCmdPipelineBarrier-dstAccessMask-02816 ] Object: 0x7fe2c3a63928 (Type = 6) | vkCmdPipelineBarrier(): pBufferMemBarriers[0].dstAccessMask (0x20) is not supported by dstStageMask (0x1). The Vulkan spec states: The dstAccessMask member of each element of pMemoryBarriers must only include access flags that are supported by one or more of the pipeline stages in dstStageMask, as specified in the table of supported access types (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdPipelineBarrier-dstAccessMask-02816)
I use Vulkan-Hpp update to 1.1.85
in vku_framework.hpp at 294
I have change from
surface_ = vk::UniqueSurfaceKHR(surface, vk::SurfaceKHRDeleter{ instance }););
to
surface_ = vk::UniqueSurfaceKHR(surface, vk::ObjectDestroy<vk::Instance, vk::DispatchLoaderStatic>(instance));
otherwise, erasing the surface_ will cause a crash
Only want to let you know.
Steps to reproduce: install latest linux LunarG packages
wget -qO - http://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.1.121-bionic.list http://packages.lunarg.com/vulkan/1.1.121/lunarg-vulkan-1.1.121-bionic.list
sudo apt update
sudo apt install vulkan-sdk
Then try to compile the examples:
cmake ../examples/ && make
/home/steven/Software/Vookoo/examples/../include/vku/vku.hpp:31:10: fatal error: vulkan/spirv.hpp11: No such file or directory
#include <vulkan/spirv.hpp11>
This is because in the new lunarg SDK splits the spirv headers into a new project https://github.com/KhronosGroup/SPIRV-Headers
The new location for the headers in the lunarg sdk is spirv/<version>
find /usr/include -name spirv.hpp11
/usr/include/spirv/unified1/spirv.hpp11
/usr/include/spirv/1.2/spirv.hpp11
/usr/include/spirv/1.0/spirv.hpp11
/usr/include/spirv/1.1/spirv.hpp11
I've started to add installation capabilities to the Vookoo CMakeLists.
After a make install
, using Vookoo from a project entails adding to the CMakeLists:
find_package(Vookoo REQUIRED)
target_link_libraries(your_target Vookoo::vookoo_interface)
To my partial surprise, make install did install glfw and if one wants to use it (for example to run code like in the examples), one would have:
find_package(Vookoo REQUIRED)
find_package(glfw3 REQUIRED)
target_link_libraries(your_target Vookoo::vookoo_interface glfw)
Actually trying to do exactly that made me realize that the examples depend on glm.
I am not a fan of glm and think it is a big error to use it in Vulkan project if for no other reason that it is geared towards OpenGL y-upward view of the screen coordinate system while Vulkan is y-downward.
Should glm be installed? Ignored? Replaced by a vkm ?
Should I impede glfw3 from installing? Or install only if a find_package(glfw3) fails?
My current source can be found at: https://github.com/FunMiles/Vookoo/tree/installer
for (uint32_t qi = 0; qi != qprops.size(); ++qi) {
auto &qprop = qprops[qi];
VkBool32 presentSupport = false;
if (pd.getSurfaceSupportKHR(qi, surface_)) {
presentQueueFamily_ = qi;
found = true;
break;//here add break
}
}
I think the fixes in #49 now causes incompatibility with the old vulkan 1.2 headers. Now you get when you compile.
error: cannot decompose inaccessible member ‘vk::UniqueHandle<vk::Pipeline, vk::DispatchLoaderStatic>::m_value’ of ‘vk::UniqueHandle<vk::Pipeline, vk::DispatchLoaderStatic>’
More specifically, it appears that at least on Ubuntu 20.04, the Vulkan headers being installed look like
template<typename Dispatch>
VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type Device::createComputePipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
{
Pipeline pipeline;
Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkComputePipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelineUnique", deleter );
}
which returns ResultValueType
instead of just ResultValue
, which looks like
template <typename T>
struct ResultValueType
{
#ifdef VULKAN_HPP_NO_EXCEPTIONS
typedef ResultValue<T> type;
#else
typedef T type;
#endif
};
This is important because if you then do not define VULKAN_HPP_NO_EXCEPTIONS
which by default is not defined, the contained type, which in this case is UniqueHandle
would directly be forwarded, causing the structured binding breakage.
Given that structured binding for called results have not been used anywhere else in vku, I would say the assumption of the project is that VULKAN_HPP_NO_EXCEPTIONS
is not defined, so I think the change made in https://github.com/tomix1024/Vookoo/blob/2b0f8f218b634e43b976408968a440bf63e3bc8a/include/vku/vku.hpp#L1333 and https://github.com/tomix1024/Vookoo/blob/2b0f8f218b634e43b976408968a440bf63e3bc8a/include/vku/vku.hpp#L1041 should be reverted to be in line with all the other return call handles.
I am suggesting to put glfw under subrepo. This follows a short discussion at the end of the MacOS issue (and thanks, @andy-thomason for taking that PR in).
Following the discussion of subrepo in #19 :
I have a slight disagreement with @andy-thomason and @lhog view/comments on subrepo. One of the significant benefits of subrepo in this case is that users of Vookoo and in most cases developers as well, can ignore the existence of the subrepo.
Let's say we put glfw3 under subrepo, appart from having the source code clone, all it does is add a file '.gitrepo' in the external/GLFW directory. Cloning the complete vookoo with the glfw3 will download the complete vookoo code, including GLFW transparently. No need to install gitrepo for that. Unless you need to update the version of glfw3 or want to push a change to glfw3, you don't even have to know about subrepo. You don't have to have the subrepo software installed. I think that is one of the greatest strenghts of subrepo vs submodule.
So, @lhog, I think end-user experience is unaffected.
I will create a version/PR for it.
PS:
An auxiliary result of cloning glfw3 into external is that a CMakeLists in the main directory, (which can then install the header-only library vookoo library) is needed because one cannot use add_subdirectory to a sibling if it is not binary.
I was helping a friend compile and run code I wrote that uses Vookoo.
Vulkan was killing the job with an error message saying that validation layer 0 could not be found.
In installed the latest Vulkan distribution on Mac OS and hit the same problem. Further investigation shows that the string VK_LAYER_LUNARG_standard_validation has disappeared from the new Vulkan distribution.
PS: Comparing the two distributions (1.2.131.2 and 1.2.135.0), the last one does not have the file VkLayer_standard_validation.json. This file has the following content:
{
"file_format_version": "1.1.1",
"layer": {
"name": "VK_LAYER_LUNARG_standard_validation",
"type": "GLOBAL",
"api_version": "1.2.131",
"implementation_version": "1",
"description": "LunarG Standard Validation",
"component_layers": [
"VK_LAYER_KHRONOS_validation"
]
}
}
I also found a web page describing this validation layer as a convenience to load several layers in the optimal order.
PPS: the Godot project hit the same issue and seems to say that this convenience layer has been replaced by VK_LAYER_KHRONOS_validation. Indeed, replacing the layer name directly with the new name fixes the issue.
This leaves me with the question of whether Vookoo should accept to run even if it can't find those validation layers?
I came across this library today and it seems to be quite promising.
With the current version of the Vulkan-Hpp headers, the return type of vku::PipelineMaker::createUnique
and vk::Device::createGraphicsPipelineUnique
mismatches.
I'd suggest to change the return value of (all) those functions to auto
in order to avoid future incompatibilities between the APIs.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.