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:
Lionel Landwerlin 2019-01-19 21:26:12 +00:00
parent 89f03d1872
commit 20c370c6b1
11 changed files with 2191 additions and 0 deletions

View File

@ -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',

View File

@ -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 \

View File

@ -25,3 +25,6 @@ inc_vulkan_wsi = include_directories('wsi')
subdir('util')
subdir('wsi')
if get_option('vulkan-overlay-layer')
subdir('overlay-layer')
endif

View File

@ -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
```

View File

@ -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"
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);