vulkan: add an overlay layer
Just a starting point to display frame timings & drawcalls/submissions per frame. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Acked-by: Jason Ekstrand <jason@jlekstrand.net> +1-by: Mike Lothian <mike@fireburn.co.uk> +1-by: Tapani Pälli <tapani.palli@intel.com> +1-by: Eric Engestrom <eric.engestrom@intel.com> +1-by: Yurii Kolesnykov <root@yurikoles.com> +1-by: myfreeweb <greg@unrelenting.technology> +1-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
parent
89f03d1872
commit
20c370c6b1
|
@ -167,6 +167,12 @@ option(
|
||||||
value : '',
|
value : '',
|
||||||
description : 'Location relative to prefix to put vulkan icds on install. Default: $datadir/vulkan/icd.d'
|
description : 'Location relative to prefix to put vulkan icds on install. Default: $datadir/vulkan/icd.d'
|
||||||
)
|
)
|
||||||
|
option(
|
||||||
|
'vulkan-overlay-layer',
|
||||||
|
type : 'boolean',
|
||||||
|
value : false,
|
||||||
|
description : 'Whether to build the vulkan overlay layer'
|
||||||
|
)
|
||||||
option(
|
option(
|
||||||
'shared-glapi',
|
'shared-glapi',
|
||||||
type : 'boolean',
|
type : 'boolean',
|
||||||
|
|
|
@ -9,6 +9,14 @@ MKDIR_GEN = $(AM_V_at)$(MKDIR_P) $(@D)
|
||||||
PYTHON_GEN = $(AM_V_GEN)$(PYTHON) $(PYTHON_FLAGS)
|
PYTHON_GEN = $(AM_V_GEN)$(PYTHON) $(PYTHON_FLAGS)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
overlay-layer/README \
|
||||||
|
overlay-layer/meson.build \
|
||||||
|
overlay-layer/overlay.cpp \
|
||||||
|
overlay-layer/overlay.frag \
|
||||||
|
overlay-layer/overlay.vert \
|
||||||
|
overlay-layer/VkLayer_MESA_overlay.json.in \
|
||||||
|
overlay-layer/vk_layer_table.cpp \
|
||||||
|
overlay-layer/vk_layer_table.h \
|
||||||
util/gen_enum_to_str.py \
|
util/gen_enum_to_str.py \
|
||||||
util/meson.build \
|
util/meson.build \
|
||||||
wsi/meson.build \
|
wsi/meson.build \
|
||||||
|
|
|
@ -25,3 +25,6 @@ inc_vulkan_wsi = include_directories('wsi')
|
||||||
|
|
||||||
subdir('util')
|
subdir('util')
|
||||||
subdir('wsi')
|
subdir('wsi')
|
||||||
|
if get_option('vulkan-overlay-layer')
|
||||||
|
subdir('overlay-layer')
|
||||||
|
endif
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
A Vulkan layer to display information about the running application
|
||||||
|
using an overlay.
|
||||||
|
|
||||||
|
To turn on the layer run :
|
||||||
|
```
|
||||||
|
VK_INSTANCE_LAYERS=VK_LAYER_MESA_overlay /path/to/my_vulkan_app
|
||||||
|
```
|
||||||
|
|
||||||
|
List the available statistics :
|
||||||
|
```
|
||||||
|
VK_INSTANCE_LAYERS=VK_LAYER_MESA_overlay VK_LAYER_MESA_OVERLAY_STATS=help /path/to/my_vulkan_app
|
||||||
|
```
|
||||||
|
|
||||||
|
Turn on some statistics :
|
||||||
|
```
|
||||||
|
VK_INSTANCE_LAYERS=VK_LAYER_MESA_overlay VK_LAYER_MESA_OVERLAY_STATS=submit,draw,pipeline-graphics /path/to/my_vulkan_app
|
||||||
|
```
|
||||||
|
|
||||||
|
Position the layer :
|
||||||
|
```
|
||||||
|
VK_INSTANCE_LAYERS=VK_LAYER_MESA_overlay VK_LAYER_MESA_OVERLAY_STATS=submit,draw,pipeline-graphics VK_LAYER_MESA_OVERLAY_POSITION=top-right /path/to/my_vulkan_app
|
||||||
|
```
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"file_format_version" : "1.0.0",
|
||||||
|
"layer" : {
|
||||||
|
"name": "VK_LAYER_MESA_overlay",
|
||||||
|
"type": "GLOBAL",
|
||||||
|
"library_path": "@install_dir@/libVkLayer_MESA_overlay.so",
|
||||||
|
"api_version": "1.1.73",
|
||||||
|
"implementation_version": "1",
|
||||||
|
"description": "Mesa Overlay layer"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
# Copyright © 2019 Intel Corporation
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
vklayer_install_dir = join_paths(get_option('prefix'), 'share', 'vulkan', 'explicit_layer.d')
|
||||||
|
|
||||||
|
glslang = find_program('glslangValidator')
|
||||||
|
|
||||||
|
overlay_shaders = [
|
||||||
|
'overlay.frag',
|
||||||
|
'overlay.vert',
|
||||||
|
]
|
||||||
|
overlay_spv = []
|
||||||
|
foreach s : ['overlay.frag', 'overlay.vert']
|
||||||
|
overlay_spv += custom_target(
|
||||||
|
s + '.spv.h', input : s, output : s + '.spv.h',
|
||||||
|
command : [glslang, '-V', '-x', '-o', '@OUTPUT@', '@INPUT@'])
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
vklayer_files = files(
|
||||||
|
'overlay.cpp',
|
||||||
|
'vk_layer_table.cpp',
|
||||||
|
)
|
||||||
|
|
||||||
|
vklayer_mesa_overlay = shared_library(
|
||||||
|
'VkLayer_MESA_overlay',
|
||||||
|
vklayer_files, overlay_spv,
|
||||||
|
c_args : [c_vis_args, no_override_init_args],
|
||||||
|
cpp_args : [cpp_vis_args],
|
||||||
|
dependencies : [libimgui_core_dep, dep_dl],
|
||||||
|
include_directories : [inc_common, inc_vulkan_util],
|
||||||
|
link_args : cc.get_supported_link_arguments(['-Wl,-Bsymbolic-functions', '-Wl,-z,relro']),
|
||||||
|
link_with : [libmesa_util, libvulkan_util],
|
||||||
|
install_dir : vklayer_install_dir,
|
||||||
|
)
|
||||||
|
|
||||||
|
sdata = configuration_data()
|
||||||
|
sdata.set('install_dir', vklayer_install_dir)
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
input : 'VkLayer_MESA_overlay.json.in',
|
||||||
|
output : '@BASENAME@',
|
||||||
|
configuration : sdata,
|
||||||
|
install_dir : vklayer_install_dir,
|
||||||
|
install : true
|
||||||
|
)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,14 @@
|
||||||
|
#version 450 core
|
||||||
|
layout(location = 0) out vec4 fColor;
|
||||||
|
|
||||||
|
layout(set=0, binding=0) uniform sampler2D sTexture;
|
||||||
|
|
||||||
|
layout(location = 0) in struct{
|
||||||
|
vec4 Color;
|
||||||
|
vec2 UV;
|
||||||
|
} In;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
fColor = In.Color * texture(sTexture, In.UV.st);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#version 450 core
|
||||||
|
layout(location = 0) in vec2 aPos;
|
||||||
|
layout(location = 1) in vec2 aUV;
|
||||||
|
layout(location = 2) in vec4 aColor;
|
||||||
|
|
||||||
|
layout(push_constant) uniform uPushConstant{
|
||||||
|
vec2 uScale;
|
||||||
|
vec2 uTranslate;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
out gl_PerVertex{
|
||||||
|
vec4 gl_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) out struct{
|
||||||
|
vec4 Color;
|
||||||
|
vec2 UV;
|
||||||
|
} Out;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Out.Color = aColor;
|
||||||
|
Out.UV = aUV;
|
||||||
|
gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1);
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/* Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||||
|
* Copyright (c) 2015-2016 Valve Corporation
|
||||||
|
* Copyright (c) 2015-2016 LunarG, Inc.
|
||||||
|
* Copyright (c) 2015-2016 Google, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Author: Tobin Ehlis <tobin@lunarg.com>
|
||||||
|
*/
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "vk_dispatch_table_helper.h"
|
||||||
|
#include "vulkan/vk_layer.h"
|
||||||
|
#include "vk_layer_table.h"
|
||||||
|
static device_table_map tableMap;
|
||||||
|
static instance_table_map tableInstanceMap;
|
||||||
|
|
||||||
|
// Map lookup must be thread safe
|
||||||
|
VkLayerDispatchTable *device_dispatch_table(void *object) {
|
||||||
|
dispatch_key key = get_dispatch_key(object);
|
||||||
|
device_table_map::const_iterator it = tableMap.find((void *)key);
|
||||||
|
assert(it != tableMap.end() && "Not able to find device dispatch entry");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkLayerInstanceDispatchTable *instance_dispatch_table(void *object) {
|
||||||
|
dispatch_key key = get_dispatch_key(object);
|
||||||
|
instance_table_map::const_iterator it = tableInstanceMap.find((void *)key);
|
||||||
|
assert(it != tableInstanceMap.end() && "Not able to find instance dispatch entry");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_dispatch_table(device_table_map &map, dispatch_key key) {
|
||||||
|
device_table_map::const_iterator it = map.find((void *)key);
|
||||||
|
if (it != map.end()) {
|
||||||
|
delete it->second;
|
||||||
|
map.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_dispatch_table(instance_table_map &map, dispatch_key key) {
|
||||||
|
instance_table_map::const_iterator it = map.find((void *)key);
|
||||||
|
if (it != map.end()) {
|
||||||
|
delete it->second;
|
||||||
|
map.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); }
|
||||||
|
|
||||||
|
void destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); }
|
||||||
|
|
||||||
|
VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object) {
|
||||||
|
dispatch_key key = get_dispatch_key(object);
|
||||||
|
device_table_map::const_iterator it = map.find((void *)key);
|
||||||
|
assert(it != map.end() && "Not able to find device dispatch entry");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object) {
|
||||||
|
dispatch_key key = get_dispatch_key(object);
|
||||||
|
instance_table_map::const_iterator it = map.find((void *)key);
|
||||||
|
assert(it != map.end() && "Not able to find instance dispatch entry");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) {
|
||||||
|
VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
|
||||||
|
while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
|
||||||
|
chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext;
|
||||||
|
}
|
||||||
|
assert(chain_info != NULL);
|
||||||
|
return chain_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) {
|
||||||
|
VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext;
|
||||||
|
while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
|
||||||
|
chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext;
|
||||||
|
}
|
||||||
|
assert(chain_info != NULL);
|
||||||
|
return chain_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Various dispatchable objects will use the same underlying dispatch table if they
|
||||||
|
* are created from that "parent" object. Thus use pointer to dispatch table
|
||||||
|
* as the key to these table maps.
|
||||||
|
* Instance -> PhysicalDevice
|
||||||
|
* Device -> CommandBuffer or Queue
|
||||||
|
* If use the object themselves as key to map then implies Create entrypoints have to be intercepted
|
||||||
|
* and a new key inserted into map */
|
||||||
|
VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) {
|
||||||
|
VkLayerInstanceDispatchTable *pTable;
|
||||||
|
dispatch_key key = get_dispatch_key(instance);
|
||||||
|
instance_table_map::const_iterator it = map.find((void *)key);
|
||||||
|
|
||||||
|
if (it == map.end()) {
|
||||||
|
pTable = new VkLayerInstanceDispatchTable;
|
||||||
|
map[(void *)key] = pTable;
|
||||||
|
} else {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
layer_init_instance_dispatch_table(instance, pTable, gpa);
|
||||||
|
|
||||||
|
// Setup func pointers that are required but not externally exposed. These won't be added to the instance dispatch table by
|
||||||
|
// default.
|
||||||
|
pTable->GetPhysicalDeviceProcAddr = (PFN_GetPhysicalDeviceProcAddr)gpa(instance, "vk_layerGetPhysicalDeviceProcAddr");
|
||||||
|
|
||||||
|
return pTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) {
|
||||||
|
return initInstanceTable(instance, gpa, tableInstanceMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) {
|
||||||
|
VkLayerDispatchTable *pTable;
|
||||||
|
dispatch_key key = get_dispatch_key(device);
|
||||||
|
device_table_map::const_iterator it = map.find((void *)key);
|
||||||
|
|
||||||
|
if (it == map.end()) {
|
||||||
|
pTable = new VkLayerDispatchTable;
|
||||||
|
map[(void *)key] = pTable;
|
||||||
|
} else {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
layer_init_device_dispatch_table(device, pTable, gpa);
|
||||||
|
|
||||||
|
return pTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) {
|
||||||
|
return initDeviceTable(device, gpa, tableMap);
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||||
|
* Copyright (c) 2015-2016 Valve Corporation
|
||||||
|
* Copyright (c) 2015-2016 LunarG, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Author: Tobin Ehlis <tobin@lunarg.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vulkan/vk_layer.h"
|
||||||
|
#include "vulkan/vulkan.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
typedef std::unordered_map<void *, VkLayerDispatchTable *> device_table_map;
|
||||||
|
typedef std::unordered_map<void *, VkLayerInstanceDispatchTable *> instance_table_map;
|
||||||
|
VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map);
|
||||||
|
VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa);
|
||||||
|
VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map);
|
||||||
|
VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa);
|
||||||
|
|
||||||
|
typedef void *dispatch_key;
|
||||||
|
|
||||||
|
static inline dispatch_key get_dispatch_key(const void *object) { return (dispatch_key) * (VkLayerDispatchTable **)object; }
|
||||||
|
|
||||||
|
VkLayerDispatchTable *device_dispatch_table(void *object);
|
||||||
|
|
||||||
|
VkLayerInstanceDispatchTable *instance_dispatch_table(void *object);
|
||||||
|
|
||||||
|
VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object);
|
||||||
|
|
||||||
|
VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object);
|
||||||
|
|
||||||
|
VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func);
|
||||||
|
VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func);
|
||||||
|
|
||||||
|
void destroy_device_dispatch_table(dispatch_key key);
|
||||||
|
void destroy_instance_dispatch_table(dispatch_key key);
|
||||||
|
void destroy_dispatch_table(device_table_map &map, dispatch_key key);
|
||||||
|
void destroy_dispatch_table(instance_table_map &map, dispatch_key key);
|
Loading…
Reference in New Issue