Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify supporting 16 KB page sizes on A15 #20

Merged
merged 1 commit into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ ferret.py.

Build
=====
```
git submodule update --init --recursive
```

Linux
-----
Expand Down Expand Up @@ -69,6 +72,9 @@ Example:
Using as a layer (Vulkan only)
==============================

Linux
-----

Once built, the layer and json manifest will be in <build_dir>/implicit_layer.d

Set the following env. vars to enable the layer on linux:
Expand All @@ -86,8 +92,24 @@ Then set the following env var to point to your libcollector JSON configuration
export VK_LIBCOLLECTOR_CONFIG_PATH=<path_to_json>
```

Android
-------

Local file to push to the location on Android specified:

```bash
adb push arm64/libVkLayer_libcollector.so /data/app/{app_path}/lib/arm64/
adb push layer/libcollector_config.json /sdcard/Download/
```

Set the following env. vars to enable the layer on Android:

```bash
adb shell setprop debug.vulkan.layer.1 VK_LAYER_ARM_libcollector
```

Then run your app as normal. One result file will be created per device in your application, and by default the results are written to the run directory.
To override this, set the "result_file_basename" field in the config json.
To override this, set the "result_file_basename" field in the config json. Get the result file in the specified location, for example: /sdcard/Download/results_device_0.json

JSON interface (layer specific)
---------------------------
Expand Down
1 change: 1 addition & 0 deletions android/gradle/collector_android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ find_library(android-lib android)

add_executable(burrow ${BURROW_SOURCES})
target_link_libraries(burrow app-glue ${log-lib} ${android-lib} ${app-glue} collector_android)
target_link_options(burrow PRIVATE -Wl,-z,max-page-size=16384)
1 change: 1 addition & 0 deletions android/gradle/layer_android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ find_library(android-lib android)

add_library(VkLayer_libcollector SHARED ${LAYER_SOURCES})
target_link_libraries(VkLayer_libcollector ${log-lib} ${android-lib})
target_link_options(VkLayer_libcollector PRIVATE -Wl,-z,max-page-size=16384)
1 change: 1 addition & 0 deletions android/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ LOCAL_C_INCLUDES := \

LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -latomic

LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384
LOCAL_STATIC_LIBRARIES := collector_android
LOCAL_CPP_FEATURES += exceptions

Expand Down
38 changes: 38 additions & 0 deletions layer/libcollector_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"result_file_basename" : "/sdcard/Download/results.json",
"num_subframes_per_frame" : 1,
"frame_trigger_function" : "vkQueuePresentKHR",
"start_frame" : 0,
"end_frame" : 99999,
"collectors": {
"perf": {
"set": 4,
"event": [
{
"name": "CPUCyclesUser",
"type": 4,
"config": 17,
"excludeKernel": true
},
{
"name": "CPUCyclesKernel",
"type": 4,
"config": 17,
"excludeUser": true
},
{
"name": "CPUInstructionUser",
"type": 4,
"config": 8,
"excludeKernel": true
},
{
"name": "CPUInstructionKernel",
"type": 4,
"config": 8,
"excludeUser": true
}
]
}
}
}
188 changes: 106 additions & 82 deletions layer/vulkan_layer.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "layer/vulkan_layer.hpp"

static std::mutex context_mutex;
static std::unordered_map<VkInstance, InstanceDispatchTable*> instance_dispatch_map;
static std::unordered_map<void*, InstanceDispatchTable*> instance_dispatch_map;
static std::unordered_map<VkDevice, vkCollectorContext*> device_to_context_map;
static std::unordered_map<VkQueue, vkCollectorContext*> queue_to_context_map;

Expand All @@ -11,12 +11,21 @@ static Json::Value glibcollector_config;
std::mutex vkCollectorContext::id_mutex;
uint32_t vkCollectorContext::next_id = 0;

template <typename dispatchable_type>
void *get_key(dispatchable_type inst) {
return *reinterpret_cast<void **>(inst);
}

#define GET_PROC_ADDR(func) \
if (!strcmp(funcName, #func)) \
return (PFN_vkVoidFunction)&lc_##func;

std::string get_config_path() {
std::string config_path = "libcollector_config.json";

#ifdef ANDROID
// TODO(tomped01): Find a better way on android
config_path = "/sdcard/libcollector_config.json";
config_path = "/sdcard/Download/libcollector_config.json";
#else
const char* env_path = std::getenv("VK_LIBCOLLECTOR_CONFIG_PATH");
if (env_path) {
Expand Down Expand Up @@ -68,7 +77,7 @@ bool read_config() {

if (glibcollector_config.get("result_file_basename", "").asString() == "") {
#ifdef ANDROID
glibcollector_config["result_file_basename"] = "/sdcard/results.json";
glibcollector_config["result_file_basename"] = "/sdcard/Download/results.json";
#else
glibcollector_config["result_file_basename"] = "results.json";
#endif
Expand All @@ -86,54 +95,6 @@ bool read_config() {
return true;
}


VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *pName) {
if (!gconfig_initialized) {
// Do this as early as possible
read_config();

gconfig_initialized = true;
}

if(!strcmp(pName, "vkGetInstanceProcAddr")) return (PFN_vkVoidFunction)&vkGetInstanceProcAddr;
if(!strcmp(pName, "vkCreateInstance")) return (PFN_vkVoidFunction)&lc_vkCreateInstance;
if(!strcmp(pName, "vkCreateDevice")) return (PFN_vkVoidFunction)&lc_vkCreateDevice;
if(!strcmp(pName, "vkDestroyInstance")) return (PFN_vkVoidFunction)&lc_vkDestroyInstance;
if(!strcmp(pName, "vkEnumerateInstanceLayerProperties")) return (PFN_vkVoidFunction)&lc_vkEnumerateInstanceLayerProperties;
if(!strcmp(pName, "vkEnumerateInstanceExtensionProperties")) return (PFN_vkVoidFunction)&lc_vkEnumerateInstanceExtensionProperties;

context_mutex.lock();
InstanceDispatchTable* instance_dtable = instance_dispatch_map[instance];
PFN_vkGetInstanceProcAddr gipa = instance_dtable->gipa;
context_mutex.unlock();

return gipa(instance, pName);
}


VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* pName) {
if(!strcmp(pName, "vkGetDeviceProcAddr")) return (PFN_vkVoidFunction)&vkGetDeviceProcAddr;
if(!strcmp(pName, "vkDestroyDevice")) return (PFN_vkVoidFunction)&lc_vkDestroyDevice;
if(!strcmp(pName, "vkGetDeviceQueue")) return (PFN_vkVoidFunction)&lc_vkGetDeviceQueue;

if (glibcollector_config.get("frame_trigger_function", "").asString() == std::string("vkQueueSubmit")) {
DBG_LOG("LIBCOLLECTOR LAYER: Sampling function set to vkQueueSubmit\n");
if(!strcmp(pName, "vkQueueSubmit")) return (PFN_vkVoidFunction)&lc_vkQueueSubmit;
} else {
DBG_LOG("LIBCOLLECTOR LAYER: Sampling function set to vkQueuePresentKHR\n");
if(!strcmp(pName, "vkQueuePresentKHR")) return (PFN_vkVoidFunction)&lc_vkQueuePresentKHR;
}

context_mutex.lock();
vkCollectorContext* context = device_to_context_map[device];
PFN_vkGetDeviceProcAddr gdpa;
gdpa = context->gdpa;
context_mutex.unlock();

return gdpa(device, pName);
}


VK_LAYER_EXPORT VkResult VKAPI_CALL lc_vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
Expand All @@ -158,9 +119,10 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL lc_vkCreateInstance(
InstanceDispatchTable* new_table = new InstanceDispatchTable();
new_table->gipa = (PFN_vkGetInstanceProcAddr)gipa(*pInstance, "vkGetInstanceProcAddr");
new_table->nextDestroyInstance = (PFN_vkDestroyInstance)gipa(*pInstance, "vkDestroyInstance");
new_table->nextEnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties)gipa(*pInstance, "vkEnumerateDeviceExtensionProperties");

context_mutex.lock();
instance_dispatch_map[*pInstance] = new_table;
instance_dispatch_map[get_key(*pInstance)] = new_table;

context_mutex.unlock();

Expand All @@ -173,9 +135,9 @@ VK_LAYER_EXPORT void VKAPI_CALL lc_vkDestroyInstance(
const VkAllocationCallbacks* pAllocator
) {
context_mutex.lock();
InstanceDispatchTable* table = instance_dispatch_map[instance];
InstanceDispatchTable* table = instance_dispatch_map[get_key(instance)];
PFN_vkDestroyInstance nextDestroyInstance = table->nextDestroyInstance;
instance_dispatch_map.erase(instance);
instance_dispatch_map.erase(get_key(instance));
context_mutex.unlock();

delete table;
Expand Down Expand Up @@ -302,9 +264,9 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL lc_vkQueuePresentKHR(
}


// Pre-instance functions
// Enum-instance functions

VK_LAYER_EXPORT VkResult VKAPI_CALL lc_vkEnumerateInstanceLayerProperties(
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
uint32_t* pPropertyCount,
VkLayerProperties* pProperties
) {
Expand All @@ -322,7 +284,17 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL lc_vkEnumerateInstanceLayerProperties(
return VK_SUCCESS;
}

VK_LAYER_EXPORT VkResult VKAPI_CALL lc_vkEnumerateInstanceExtensionProperties(

VK_LAYER_EXPORT VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
VkPhysicalDevice physicalDevice,
uint32_t *pPropertyCount,
VkLayerProperties *pProperties
) {
return vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties);
}


VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties
Expand All @@ -337,39 +309,91 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL lc_vkEnumerateInstanceExtensionProperties(
return VK_ERROR_LAYER_NOT_PRESENT;
}

// Pre-instance interface functions, not currently in use, but can be enabled if/when we update to manifest format 1.2.1
VK_LAYER_EXPORT VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName,
uint32_t *pPropertyCount,
VkExtensionProperties *pProperties)
{
if (pLayerName == NULL || strcmp(pLayerName, "VK_LAYER_ARM_libcollector")) {
if (physicalDevice == VK_NULL_HANDLE)
{
return VK_SUCCESS;
}

VkResult lc_pre_vkEnumerateInstanceExtensionProperties(
const VkEnumerateInstanceExtensionPropertiesChain* pChain,
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties
) {
if (pLayerName == NULL) {
return VK_ERROR_LAYER_NOT_PRESENT;
} else if (!strcmp(pLayerName, "VK_LAYER_ARM_libcollector")) {
return pChain->pfnNextLayer(pChain->pNextLink, pLayerName, pPropertyCount, pProperties);
return instance_dispatch_map[get_key(physicalDevice)]->nextEnumerateDeviceExtensionProperties(
physicalDevice, pLayerName, pPropertyCount, pProperties);
}

return VK_ERROR_LAYER_NOT_PRESENT;
if (pPropertyCount != nullptr) {
*pPropertyCount = 0;
}

return VK_SUCCESS;
}

VkResult lc_pre_vkEnumerateInstanceLayerProperties(
const VkEnumerateInstanceLayerPropertiesChain* pChain,
uint32_t* pPropertyCount,
VkLayerProperties* pProperties
) {
if (pProperties == nullptr) {
*pPropertyCount = 1;

VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL lc_vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
GET_PROC_ADDR(vkGetDeviceProcAddr);
GET_PROC_ADDR(vkDestroyDevice);
GET_PROC_ADDR(vkGetDeviceQueue);

if (glibcollector_config.get("frame_trigger_function", "").asString() == std::string("vkQueueSubmit")) {
DBG_LOG("LIBCOLLECTOR LAYER: Sampling function set to vkQueueSubmit\n");
GET_PROC_ADDR(vkQueueSubmit);
} else {
const char* layer_name = "VK_LAYER_ARM_libcollector";
strncpy(pProperties[0].layerName, layer_name, strlen(layer_name) + 1);
pProperties[0].specVersion = VK_MAKE_API_VERSION(0, 1, 1, 2);
pProperties[0].implementationVersion = 2;
const char* layer_description = "ARM libcollector layer implementation.";
strncpy(pProperties[0].description, layer_description, strlen(layer_description) + 1);
DBG_LOG("LIBCOLLECTOR LAYER: Sampling function set to vkQueuePresentKHR\n");
GET_PROC_ADDR(vkQueuePresentKHR);
}

context_mutex.lock();
vkCollectorContext* context = device_to_context_map[device];
PFN_vkGetDeviceProcAddr gdpa;
gdpa = context->gdpa;
context_mutex.unlock();

return gdpa(device, funcName);
}


VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
return lc_vkGetDeviceProcAddr(device, funcName);
}


VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL lc_vkGetInstanceProcAddr(VkInstance instance,
const char *funcName) {
if (!gconfig_initialized) {
// Do this as early as possible
read_config();

gconfig_initialized = true;
}

GET_PROC_ADDR(vkGetInstanceProcAddr);
GET_PROC_ADDR(vkCreateInstance);
GET_PROC_ADDR(vkCreateDevice);
GET_PROC_ADDR(vkDestroyInstance);

context_mutex.lock();
InstanceDispatchTable* instance_dtable = instance_dispatch_map[get_key(instance)];
PFN_vkGetInstanceProcAddr gipa = instance_dtable->gipa;
context_mutex.unlock();

return gipa(instance, funcName);
}


VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
return lc_vkGetInstanceProcAddr(instance, funcName);
}


VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
pVersionStruct->pfnGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)&lc_vkGetInstanceProcAddr;
pVersionStruct->pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)&lc_vkGetDeviceProcAddr;
pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;

return VK_SUCCESS;
}

Expand Down
Loading
Loading