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 : '',
|
||||
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(
|
||||
'shared-glapi',
|
||||
type : 'boolean',
|
||||
|
|
|
@ -9,6 +9,14 @@ MKDIR_GEN = $(AM_V_at)$(MKDIR_P) $(@D)
|
|||
PYTHON_GEN = $(AM_V_GEN)$(PYTHON) $(PYTHON_FLAGS)
|
||||
|
||||
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/meson.build \
|
||||
wsi/meson.build \
|
||||
|
|
|
@ -25,3 +25,6 @@ inc_vulkan_wsi = include_directories('wsi')
|
|||
|
||||
subdir('util')
|
||||
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