### Processor Power Information Example Source: https://docs.qualcomm.com/doc/80-78185-2/topic/performance_optimization.html This example demonstrates how to retrieve and display detailed power information for each processor, including current and maximum MHz, MHz limits, and idle states. It requires the Powrprof.lib library. ```cpp int main(int argc, char* argv[]) { DWORD dwNumProcessors = GetInstalledProcessorCount(); std::vector a(dwNumProcessors); DWORD dwSize = sizeof(PROCESSOR_POWER_INFORMATION) * dwNumProcessors; std::cout << "Number of processors: " << dwNumProcessors << std::endl; CallNtPowerInformation(ProcessorInformation, NULL, 0, &a[0], dwSize); std::cout << "Processor\tMHz\tMaxMHz\tMHz Limit\tIdle State\tMax Idle State" << std::endl; for (int i = 0; i < dwNumProcessors; i++) { std::cout << a[i].Number << "\t\t"; std::cout << a[i].CurrentMhz << '\t'; std::cout << a[i].MaxMhz << '\t'; std::cout << a[i].MhzLimit << "\t\t\t"; std::cout << a[i].CurrentIdleState << "\t\t"; std::cout << a[i].MaxIdleState << "\t" << std::endl; } a.clear(); system("pause"); return 0; } ``` -------------------------------- ### Get Installed Processor Count Source: https://docs.qualcomm.com/doc/80-78185-2/topic/performance_optimization.html Retrieves the number of installed processors on a Windows system. It attempts to use GetActiveProcessorCount, then GetLogicalProcessorInformationEx, GetLogicalProcessorInformation, and finally GetSystemInfo as fallbacks. ```cpp #include #include extern "C" { #include } #include #pragma comment(lib, "Powrprof.lib") typedef struct _PROCESSOR_POWER_INFORMATION { ULONG Number; ULONG MaxMhz; ULONG CurrentMhz; ULONG MhzLimit; ULONG MaxIdleState; ULONG CurrentIdleState; } PROCESSOR_POWER_INFORMATION, * PPROCESSOR_POWER_INFORMATION; typedef BOOL(WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD); typedef BOOL(WINAPI* LPFN_GLPIEX)(LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); typedef DWORD(WINAPI* LPFN_GAPC)(WORD); #define ALL_PROCESSOR_GROUPS 0xffff // Helper function to count set bits in the processor mask. DWORD CountSetBits(ULONG_PTR bitMask) { DWORD LSHIFT = sizeof(ULONG_PTR) * 8 - 1; DWORD bitSetCount = 0; ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT; DWORD i; for (i = 0; i <= LSHIFT; ++i) { bitSetCount += ((bitMask & bitTest) ? 1 : 0); bitTest /= 2; } return bitSetCount; } DWORD GetInstalledProcessorCount() { // on Windows 7 and later, use GetActiveProcessorCount() ... LPFN_GAPC gapc = (LPFN_GAPC)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetActiveProcessorCount"); if (gapc) return gapc(ALL_PROCESSOR_GROUPS); // on Vista and later, try GetLogicalProcessorInformationEx() next ... LPFN_GLPIEX glpiex = (LPFN_GLPIEX)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformationEx"); if (glpiex) { std::vector buffer; PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info = NULL; DWORD bufsize = 0; // not using RelationGroup because it does not return accurate info under WOW64... while (!glpiex(RelationProcessorCore, info, &bufsize)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return 0; buffer.resize(bufsize); info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)&buffer[0]; } DWORD logicalProcessorCount = 0; while (bufsize >= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)) { // for RelationProcessorCore, info->Processor.GroupCount is always 1... logicalProcessorCount += CountSetBits(info->Processor.GroupMask[0].Mask); bufsize -= info->Size; info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)(((LPBYTE)info) + info->Size); } return logicalProcessorCount; } // on XP and later, try GetLogicalProcessorInformation() next... LPFN_GLPI glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation"); if (glpi) { std::vector buffer; PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = NULL; DWORD bufsize = 0; while (!glpi(info, &bufsize)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return 0; buffer.resize(bufsize); info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)&buffer[0]; } DWORD logicalProcessorCount = 0; while (bufsize >= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)) { if (info->Relationship == RelationProcessorCore) { // A hyperthreaded core supplies more than one logical processor. logicalProcessorCount += CountSetBits(info->ProcessorMask); } bufsize -= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++info; } return logicalProcessorCount; } // fallback to GetSystemInfo() last ... SYSTEM_INFO si = { 0 }; GetSystemInfo(&si); return si.dwNumberOfProcessors; } ``` -------------------------------- ### GET /texture-formats Source: https://docs.qualcomm.com/doc/80-78185-2/topic/spec_sheets.html Retrieves the list of supported texture formats and their hardware capability flags for A5x/A6x architectures. ```APIDOC ## GET /texture-formats ### Description Returns a comprehensive table of texture formats supported by the hardware, detailing capabilities such as bit depth, MSAA levels, and support for features like UBWC, Fast Clear, and UAV operations. ### Method GET ### Endpoint /texture-formats ### Response #### Success Response (200) - **formats** (array) - A list of objects representing each texture format and its supported features (e.g., bit_depth, max_msaa, srgb, linear, optimal, ubwc, fast_clear, point_sample_only, blendable_rt, uav_read, uav_write). #### Response Example [ { "format": "R8_UNORM", "bit_depth": "8 bit", "max_msaa": "8x", "srgb": false, "linear": true, "optimal": true, "ubwc": false, "fast_clear": true, "point_sample_only": false, "blendable_rt": true, "uav_read": true, "uav_write": true } ] ``` -------------------------------- ### Example adb output for GLES driver version Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Example output from 'adb shell dumpsys SurfaceFlinger | grep GLES', showing the driver version format. The 'V@0676.0' indicates driver version 676. ```text GLES: Qualcomm, Adreno (TM) 740, OpenGL ES 3.2 V@0676.0 (GIT@6f08ddb, I5e1ee3b043, 1669189803) (Date:11/23/22) ``` -------------------------------- ### Implement Adreno driver version workaround Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Example of implementing a workaround for a specific Adreno driver version (676) and patch range. This code guards against known issues in older patches of a specific driver release. ```c // Workarounds for Adreno driver 676 if (VK_VERSION_MINOR(version) == 676) { // Guard for known Adreno issue on patch < 17 and driver 676 if (VK_VERSION_PATCH(version) < 17) { doWorkaround(); } // After patch 17 we know the issue was addressed by the vendor else { doNormalFlow(); } } ``` -------------------------------- ### ISPC Vector Addition Implementation Source: https://docs.qualcomm.com/doc/80-78185-2/topic/performance_optimization.html Example of defining a vector structure and operator overload for SPMD-style addition in ISPC. ```cpp struct FloatVector { float V[4]; }; FloatVector operator+(const FloatVector& A, const FloatVector& B) { FloatVector R; for (uniform int i=0; i< 4; i++) { R.V[i] = A.V[i] + B.V[i]; } return R; } ``` -------------------------------- ### Load Program Binary (OpenGL ES) Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Load a previously saved binary representation of a program object using glProgramBinaryOES or glProgramBinary. This bypasses recompilation and relinking, significantly speeding up application launch times. ```c glProgramBinaryOES( program, binaryFormat, binary, length ); ``` ```c glProgramBinary( program, binaryFormat, binary, length ); ``` -------------------------------- ### Map Threads to Cores using sched_setaffinity Source: https://docs.qualcomm.com/doc/80-78185-2/topic/cpu.html Use sched_setaffinity from sched.h to map threads to specific CPU cores. This allows for intelligent thread placement, potentially outperforming default Android scheduling. ```c #include // Example of using sched_setaffinity (actual implementation would involve setting CPU sets) int set_cpu_affinity(pid_t pid, int core_id) { cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(core_id, &mask); return sched_setaffinity(pid, sizeof(cpu_set_t), &mask); } ``` -------------------------------- ### Compute Shader Workgroup Size Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html When using glDispatchIndirect() on OpenGL ES, ensure the workgroup size is at least 64 to avoid CPU-GPU synchronization issues. This example sets a workgroup size of 32, which should be increased. ```glsl layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; //workgroup size = local_size_x*local_size_y*local_size_z = 32x1x1 = 32 -- make sure this equation produces at least 64 to avoid a Cpu-wait-on-Gpu ``` -------------------------------- ### Initialize and Traverse Ray Query for Shadow Generation Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Initializes a ray query object and traverses it to determine pixel occlusion for shadow generation. This code is used within a subpass for ray tracing from a light source. ```glsl // Initialize the query object rayQueryEXT rayQuery; rayQueryInitializeEXT( rayQuery, accelStructure, gl_RayFlagsTerminateOnFirstHitEXT, cullMask, WorldPos, minDistance, DirectionToLight, LightDistance); // Traverse the query -- do once for the first hit while(rayQueryProceedEXT(rayQuery)) { // Hit something! Logic can be added here depending on the type of intersection } // Get the last intersection information if(rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT) { // Got an intersection -- this pixel is occluded, so retrieve distance float intersectionDistance = rayQueryGetIntersectionTEXT(rayQuery, true); // ... } ``` -------------------------------- ### ARM64 Assembly Loop Vectorization Source: https://docs.qualcomm.com/doc/80-78185-2/topic/performance_optimization.html Assembly output demonstrating a vectorized loop structure on ARM64 architecture. ```asm |$LL22@S| ldur s17,[x8,#-0x10] sub x10,x10,#1 ldr s16,[x0],#4 fadd s16,s17,s16 ldr s17,[x13,x8] stur s16,[x9,#-0x20] ldr s16,[x8] fadd s16,s17,s16 ldr s17,[x11,x9] str s16,[x12,x8] ldr s16,[x8,#0x10] fadd s16,s17,s16 ldr s17,[x8,#0x20] add x8,x8,#4 str s16,[x9],#4 ldr s16,[x0,#0x2C] fadd s16,s17,s16 str s16,[x9,#0xC] cbnz x10,|$LL22@sumS| ret ``` -------------------------------- ### Loop Unrolling for GPR Optimization Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Demonstrates replacing a loop with explicit unrolled calls to potentially reduce GPR usage. ```GLSL for (i = 0; i < 4; ++i) { diffuse += ComputeDiffuseContribution(normal, light[i]); } ``` ```GLSL diffuse += ComputeDiffuseContribution(normal, light[0]); diffuse += ComputeDiffuseContribution(normal, light[1]); diffuse += ComputeDiffuseContribution(normal, light[2]); diffuse += ComputeDiffuseContribution(normal, light[3]); ``` -------------------------------- ### Retrieve Program Binary (OpenGL ES 2.0) Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html For OpenGL ES 2.0 contexts, use glGetProgramBinaryOES to retrieve the binary representation of a linked program object, provided the GL_OES_get_program_binary extension is available. This facilitates saving and loading compiled shaders. ```c glGetProgramBinaryOES( program, bufSize, length, binaryFormat, binary ); ``` -------------------------------- ### Supported Texture Formats Source: https://docs.qualcomm.com/doc/80-78185-2/topic/spec_sheets.html A detailed breakdown of available texture formats, their bit depths, and specific feature support. ```APIDOC ## Texture Format Details This section lists various texture formats, their bit depth, and support for specific features indicated by checkmarks. ### Format Table | Format Name | Bit Depth | 8x | √ | √ | √ | √ | | √ | | √ | √ | |---|---|---|---|---|---|---|---|---|---|---|---| | R16G16B16A16_SINT | 64 bit | 8x | | √ | √ | √ | | √ | | √ | √ | | R32G32_UNORM | 64 bit | | | √ | | | | | | | | | R32G32_SNORM | 64 bit | | | √ | | | | | | | | | R32G32_FP32 | 64 bit | 8x | | √ | √ | √ | √ | | | √ | √ | √ | | R32G32_UINT | 64 bit | 8x | | √ | √ | √ | √ | | √ | | √ | √ | | R32G32_SINT | 64 bit | 8x | | √ | √ | √ | √ | | √ | | √ | √ | | R32G32_S15_16_FIXED | 64 bit | | | √ | | | | | | | | | | R32G32B32_UNORM | 96 bit | | | √ | | | | | | | | | | R32G32B32_SNORM | 96 bit | | | √ | | | | | | | | | | R32G32B32_UINT | 96 bit | 1x | | √ | | | | | √ | | | | | R32G32B32_SINT | 96 bit | 1x | | √ | | | | | √ | | | | | R32G32B32_FP32 | 96 bit | 1x | | √ | | | | | | | | | | R32G32B32_S15_16_FIXED | 96 bit | | | √ | | | | | | | | | | R32G32B32A32_UNORM | 128 bit | | | √ | | | | | | | | | | R32G32B32A32_SNORM | 128 bit | | | √ | | | | | | | | | | R32G32B32A32_FP32 | 128 bit | 4x | | √ | √ | √ | √ | | | √ | √ | √ | | R32G32B32A32_UINT | 128 bit | 4x | | √ | √ | √ | √ | | √ | | √ | √ | | R32G32B32A32_SINT | 128 bit | 4x | | √ | √ | √ | √ | | √ | | √ | √ | | R32G32B32A32_S15_16_FIXED | 128 bit | | | √ | | | | | | | | | | UYVY_UNORM | YUV packed (16 bit) | 1x | | √ | | | | | √ | | | | YUY2_UNORM (YUYV) | YUV packed (16 bit) | 1x | | √ | √ | | | | | √ | | | | NV12_UNORM | YUV planar (8/16 bit) | 1x | | | √ | √ | | | | √ | | | | NV21_UNORM | YUV planar (8/16 bit) | 1x | | √ | | | | | | √ | | | | IYUV_UNORM | YUV planar (8 bit) | 1x | | √ | | | | | | √ | | | | Y8U8V8A8_UNORM | YUV packed (32 bit) | 8x | | √ | √ | √ | √ | | | √ | √ | √ | | YVYU_UNORM | YUV packed (16 bit) | 1x | | √ | | | | | | √ | | | | VYUY_UNORM | YUV packed (16 bit) | 1x | | √ | | | | | | √ | | | | Y8_UNORM | Y/U/V planar (8 bit)3 | 1x | | | √ | √ | | | | √ | √ | √ | | NV12_UV_UNORM | UV planar (16 bit) | 1x | | | √ | √ | | | | √ | √ | √ | | NV21_VU_UNORM | VU planar (16 bit) | 1x | | √ | | | | | | √ | √ | √ | | NV12_4R_UNORM | YUV planar (8/16 bit) | 1x | | √ | √ | √ | | | | √ | | | | NV12_4R_Y_UNORM | Y planar (8 bit) | 1x | | √ | √ | √ | | | | √ | | √ | | NV12_4R_UV_UNORM | UV planar (16 bit) | 1x | | √ | √ | √ | | | | √ | | √ | | P010_UNORM | YUV planar (16/32 bit) | 1x | | √ | √ | √ | | | | √ | | | | P010_Y_UNORM | Y planar (16 bit) | 1x | | √ | √ | √ | | | | √ | √ | √ | | P010_UV_UNORM | UV planar (32 bit) | 1x | | √ | √ | √ | | | | √ | √ | √ | | TP10_UNORM | YUV planar ((32/3)/(32/3) bit) | 1x | | √ | √ | | | √ | | | | | | TP10_Y_UNORM | Y planar (32/3 bit) | 1x | | √ | √ | | | √ | | | | √ | | TP10_UV_UNORM | UV planar (32/3 bit) | 1x | | √ | √ | | | √ | | | | √ | | R24_UNORM_X8_TYPELESS | Depth/stencil (32 bit) | 8x | | | √ | √ | √ | | | | | | | ATI_TC_RGB | Compressed (64 bit) | 1x | √ | √ | √ | | | | | | | | | ATI_TC_RGBA | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | | ATI_TC_RGBA_INTERP | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | | EACX2_RG11_UNSIGNED | Compressed (128 bit) | 1x | | √ | √ | | | | | | | | | EACX2_RG11_SIGNED | Compressed (128 bit) | 1x | | √ | √ | | | | | | | | | EAC_R11_UNSIGNED | Compressed (64 bit) | 1x | | √ | √ | | | | | | | | | EAC_R11_SIGNED | Compressed (64 bit) | 1x | | √ | √ | | | | | | | | | ETC1_RGB | Compressed (64 bit) | 1x | √ | √ | √ | | | | | | | | | ETC2_RGB8 | Compressed (64 bit) | 1x | √ | √ | √ | | | | | | | | | ETC2A_RGBA8 | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | | ETC2_PTA_RGBA8 | Compressed (64 bit) | 1x | √ | √ | √ | | | | | | | | | BC1_UNORM | Compressed (64 bit) | 1x | √ | √ | √ | | | | | | | | | BC2_UNORM | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | | BC3_UNORM | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | | BC4_UNORM | Compressed (64 bit) | 1x | | √ | √ | | | | | | | | | BC4_UNORM_FAST | Compressed (64 bit) | 1x | | √ | √ | | | | | | | | | BC4_SNORM | Compressed (64 bit) | 1x | | √ | √ | | | | | | | | | BC4_SNORM_FAST | Compressed (64 bit) | 1x | | √ | √ | | | | | | | | | BC5_UNORM | Compressed (128 bit) | 1x | | √ | √ | | | | | | | | | BC5_UNORM_FAST | Compressed (128 bit) | 1x | | √ | √ | | | | | | | | | BC5_SNORM | Compressed (128 bit) | 1x | | √ | √ | | | | | | | | | BC5_SNORM_FAST | Compressed (128 bit) | 1x | | √ | √ | | | | | | | | | BC6H_UFP16 | Compressed (128 bit) | 1x | | √ | √ | | | | | | | | | BC6H_SFP16 | Compressed (128 bit) | 1x | | √ | √ | | | | | | | | | BC7_UNORM | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | | ASTC_4X4 | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | | ASTC_5X4 | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | | ASTC_5X5 | Compressed (128 bit) | 1x | √ | √ | √ | | | | | | | | ### Feature Key - **√**: Supported - **Blank**: Not Supported *Note: The '8x' and '1x' columns likely refer to specific hardware or API capabilities not detailed here.* ``` -------------------------------- ### Add vectors using NEON intrinsics Source: https://docs.qualcomm.com/doc/80-78185-2/topic/performance_optimization.html Demonstrates loading two sets of four 32-bit integers into vector registers and adding them using NEON intrinsic functions. ```C uint32x4_t sumVector(uint32_t* A, uint32_t* B) { uint32x4_t temp = vld1q_u32(A); uint32x4_t temp1 = vld1q_u32(B); uint32x4_t vec128 = vaddq_u32(temp, temp1); return vec128; } ``` -------------------------------- ### Structure of Arrays (SoA) Addition Source Code Source: https://docs.qualcomm.com/doc/80-78185-2/topic/performance_optimization.html C++ implementation using a structure of arrays to pack four vectors for simultaneous computation. ```cpp struct FloatVectorSoA { float X[4]; float Y[4]; float Z[4]; float W[4]; }; void sumSoAFloat(FloatVectorSoA& __restrict A, FloatVectorSoA& __restrict B, FloatVectorSoA& R) { for (int i=0;i<4;i++) { R.X[i] = A.X[i] + B.X[i]; R.Y[i] = A.Y[i] + B.Y[i]; R.Z[i] = A.Z[i] + B.Z[i]; R.W[i] = A.W[i] + B.W[i]; } } ``` -------------------------------- ### Texture Format Reference Source: https://docs.qualcomm.com/doc/80-78185-2/topic/spec_sheets.html A comprehensive list of supported texture formats and their technical specifications. ```APIDOC ## Texture Format Specifications ### Description This table defines the supported texture formats, their bit depth, and hardware capability flags. ### Data Formats | Format | Bit Depth | Support Features | | :--- | :--- | :--- | | R32G32_UINT | 64 bit | 8x | | R32G32_SINT | 64 bit | 8x | | R32G32_S15_16_FIXED | 64 bit | - | | R32G32B32_UNORM | 96 bit | - | | R32G32B32_SNORM | 96 bit | - | | R32G32B32_UINT | 96 bit | 1x | | R32G32B32_SINT | 96 bit | 1x | | R32G32B32_FP32 | 96 bit | 1x | | R32G32B32_S15_16_FIXED | 96 bit | - | | R32G32B32A32_UNORM | 128 bit | - | | R32G32B32A32_SNORM | 128 bit | - | | R32G32B32A32_FP32 | 128 bit | 8x | | R32G32B32A32_UINT | 128 bit | 8x | | R32G32B32A32_SINT | 128 bit | 8x | | R32G32B32A32_S15_16_FIXED | 128 bit | - | | UYVY_UNORM | YUV packed (16 bit) | 1x | | YUY2_UNORM | YUV packed (16 bit) | 1x | | NV12_UNORM | YUV planar (8/16 bit) | 1x | | NV21_UNORM | YUV planar (8/16 bit) | 1x | | IYUV_UNORM | YUV planar (8 bit) | 1x | | Y8U8V8A8_UNORM | YUV packed (32 bit) | 1x | | YVYU_UNORM | YUV packed (16 bit) | 1x | | VYUY_UNORM | YUV packed (16 bit) | 1x | | R24_UNORM_X8_TYPELESS | Depth/stencil (32 bit) | 8x | | ATI_TC_RGB | Compressed (64 bit) | 1x | | ATI_TC_RGBA | Compressed (128 bit) | 1x | | ATI_TC_RGBA_INTERP | Compressed (128 bit) | 1x | | EACX2_RG11_UNSIGNED | Compressed (128 bit) | 1x | | EACX2_RG11_SIGNED | Compressed (128 bit) | 1x | | EAC_R11_UNSIGNED | Compressed (64 bit) | 1x | | EAC_R11_SIGNED | Compressed (64 bit) | 1x | | ETC1_RGB | Compressed (64 bit) | 1x | | ETC2_RGB8 | Compressed (64 bit) | 1x | | ETC2A_RGBA8 | Compressed (128 bit) | 1x | | ETC2_PTA_RGBA8 | Compressed (64 bit) | 1x | | BC1_UNORM | Compressed (64 bit) | 1x | | BC2_UNORM | Compressed (128 bit) | 1x | | BC3_UNORM | Compressed (128 bit) | 1x | | BC4_UNORM | Compressed (64 bit) | 1x | | BC4_UNORM_FAST | Compressed (64 bit) | 1x | | BC4_SNORM | Compressed (64 bit) | 1x | | BC4_SNORM_FAST | Compressed (64 bit) | 1x | | BC5_UNORM | Compressed (128 bit) | 1x | | BC5_UNORM_FAST | Compressed (128 bit) | 1x | | BC5_SNORM | Compressed (128 bit) | 1x | | BC5_SNORM_FAST | Compressed (128 bit) | 1x | | BC6H_UFP16 | Compressed (128 bit) | 1x | | BC6H_SFP16 | Compressed (128 bit) | 1x | | BC7_UNORM | Compressed (128 bit) | 1x | | ASTC_4X4 | Compressed (128 bit) | 1x | | ASTC_5X4 | Compressed (128 bit) | 1x | | ASTC_5X5 | Compressed (128 bit) | 1x | | ASTC_6X5 | Compressed (128 bit) | 1x | | ASTC_6X6 | Compressed (128 bit) | 1x | | ASTC_8X5 | Compressed (128 bit) | 1x | | ASTC_8X6 | Compressed (128 bit) | 1x | | ASTC_8X8 | Compressed (128 bit) | 1x | | ASTC_10X5 | Compressed (128 bit) | 1x | | ASTC_10X6 | Compressed (128 bit) | 1x | | ASTC_10X8 | Compressed (128 bit) | 1x | | ASTC_10X10 | Compressed (128 bit) | 1x | | ASTC_12X10 | Compressed (128 bit) | 1x | | ASTC_12X12 | Compressed (128 bit) | 1x | | ASTC_3X3X3 | Compressed (128 bit) | 1x | | ASTC_4X3X3 | Compressed (128 bit) | 1x | | ASTC_4X4X3 | Compressed (128 bit) | 1x | | ASTC_4X4X4 | Compressed (128 bit) | 1x | | ASTC_5X4X4 | Compressed (128 bit) | 1x | ``` -------------------------------- ### Optimize scalar constant usage with vector packing Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Packing scalar constants into vectors can improve hardware fetch effectiveness and enable more efficient instructions like 'mad'. ```GLSL float scale, bias; vec4 a = Pos * scale + bias; ``` ```GLSL vec2 scaleNbias; vec4 a = Pos * scaleNbias.x + scaleNbias.y; ``` -------------------------------- ### Set EGLSurface color space to BT.2020 PQ Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Create an EGL window surface with the color space set to EGL_GL_COLORSPACE_BT2020_PQ_EXT. This is useful for HDR content. ```c EGLint attribs[] = {EGL_GL_COLORSPACE_KHR,EGL_GL_COLORSPACE_BT2020_PQ_EXT,EGL_NONE }; EGLSurface eglSurface=eglCreateWidowSurface(eglDisplay,eglConfigParam, InWindow, attribs); ``` -------------------------------- ### Structure of Arrays (SoA) Addition Assembly Output Source: https://docs.qualcomm.com/doc/80-78185-2/topic/performance_optimization.html Assembly output for SoA vector addition. ```asm ldp q24, q29, [x0] ldp q28, q25, [x1] ldp q30, q31, [x0, 32] ldp q26, q27, [x1, 32] fadd v28.4s, v28.4s, v24.4s fadd v29.4s, v29.4s, v25.4s fadd v30.4s, v30.4s, v26.4s fadd v31.4s, v31.4s, v27.4s stp q28, q29, [x2] stp q30, q31, [x2, 32] ret ``` ```asm ldp q0, q3, [x1] ldp q1, q2, [x0] fadd v0.4s, v1.4s, v0.4s ldp q1, q5, [x0, #32] fadd v2.4s, v2.4s, v3.4s ldp q4, q3, [x1, #32] fadd v1.4s, v1.4s, v4.4s fadd v3.4s, v5.4s, v3.4s stp q0, q2, [x2] stp q1, q3, [x2, #32] ret ``` ```asm add x9,x2,#0x20 add x8,x1,#0x10 sub x13,x0,x1 sub x12,x2,x1 sub x11,x0,x2 mov x10,#4 ``` -------------------------------- ### Retrieve Program Binary (OpenGL ES 3.0+) Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Use glGetProgramBinary to retrieve the binary representation of a linked program object in OpenGL ES 3.0 and 3.1 contexts. This allows for saving and loading compiled shaders, speeding up application launch. ```c glGetProgramBinary( program, bufSize, length, binaryFormat, binary ); ``` -------------------------------- ### Set EGLSurface format to R10G10B10A2 Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Configure EGL to choose a config with 10 bits for red, green, blue, and 2 bits for alpha. Ensure EGL_COLOR_COMPONENT_TYPE_EXT is set to EGL_COLOR_COMPONENT_TYPE_FIXED_EXT. ```c EGLConfig EGLConfigList [1]; int ConfigAttributes [] = { EGL_RED_SIZE,10 EGL_GREEN_SIZE,10 EGL_BLUE_SIZE,10 EGL_ALPHA_SIZE,2 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT, EGL_NONE}; eglChooseConfig (eglDisplay,ConfigAttributes,EGLConfigList,1, eglNumConfigs); ``` -------------------------------- ### Perform Ray Query without Loop Source: https://docs.qualcomm.com/doc/80-78185-2/topic/mobile_best_practices.html Simplifies ray traversal by removing the while loop when using termination flags like gl_RayFlagsTerminateOnFirstHitEXT. ```GLSL rayQueryEXT rayQuery; rayQueryInitializeEXT(rayQuery, rayTraceAS, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsCullOpaqueEXT, cullMask, WorldPos, minDistance, DirectionToLight, LightDistance); // Traverse the query. No need for a while(), since we want first hit or // non-opaque intersections only rayQueryProceedEXT(rayQuery)); // Determine if the shadow query collided if(rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT) { // Got an intersection == Shadow, do something } ```