Skip to content

Commit

Permalink
Initial PowerVR PerfDoc changes
Browse files Browse the repository at this point in the history
  • Loading branch information
PVRDevTech committed Nov 26, 2019
1 parent 718ab65 commit a677ae8
Show file tree
Hide file tree
Showing 45 changed files with 3,108 additions and 180 deletions.
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ cmake_minimum_required(VERSION 3.5)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD 99)

if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
project(PowerVR-PerfDoc LANGUAGES CXX C)

if ((${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
set(PERFDOC_CXX_FLAGS -Wall -Wextra -Wno-missing-field-initializers)
elseif(MSVC)
set(PERFDOC_CXX_FLAGS /wd4244 /wd4996 /wd4800 /D_CRT_SECURE_NO_WARNINGS /DNOMINMAX)
endif()

project(Mali-PerfDoc LANGUAGES CXX C)

enable_testing()
set(PLATFORM png)
add_subdirectory(layer)
Expand Down
Binary file added PVRPerfDoc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 47 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
# PerfDoc

![perfdocbanner](https://user-images.githubusercontent.com/11390552/31229971-5d89fc18-a9da-11e7-978b-9d806ef39450.png)
# PowerVR PerfDoc

![banner](PVRPerfDoc.png)

PerfDoc is a Vulkan layer which aims to validate applications against the
[Mali Application Developer Best Practices](https://developer.arm.com/graphics/developer-guides/mali-gpu-best-practices) document.
The PowerVR Developer Support team has adapted the ARM PerfDoc validation layer to make it more applicable to the PowerVR architecture.

Just like the LunarG validation layers, this layer tracks your application and attempts to find API usage which is discouraged.
PerfDoc focuses on checks which can be done up-front, and checks which can portably run on all platforms which support Vulkan.
We have attempted to modify the original code as little as possible, just adding or removing checks that reflect our own [PowerVR Performance Recommendations](https://docs.imgtec.com/PerfRec/topics/c_PerfRec_introduction.html) more closely.

The intended use of PerfDoc is to be used during development to catch potential performance issues early.
The layer will run on any Vulkan implementation, so Mali-related optimizations can be found even when doing bringup on desktop platforms.
Just like Vulkan validation layers, errors are reported either through `VK_EXT_debug_report` to the application as callbacks, or via console/logcat if enabled.
As with the original PerfDoc, this version evaluates API usage with checks which can be done up-front, and tries to keep code portability as high as possible.

Dynamic checking (i.e. profiling) of how an application is behaving in run-time is currently not in the scope of PerfDoc.
Just like PerfDoc and other Vulkan validation layers, errors are reported either through VK_EXT_debug_report to the application as callbacks, or via a console/logcat if enabled. The layer will run on any Vulkan implementation, so optimisations can be found even when running on non-PowerVR platforms.

Some heuristics in PerfDoc are based on "arbitrary limits" in case where there is no obvious limit to use.
These values can be tweaked later via config files if needed.
Some checks which are CPU intensive (index scanning for example), can also be disabled by the config file.

## Features

Expand Down Expand Up @@ -65,6 +58,21 @@ enum MessageCodes
MESSAGE_CODE_REDUNDANT_IMAGE_CLEAR = 35,
MESSAGE_CODE_INEFFICIENT_CLEAR = 36,
MESSAGE_CODE_LAZY_TRANSIENT_IMAGE_NOT_SUPPORTED = 37,
MESSAGE_CODE_UNCOMPRESSED_TEXTURE_USED = 38,
MESSAGE_CODE_NON_MIPMAPPED_TEXTURE_USED = 39,
MESSAGE_CODE_NON_INDEXED_DRAW_CALL = 40,
MESSAGE_CODE_SUBOPTIMAL_TEXTURE_FORMAT = 41,
MESSAGE_CODE_TEXTURE_LINEAR_TILING = 42,
MESSAGE_CODE_NO_FBCDC = 43,
MESSAGE_CODE_ROBUST_BUFFER_ACCESS_ENABLED = 44,
MESSAGE_CODE_SUBOPTIMAL_SUBPASS_DEPENDENCY_FLAG = 45,
MESSAGE_CODE_PARTIAL_CLEAR = 46,
MESSAGE_CODE_PIPELINE_OPTIMISATION_DISABLED = 47,
MESSAGE_CODE_WORKGROUP_SIZE_DIVISOR = 48,
MESSAGE_CODE_POTENTIAL_SUBPASS = 49,
MESSAGE_CODE_SUBPASS_STENCIL_SELF_DEPENDENCY = 50,
MESSAGE_CODE_INEFFICIENT_DEPTH_STENCIL_OPS = 51,
MESSAGE_CODE_QUERY_BUNDLE_TOO_SMALL = 52,
MESSAGE_CODE_COUNT
};
Expand All @@ -75,13 +83,13 @@ The objectType reported by the layer matches the standard `VK_EXT_debug_report`

## To build

See [BUILD.md](BUILD.md).
See BUILD.md.

## Config file

**The config file is optional.**

There are certain values in PerfDoc which are used as thresholds for heuristics, which can flag potential issues in an application.
There are certain values in PowerVR PerfDoc which are used as thresholds for heuristics, which can flag potential issues in an application.
Sometimes, these thresholds are somewhat arbitrary and may cause unnecessary false positives for certain applications.
For these scenarios it is possible to provide a config file.
See the sections below for how to enable the config file for Linux/Windows and Android.
Expand All @@ -104,34 +112,34 @@ VK_LAYER_PATH=/path/to/directory/with/json/and/binary
```

This allows the application to enumerate the layer manually and enable the debug callback from within the app.
The layer name is `VK_LAYER_ARM_mali_perf_doc`.
The layer name is `VK_LAYER_IMG_powervr_perf_doc`.
The layer should appear in `vkEnumerateInstanceLayerProperties` and `vkEnumerateDeviceLayerProperties`.

### Enabling layers outside the application

To force-enable PerfDoc outside the application, some environment variables are needed.
To force-enable PowerVR PerfDoc outside the application, some environment variables are needed.

```
VK_LAYER_PATH=/path/to/directory/with/json/and/binary
VK_INSTANCE_LAYERS=VK_LAYER_ARM_mali_perf_doc
VK_DEVICE_LAYERS=VK_LAYER_ARM_mali_perf_doc
VK_INSTANCE_LAYERS=VK_LAYER_IMG_powervr_perf_doc
VK_DEVICE_LAYERS=VK_LAYER_IMG_powervr_perf_doc
```

However, without a `VK_EXT_debug_report` debug callback,
you will not get any output, so to add logging to file or console:

```
# Either one of these
MALI_PERFDOC_LOG=stdout
MALI_PERFDOC_LOG=stderr
MALI_PERFDOC_LOG=/path/to/log.txt
MALI_PERFDOC_LOG=debug_output # OutputDebugString, Windows only
POWERVR_PERFDOC_LOG=stdout
POWERVR_PERFDOC_LOG=stderr
POWERVR_PERFDOC_LOG=/path/to/log.txt
POWERVR_PERFDOC_LOG=debug_output # OutputDebugString, Windows only
```

It is also possible to use a config file which supports more options as well as logging output:

```
MALI_PERFDOC_CONFIG=/tmp/path/to/config.cfg"
POWERVR_PERFDOC_CONFIG=/tmp/path/to/config.cfg"
```

## Enabling layers on Android
Expand All @@ -146,8 +154,8 @@ Make sure to use the right version which matches your application.
The layer .so must be present in the APKs library directory.
The Android loader will find the layers when enumerating layers, just like the validation layers.

The PerfDoc layer must be enabled explicitly by the app in both `vkCreateInstance` and `vkCreateDevice`.
The layer name is `VK_LAYER_ARM_mali_perf_doc`.
The PowerVR PerfDoc layer must be enabled explicitly by the app in both `vkCreateInstance` and `vkCreateDevice`.
The layer name is `VK_LAYER_IMG_powervr_perf_doc`.
The layer should appear in `vkEnumerateInstanceLayerProperties` and `vkEnumerateDeviceLayerProperties`.

### Outside the application
Expand All @@ -160,50 +168,50 @@ but this will certainly require root.
To force-enable the layer for all Vulkan applications:

```
setprop debug.vulkan.layers VK_LAYER_ARM_mali_perf_doc:
setprop debug.vulkan.layers VK_LAYER_IMG_powervr_perf_doc:
```

Here is an example for how to enable PerfDoc for any Vulkan application:
Here is an example for how to enable PowerVR PerfDoc for any Vulkan application:
```
# For ARMv7-A
adb push build-android-armeabi-v7a/layer/libVkLayer_mali_perf_doc.so /data/local/debug/vulkan/
adb push build-android-armeabi-v7a/layer/libVkLayer_powervr_perf_doc.so /data/local/debug/vulkan/
# For AArch64
adb push build-android-arm64-v8a/layer/libVkLayer_mali_perf_doc.so /data/local/debug/vulkan/
adb push build-android-arm64-v8a/layer/libVkLayer_powervr_perf_doc.so /data/local/debug/vulkan/
adb shell
setprop debug.mali.perfdoc.log logcat
setprop debug.vulkan.layers VK_LAYER_ARM_mali_perf_doc:
setprop debug.powervr.perfdoc.log logcat
setprop debug.vulkan.layers VK_LAYER_IMG_powervr_perf_doc:
exit
adb logcat -c && adb logcat -s MaliPerfDoc
adb logcat -c && adb logcat -s PowerVRPerfDoc
```

#### Enabling logcat/file logging

It is sometimes desirable to use PerfDoc from outside an application,
e.g. when debugging random APKs which do not have PerfDoc integrated.
It is sometimes desirable to use PowerVR PerfDoc from outside an application,
e.g. when debugging random APKs which do not have PowerVR PerfDoc integrated.

There are two ways to enable external logging on Android.
Both of the methods described below can also be used when the layer is embedded in the APK (but not enabled by the app),
but they are most relevant when dealing with arbitrary Vulkan applications.

To filter logcat output, you can use:
```
adb logcat -s MaliPerfDoc
adb logcat -s PowerVRPerfDoc
```

##### setprop method (Recommended)

To force-enable logging from outside an application, you can set an Android system property:
```
setprop debug.mali.perfdoc.log logcat
setprop debug.powervr.perfdoc.log logcat
```

To log to a file, replace logcat with a filename. Be aware that system properties on Android
have a very limited number of characters available, so a long path might not be possible to represent.
```
setprop debug.mali.perfdoc.log /sdcard/path/to/log.txt
setprop debug.powervr.perfdoc.log /sdcard/path/to/log.txt
```

##### Config file method
Expand All @@ -226,7 +234,7 @@ loggingFilename /sdcard/path/to/log.txt
Then, point the layer to this config file by typing this into adb shell:

```
setprop debug.mali.perfdoc.config /sdcard/path/to/perfdoc.cfg
setprop debug.powervr.perfdoc.config /sdcard/path/to/perfdoc.cfg
```

Be careful with permissions however. Not all paths on the SD card can be made visible to an application.
Expand Down
2 changes: 1 addition & 1 deletion cross_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ cd ..

day=$(date "+%Y-%m-%d")
commit=$(git rev-parse HEAD | cut -b 1-10)
zip mali-perfdoc-$day-$commit.zip \
zip powervr-perfdoc-$day-$commit.zip \
README.md \
layer/perfdoc-default.cfg \
build-linux-x64/layer/*.{so,json} \
Expand Down
36 changes: 18 additions & 18 deletions layer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ else()
set(export-file )
endif()

add_library(VkLayer_mali_perf_doc SHARED
add_library(VkLayer_powervr_perf_doc SHARED
logger.cpp
config.cpp
base_object.cpp
Expand Down Expand Up @@ -52,42 +52,42 @@ add_library(VkLayer_mali_perf_doc SHARED
swapchain.cpp
heuristic.cpp
${export-file})
target_include_directories(VkLayer_mali_perf_doc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_include_directories(VkLayer_powervr_perf_doc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)

target_compile_options(VkLayer_mali_perf_doc PUBLIC ${PERFDOC_CXX_FLAGS})
target_compile_options(VkLayer_powervr_perf_doc PUBLIC ${PERFDOC_CXX_FLAGS})

file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/layer)

if (WIN32)
add_custom_command(TARGET VkLayer_mali_perf_doc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/VkLayer_mali_perf_doc_win32.json ${CMAKE_BINARY_DIR}/layer/VkLayer_mali_perf_doc.json)
set_target_properties(VkLayer_mali_perf_doc PROPERTIES PREFIX "" LIBRARY_OUTPUT_NAME VkLayer_mali_perf_doc)
add_custom_command(TARGET VkLayer_powervr_perf_doc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/VkLayer_powervr_perf_doc_win32.json ${CMAKE_BINARY_DIR}/layer/VkLayer_powervr_perf_doc.json)
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES PREFIX "" LIBRARY_OUTPUT_NAME VkLayer_powervr_perf_doc)
if (CMAKE_COMPILER_IS_GNUCXX)
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
set_target_properties(VkLayer_mali_perf_doc PROPERTIES LINK_FLAGS "-Wl,--no-undefined -static -s")
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES LINK_FLAGS "-Wl,--no-undefined -static -s")
else()
set_target_properties(VkLayer_mali_perf_doc PROPERTIES LINK_FLAGS "-Wl,--no-undefined -static")
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES LINK_FLAGS "-Wl,--no-undefined -static")
endif()
endif()
else()
add_custom_command(TARGET VkLayer_mali_perf_doc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/VkLayer_mali_perf_doc.json ${CMAKE_BINARY_DIR}/layer/VkLayer_mali_perf_doc.json)
add_custom_command(TARGET VkLayer_powervr_perf_doc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/VkLayer_powervr_perf_doc.json ${CMAKE_BINARY_DIR}/layer/VkLayer_powervr_perf_doc.json)
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
set_target_properties(VkLayer_mali_perf_doc PROPERTIES LINK_FLAGS "-Wl,--no-undefined -s")
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES LINK_FLAGS "-Wl,--no-undefined -s")
else()
set_target_properties(VkLayer_mali_perf_doc PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES LINK_FLAGS "-Wl,--no-undefined")
endif()
endif()

set_target_properties(VkLayer_mali_perf_doc PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/layer")
set_target_properties(VkLayer_mali_perf_doc PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/layer")
set_target_properties(VkLayer_mali_perf_doc PROPERTIES RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}/layer")
set_target_properties(VkLayer_mali_perf_doc PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/layer")
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/layer")
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/layer")
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}/layer")
set_target_properties(VkLayer_powervr_perf_doc PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/layer")

add_subdirectory(SPIRV-Cross EXCLUDE_FROM_ALL)
set_property(TARGET spirv-cross-core PROPERTY POSITION_INDEPENDENT_CODE TRUE)
target_link_libraries(VkLayer_mali_perf_doc spirv-cross-core)
target_link_libraries(VkLayer_powervr_perf_doc spirv-cross-core)

if (ANDROID)
target_link_libraries(VkLayer_mali_perf_doc log)
target_link_libraries(VkLayer_powervr_perf_doc log)
endif()
2 changes: 1 addition & 1 deletion layer/SPIRV-Cross
Submodule SPIRV-Cross updated 397 files
17 changes: 17 additions & 0 deletions layer/VkLayer_powervr_perf_doc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_IMG_powervr_perf_doc",
"type": "GLOBAL",
"library_path": "./libVkLayer_powervr_perf_doc.so",
"api_version": "1.0.0",
"implementation_version": "1",
"description": "IMG PowerVR PerfDoc",
"instance_extensions": [
{
"name": "VK_EXT_debug_report",
"spec_version": "3"
}
]
}
}
17 changes: 17 additions & 0 deletions layer/VkLayer_powervr_perf_doc_win32.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_IMG_powervr_perf_doc",
"type": "GLOBAL",
"library_path": ".\\VkLayer_powervr_perf_doc.dll",
"api_version": "1.0.0",
"implementation_version": "1",
"description": "IMG PowerVR PerfDoc",
"instance_extensions": [
{
"name": "VK_EXT_debug_report",
"spec_version": "3"
}
]
}
}
6 changes: 5 additions & 1 deletion layer/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,12 @@ VkResult Buffer::bindMemory(DeviceMemory *memory_, VkDeviceSize offset)

auto memorySize = memory->getAllocateInfo().allocationSize;

const auto &cfg = this->getDevice()->getConfig();

// If we're consuming an entire memory block here, it better be a very large allocation.
if (memorySize == memoryRequirements.size && memorySize < baseDevice->getConfig().minDedicatedAllocationSize)
if (
cfg.msgSmallDedicatedAllocation &&
memorySize == memoryRequirements.size && memorySize < baseDevice->getConfig().minDedicatedAllocationSize)
{
// Sanity check.
MPD_ASSERT(offset == 0);
Expand Down
Loading

0 comments on commit a677ae8

Please sign in to comment.