#include <renderservice.h>
Classes | |
struct | Pipeline |
Public Types | |
using | SortFunction = std::function< void(std::vector< RenderableComponentInstance * > &, const glm::mat4 &viewMatrix)> |
using | VulkanObjectDestructor = std::function< void(RenderService &)> |
using | RenderCommand = std::function< void(RenderService &)> |
Public Attributes | |
nap::Signal< nap::RenderWindow & > | windowAdded |
nap::Signal< nap::RenderWindow & > | windowRemoved |
Protected Member Functions | |
virtual void | getDependentServices (std::vector< rtti::TypeInfo > &dependencies) override |
virtual bool | init (nap::utility::ErrorState &errorState) override |
virtual void | preShutdown () override |
virtual void | shutdown () override |
virtual void | preResourcesLoaded () override |
virtual void | postResourcesLoaded () override |
virtual void | update (double deltaTime) override |
![]() | |
virtual void | registerObjectCreators (rtti::Factory &factory) |
virtual void | created () |
virtual void | preUpdate (double deltaTime) |
virtual void | postUpdate (double deltaTime) |
template<typename SERVICE_CONFIG > | |
SERVICE_CONFIG * | getConfiguration () |
template<typename SERVICE_CONFIG > | |
const SERVICE_CONFIG * | getConfiguration () const |
std::string | getIniFilePath () const |
std::string | getIniFilePath (const std::string &appendix) const |
Main interface for Vulkan Render (2D/3D) and Vulkan Compute operations.
This service initializes the Vulkan back-end and provides an interface to render objects to a specific target (screen or back-buffer). The service is shut down automatically on exit, and destroys all left over resources. When rendering geometry the service automatically sorts your selection based on the blend mode of the material. Opaque objects are rendered front to back, alpha blended objects are rendered back to front.
By default headless rendering is turned off. This means Vulkan is setup to display the result of a render operation in a nap::RenderWindow, next to a nap::RenderTarget. This requires a display device to be connected to the system. Enable headless rendering when you do NOT want to render to a window or when there is no display attached to the system. This in turn forbids the use of a nap::RenderWindow inside your application.
When headless rendering is enabled, the engine will be initialized without surface and swapchain support, which are required by a nap::RenderWindow to display images on screen. You can therefore only render to a nap::RenderTarget when Headless rendering is enabled.
Turn headless rendering on / off using the nap::RenderServiceConfiguration.
The service creates a Vulkan 1.0 instance by default, but applications may use Vulkan 1.1 and 1.2 functionality if required. Make sure to set the required major and minor Vulkan version accordingly using the RenderServiceConfiguration. The application will not start if the device does not support the selected (and therefore required) version of Vulkan.
The following Vulkan device extensions are always required: VK_KHR_MAINTENANCE1_EXTENSION. When rendering to a window, the VK_KHR_SWAPCHAIN_EXTENSION is also required. Additional extension can be specified using the nap::RenderServiceConfiguration.
The system will try to load the requested validation layers in debug mode only. Use the RenderServiceConfiguration to specify which layers the Vulkan loader should attempt to load. A warning is issued when the validation layer can't be located or loaded. Validation layers are disabled in release mode.
For more information on setting up validation layers refer to: https://vulkan.lunarg.com/doc/view/1.2.131.2/windows/layer_configuration.html
On initialization the service will try to choose a physical device based on the preferred GPU type. If no compatible GPU is found (even a not-preferred one) the system will fail to initialize. Most dedicated and integrated GPUs are supported.
using RenderCommand = std::function<void(RenderService&)> |
using SortFunction = std::function<void(std::vector<RenderableComponentInstance*>&, const glm::mat4& viewMatrix)> |
using VulkanObjectDestructor = std::function<void(RenderService&)> |
RenderService | ( | ServiceConfiguration * | configuration | ) |
Creates the service together with the provided configuration settings.
configuration | render engine configuration. |
|
virtual |
void addEvent | ( | WindowEventPtr | windowEvent | ) |
Add a window event that is processed later, ownership is transferred here. The window number in the event is used to find the right render window to forward the event to.
windowEvent | the window event to add. |
bool addWindow | ( | RenderWindow & | window, |
utility::ErrorState & | errorState | ||
) |
Add a new window as target to the render engine.
window | the window to add as a valid render target |
errorState | contains the error message if the window could not be added |
bool anisotropicFilteringSupported | ( | ) | const |
Returns if anisotropic filtering is supported
bool beginComputeRecording | ( | ) |
Starts a compute operation. Records any queued compute render commands. Call this when you want to start recording general purpose computate operations to the compute queue. Always call RenderService::endComputeRecording() afterwards, on success. Must be called before any (headless) rendering has been recorded in the current frame.
void beginFrame | ( | ) |
Tells the system you are about to render a new frame. The system might wait until all commands issued previously, associated with the same frame handle (fence), have been processed. Multiple frames are in flight at the same time, but if the graphics load is heavy, the system might wait here to ensure resources are available. Pending upload requests are executed. Previously issued download requests are checked for completion. Queued resources that are out of scope are destroyed.
Call this function at the beginning of the render loop, before any RenderService::beginRecording() calls. Make sure to call RenderService::endFrame() after all recording operations are finished, at the end of the render loop.
bool beginHeadlessRecording | ( | ) |
Starts a headless render operation. Records any queued headless render commands. Call this when you want to render objects to a render-target instead of a render window. Make sure to call RenderService::endHeadlessRecording() afterwards.
bool beginRecording | ( | RenderWindow & | renderWindow | ) |
Starts a window render operation. Call this when you want to render geometry to a render window. Always call RenderService::endRecording() afterwards, on success.
void computeObjects | ( | const std::vector< ComputeComponentInstance * > & | comps | ) |
Calls onCompute() on a specific set of compute component instances, in the order specified.
comps | the compute components to call onCompute |
RenderableMesh createRenderableMesh | ( | IMesh & | mesh, |
MaterialInstance & | materialInstance, | ||
utility::ErrorState & | errorState | ||
) |
Creates a renderable mesh, that represents the coupling between a mesh and material, that can be rendered to screen. Internally the renderable mesh manages a vertex array object that is issued by the render service. This function should be called from on initialization of components that work with meshes and materials: ie: all types of RenderableComponent. The result should be validated by calling RenderableMesh.isValid(). Invalid mesh / material representations can't be rendered together.
mesh | The mesh that is used in the mesh-material combination. |
materialInstance | The material instance that is used in the mesh-material combination. |
errorState | If this function returns an invalid renderable mesh, the error state contains error information. |
void endComputeRecording | ( | ) |
Ends a compute operation, submits the recorded compute command buffer to the compute queue. Always call this function after a successful call to nap::RenderService::beginComputeRecording().
void endFrame | ( | ) |
Tells the system you finished rendering into the frame. Always call this at the end of the render() loop, after RenderService::beginFrame(). Failure to properly end the frame will result in a system freeze. Any pending download requests are pushed onto the command buffer.
void endHeadlessRecording | ( | ) |
Ends a headless render operation, submits the recorded command buffer to the queue. Always call this function after a successful call to nap::RenderService::beginHeadlessRecording().
void endRecording | ( | ) |
Ends a window render operation, submits the recorded command buffer to the queue. Always call this function after a successful call to nap::RenderService::beginRecording().
std::vector<RenderableComponentInstance*> filterObjects | ( | const std::vector< RenderableComponentInstance * > & | comps, |
RenderMask | renderMask | ||
) |
Filters list of renderable components with the specified render mask.
comps | the render components to filter |
renderMask | the render mask used to filter |
const Display* findDisplay | ( | const nap::RenderWindow & | window | ) | const |
Returns the display that contains the center of the window.
const Display* findDisplay | ( | int | index | ) | const |
Find a display based on the index provided. Note that changes to display configuration are not considered when application is running.
index | the number of the display to find |
RenderWindow* findWindow | ( | uint | id | ) | const |
Find a RenderWindow based on a window number.
id | the number of the window to find. |
RenderWindow* findWindow | ( | void * | nativeWindow | ) | const |
Find a RenderWindowResource by its native handle
nativeWindow | the native window handle (i.e. the SDL_Window pointer) |
uint32 getAnisotropicSamples | ( | ) | const |
Returns the (system default) number of anisotropic filter samples. The output is always 1 when anisotropic filtering is not supported.
VkCommandPool getCommandPool | ( | ) | const |
Returns a handle to the Vulkan command pool object. Command pools are opaque objects that command buffer memory is allocated from.
VkCommandBuffer getCurrentCommandBuffer | ( | ) |
Returns the command buffer that is being recorded. Every window records into it's own command buffer. All headless render operations share the same command buffer. The current command buffer is set after nap::beginHeadlessRecording() or nap::beginRecording(RenderWindow&) and only valid until the recording operation is ended.
int getCurrentFrameIndex | ( | ) | const |
Returns the index of the frame that is currently rendered. This index controls which command buffer is recorded and is therefore capped to the max number of images in flight.
RenderWindow* getCurrentRenderWindow | ( | ) |
Returns the window that is being rendered to, only valid between a successfull call to: RenderService::beginRecording() and RenderService::endRecording().
|
overrideprotectedvirtual |
Register dependencies, render module depends on scene
Reimplemented from Service.
VkImageAspectFlags getDepthAspectFlags | ( | ) | const |
VkFormat getDepthFormat | ( | ) | const |
Returns the selected and currently in use depth format.
VkDevice getDevice | ( | ) | const |
Returns the handle to the logical Vulkan device, represents the hardware together with the extensions, selected queue and features enabled for it.
int getDisplayCount | ( | ) | const |
Returns the total number of displays. Note that changes to display configuration are not considered when application is running.
const DisplayList& getDisplays | ( | ) | const |
Texture2D& getEmptyTexture2D | ( | ) | const |
Returns an empty 2D texture that is available on the GPU for temporary binding or storage.
TextureCube& getEmptyTextureCube | ( | ) | const |
Returns an error cube texture that can be bound to materials to signal an application warning or error.
Texture2D& getErrorTexture2D | ( | ) | const |
Returns an error 2D texture that can be bound to materials to signal an application warning or error.
TextureCube& getErrorTextureCube | ( | ) | const |
Returns an empty cube texture that is available on the GPU for temporary binding or storage.
void getFormatProperties | ( | VkFormat | format, |
VkFormatProperties & | outProperties | ||
) | const |
Returns the physical device properties for the requested Vulkan format.
bool getHighDPIEnabled | ( | ) | const |
Configurable setting. When enabled fonts and general scaling is adjusted for high dpi monitors.
bool getLargePointsSupported | ( | ) | const |
Returns if rendering large points is supported.
glm::uvec3 getMaxComputeWorkGroupSize | ( | ) | const |
Returns the max compute shader workgroup size.
int getMaxFramesInFlight | ( | ) | const |
Returns the max number of frames in flight. If there is only 1 frame in flight the application will stall until it is rendered. Having multiple frames in flight at once allows the render engine to start on a new frame without having to wait on the previous one to finish.
Increasing the number of frames in flight does however have a negative impact on resource usage, because every frame requires its own unique set of command buffers, descriptor sets etc. 2 is therefore a good number, where 3 offers only, in most situations, a slight increase in performance. This however greatly depends on the application GPU and CPU load.
VkSampleCountFlagBits getMaxRasterizationSamples | ( | ) | const |
Returns the max number of hardware supported rasterization samples.
bool getNonSolidFillSupported | ( | ) | const |
Returns if point and wire-frame rasterization fill modes are supported.
Pipeline getOrCreateComputePipeline | ( | const ComputeMaterialInstance & | computeMaterialInstance, |
utility::ErrorState & | errorState | ||
) |
Returns a Vulkan compute pipeline for the given compute material. Internally pipelines are cached, a new compute pipeline is created when a new compute material is encountered. Because of this, initial frames are slower to render, until all compute materials are cached and returned from the pool. Pipeline creation is considered to be a heavy operation, take this into account when designing your application.
Use this function inside nap::ComputeComponentInstance::onCompute() to find the right pipeline before dispatching a compute shader.
computeMaterialInstance | the compute material instance |
errorState | contains the error if the pipeline can't be created |
DescriptorSetCache& getOrCreateDescriptorSetCache | ( | VkDescriptorSetLayout | layout | ) |
Returns a descriptor set cache based on the given layout. The cache is used to acquire descriptor sets.
layout | the descriptor set layout to create the cache for. |
Material* getOrCreateMaterial | ( | rtti::TypeInfo | shaderType, |
utility::ErrorState & | error | ||
) |
Returns an existing or new material for the given type of shader that can be shared. This only works for hard coded shader types that can be initialized without input arguments. If initialization or creation fails, the result is cached but invalid. Use the material as a template for a material instance.
shaderType | type of shader to get material for. |
error | contains the error if the material could not be created or initialized. |
Material* getOrCreateMaterial | ( | utility::ErrorState & | error | ) |
Returns an existing or new material for the given type of shader T that can be shared. This only works for hard coded shader types that can be initialized without input arguments. If initialization or creation fails, the result is cached but invalid. Use the material as a template for a material instance.
error | contains the error if the material could not be created or initialized. |
Pipeline getOrCreatePipeline | ( | const IRenderTarget & | renderTarget, |
const IMesh & | mesh, | ||
const MaterialInstance & | materialInstance, | ||
utility::ErrorState & | errorState | ||
) |
Returns a Vulkan pipeline for the given render target, mesh and material combination. Internally pipelines are cached, a new pipeline is created when a new combination is encountered. Because of this, initial frames are slower to render, until all combinations are cached and returned from the pool. Pipeline creation is considered to be a heavy operation, take this into account when designing your application.
Use this function inside nap::RenderableComponentInstance::onDraw() to find the right pipeline before rendering.
renderTarget | target that is rendered too. |
mesh | the mesh that is drawn. |
materialInstance | the material applied to the mesh. |
errorState | contains the error if the pipeline can't be created |
Pipeline getOrCreatePipeline | ( | const IRenderTarget & | renderTarget, |
const RenderableMesh & | renderableMesh, | ||
utility::ErrorState & | errorState | ||
) |
Returns a Vulkan pipeline for the given render target and Renderable-mesh combination. Internally pipelines are cached, a new pipeline is created when a new combination is encountered. Because of this initial frames are slower to render, until all combinations are cached and returned from the pool. Pipeline creation is considered to be a heavy operation, take this into account when designing your application.
Use this function inside nap::RenderableComponentInstance::onDraw() to find the right pipeline before rendering.
renderTarget | target that is rendered too. |
renderableMesh | the mesh / material combination that is rendered |
errorState | contains the error if the pipeline can't be created |
VkPhysicalDevice getPhysicalDevice | ( | ) | const |
Returns the physical device (GPU) that is used for all render operations. Multiple physical devices are not supported.
const VkPhysicalDeviceFeatures& getPhysicalDeviceFeatures | ( | ) | const |
Returns all supported physical device (GPU) features.
const VkPhysicalDeviceProperties& getPhysicalDeviceProperties | ( | ) | const |
All physical device hardware properties.
uint32 getPhysicalDeviceVersion | ( | ) | const |
Returns the Vulkan api version, as supported by the physical device. Note that this is not the same as the api version used by the render engine. The physical device needs to support the min required api version requested by the render engine, but could be higher.
bool getPolygonModeSupported | ( | EPolygonMode | mode | ) |
Checks if the selected polygon mode is supported by current selected device.
mode | the mode to check. |
VkQueue getQueue | ( | ) | const |
Returns the selected queue, used to execute recorded command buffers. The queue must support Graphics and Transfer operations.
uint32 getQueueIndex | ( | ) | const |
Returns the index of the selected queue family.
int getRank | ( | const nap::RenderLayer & | layer | ) | const |
Returns the rank of the given layer in the render chain. Asserts and returns RenderChain::invalidRank
if the rank is not registered. The rank controls the order in which objects are rendered.
layer | the layer to get the rank index for |
bool getRasterizationSamples | ( | ERasterizationSamples | requestedSamples, |
VkSampleCountFlagBits & | outSamples, | ||
nap::utility::ErrorState & | errorState | ||
) |
Returns max supported rasterization samples based on the requested number of samples. The output is automatically clamped if the requested number of samples exceeds the hardware limit.
requestedSamples | requested number of samples. |
outSamples | supported number of samples. |
errorState | contains the error if requested number of samples is not supported by the hardware. |
RenderMask getRenderMask | ( | const RenderTag & | renderTag | ) | const |
Returns the render mask for the given tag.
RenderMask getRenderMask | ( | const std::string & | tagName | ) |
Returns the render mask for the given render tag name, 0 if no match is found.
tagName | name of the render tag |
VmaAllocator getVulkanAllocator | ( | ) | const |
VkInstance getVulkanInstance | ( | ) | const |
Returns the Vulkan runtime instance.
uint32 getVulkanVersion | ( | ) | const |
Returns the api version used to create the Vulkan instance. Note that the physical device is required to support at least that version.
uint32 getVulkanVersionMajor | ( | ) | const |
Returns the major api version used to create the Vulkan instance. The vulkan instance is created using a combination of the major and minor api version. Note that the physical device is required to support at least that version.
uint32 getVulkanVersionMinor | ( | ) | const |
Returns the minor api version used to create the Vulkan instance. The vulkan instance is created using a combination of the major and minor api version. Note that the physical device is required to support at least that version.
bool getWideLinesSupported | ( | ) | const |
Returns if wide line rendering is supported, if so you can use a line width higher than 1.
|
overrideprotectedvirtual |
Initialize the renderer, the service owns the renderer.
errorState | contains the error message if the service could not be initialized |
Reimplemented from Service.
bool initShaderCompilation | ( | utility::ErrorState & | error | ) |
Initializes GLSL shader compilation and linking. Don't call this in your application! Only required by external processes that want to use the nap render interface.
error | contains the error if initialization fails |
bool isComputeAvailable | ( | ) | const |
Returns true if the selected device has compute capability, else returns false.
bool isComputeCommandQueued | ( | ) | const |
bool isHeadless | ( | ) | const |
Returns if the render engine runs headless. This allows you to render images without any display device. This in turn means that when enabled it is not possible to display (present) images to a window.
bool isHeadlessCommandQueued | ( | ) | const |
bool isInitialized | ( | ) | const |
Returns if the render service is running, a non operational render service is in an undefined state and can therefore not be queried
bool isRenderingFrame | ( | ) | const |
Returns if the render service is currently recording (rendering) a frame. Returns true in between start and end frame calls, otherwise false. If that is the case, certain operations are not allowed. For example: data upload / download operations to and from the GPU are forbidden.
|
overrideprotectedvirtual |
Invoked when the resource manager is about to load resources.
Reimplemented from Service.
|
overrideprotectedvirtual |
Invoked when the resource manager is about to load resources.
Reimplemented from Service.
|
overrideprotectedvirtual |
Waits for the device to be idle and deletes queued resources.
Reimplemented from Service.
void queueComputeCommand | ( | const RenderCommand & | command | ) |
Queues a compute render command with priority in the subsequent frame. The queue is handled the next time RenderService::beginComputeRecording
is called.
command | the command to queue, ownership is transferred |
void queueHeadlessCommand | ( | const RenderCommand & | command | ) |
Queues a headless render command with priority in the subsequent frame. The queue is handled the next time RenderService::beginHeadlessRecording
is called.
command | the command to queue, ownership is transferred |
void queueVulkanObjectDestructor | ( | const VulkanObjectDestructor & | function | ) |
Queues a function that destroys Vulkan resources when appropriate. Certain Vulkan resources, including buffers, image buffers etc. might still be in use when the NAP resource is destroyed. It is therefore necessary to queue their destruction, instead of deleting them immediately. Make sure that all resources are captured by copy, instead of reference.
void removeWindow | ( | RenderWindow & | window | ) |
Remove a window as a valid target from the render engine.
window | the window to remove from the render service |
void renderObjects | ( | IRenderTarget & | renderTarget, |
CameraComponentInstance & | camera, | ||
const SortFunction & | sortFunction, | ||
RenderMask | = mask::all |
||
) |
Renders all available nap::RenderableComponent(s) in the scene to a specific renderTarget. The objects to render are sorted using the provided sort function. Components that can't be rendered with the given camera are omitted.
renderTarget | the target to render to |
camera | the camera used for rendering all the available components |
sortFunction | The function used to sort the components to render |
void renderObjects | ( | IRenderTarget & | renderTarget, |
CameraComponentInstance & | camera, | ||
const std::vector< RenderableComponentInstance * > & | comps, | ||
const SortFunction & | sortFunction, | ||
RenderMask | renderMask = mask::all |
||
) |
Renders a specific set of objects to a specific renderTarget using an optional mask The objects to render are sorted using the provided sort function. Components that can't be rendered with the given camera are omitted.
renderTarget | the target to render to |
camera | the camera used for rendering all the available components |
comps | the components to render to renderTarget |
sortFunction | The function used to sort the components to render |
renderMask | optional component filter mask |
void renderObjects | ( | IRenderTarget & | renderTarget, |
CameraComponentInstance & | camera, | ||
const std::vector< RenderableComponentInstance * > & | comps, | ||
RenderMask | renderMask = mask::all |
||
) |
Renders a specific set of objects to a specific renderTarget using an optional mask The objects to render are sorted using the default sort function (front-to-back for opaque objects, back-to-front for transparent objects) The sort function is provided by the render service itself, using the default NAP DepthSorter.
renderTarget | the target to render to |
camera | the camera used for rendering all the available components |
comps | the components to render to renderTarget |
renderMask | optional component filter mask |
void renderObjects | ( | IRenderTarget & | renderTarget, |
CameraComponentInstance & | camera, | ||
RenderMask | renderMask = mask::all |
||
) |
Renders all available nap::RenderableComponent(s) in the scene to a specific renderTarget. The objects to render are sorted using the default sort function (front-to-back for opaque objects, back-to-front for transparent objects). The sort function is provided by the render service itself, using the default NAP DepthSorter. Components that can't be rendered with the given camera are omitted.
renderTarget | the target to render to |
camera | the camera used for rendering all the available components |
renderMask | the objects to include |
void renderObjects | ( | IRenderTarget & | renderTarget, |
const glm::mat4 & | projection, | ||
const glm::mat4 & | view, | ||
const std::vector< RenderableComponentInstance * > & | comps, | ||
const SortFunction & | sortFunction, | ||
RenderMask | renderMask = mask::all |
||
) |
Renders a specific set of objects to a specific renderTarget using a specific projection and view matrix and optional mask. The objects to render are sorted using the provided sort function. Components that can't be rendered with the given camera are omitted.
renderTarget | the target to render to |
projection | the camera projection matrix |
view | the camera view matrix |
comps | the components to render to renderTarget |
sortFunction | The function used to sort the components to render |
renderMask | optional component filter mask |
bool sampleShadingSupported | ( | ) | const |
Returns if sample shading is supported and enabled, reduces texture aliasing at computational cost.
|
overrideprotectedvirtual |
Shuts down the renderer, local Vulkan resources are destroyed.
Reimplemented from Service.
|
overrideprotectedvirtual |
Process all received window events.
deltaTime | time in seconds in between frames. |
Reimplemented from Service.
void waitForFence | ( | int | frameIndex | ) |
Wait for the fence belonging to the specified frame index. This ensures that, after the wait, all resources for that frame are no longer in use. You normally don't need to use this as all synchronization is handled for you. This function is only used by RenderWindow to ensure that the current swap chain image is no longer in use.
frameIndex | The index of the frame to wait for |
nap::Signal<nap::RenderWindow&> windowAdded |
Called when a new window is added to the system
nap::Signal<nap::RenderWindow&> windowRemoved |
Called just before a window is removed from the system