15bd8deadSopenharmony_ciName 25bd8deadSopenharmony_ci 35bd8deadSopenharmony_ci AMD_performance_monitor 45bd8deadSopenharmony_ci 55bd8deadSopenharmony_ciName Strings 65bd8deadSopenharmony_ci 75bd8deadSopenharmony_ci GL_AMD_performance_monitor 85bd8deadSopenharmony_ci 95bd8deadSopenharmony_ciContributors 105bd8deadSopenharmony_ci 115bd8deadSopenharmony_ci Dan Ginsburg 125bd8deadSopenharmony_ci Aaftab Munshi 135bd8deadSopenharmony_ci Dave Oldcorn 145bd8deadSopenharmony_ci Maurice Ribble 155bd8deadSopenharmony_ci Jonathan Zarge 165bd8deadSopenharmony_ci 175bd8deadSopenharmony_ciContact 185bd8deadSopenharmony_ci 195bd8deadSopenharmony_ci Dan Ginsburg (dan.ginsburg 'at' amd.com) 205bd8deadSopenharmony_ci 215bd8deadSopenharmony_ciStatus 225bd8deadSopenharmony_ci 235bd8deadSopenharmony_ci ??? 245bd8deadSopenharmony_ci 255bd8deadSopenharmony_ciVersion 265bd8deadSopenharmony_ci 275bd8deadSopenharmony_ci Last Modified Date: 11/29/2007 285bd8deadSopenharmony_ci 295bd8deadSopenharmony_ciNumber 305bd8deadSopenharmony_ci 315bd8deadSopenharmony_ci OpenGL Extension #360 325bd8deadSopenharmony_ci OpenGL ES Extension #50 335bd8deadSopenharmony_ci 345bd8deadSopenharmony_ciDependencies 355bd8deadSopenharmony_ci 365bd8deadSopenharmony_ci None 375bd8deadSopenharmony_ci 385bd8deadSopenharmony_ciOverview 395bd8deadSopenharmony_ci 405bd8deadSopenharmony_ci This extension enables the capture and reporting of performance monitors. 415bd8deadSopenharmony_ci Performance monitors contain groups of counters which hold arbitrary counted 425bd8deadSopenharmony_ci data. Typically, the counters hold information on performance-related 435bd8deadSopenharmony_ci counters in the underlying hardware. The extension is general enough to 445bd8deadSopenharmony_ci allow the implementation to choose which counters to expose and pick the 455bd8deadSopenharmony_ci data type and range of the counters. The extension also allows counting to 465bd8deadSopenharmony_ci start and end on arbitrary boundaries during rendering. 475bd8deadSopenharmony_ci 485bd8deadSopenharmony_ciIssues 495bd8deadSopenharmony_ci 505bd8deadSopenharmony_ci 1. Should this be an EGL or OpenGL/OpenGL ES extension? 515bd8deadSopenharmony_ci 525bd8deadSopenharmony_ci Decision - Make this an OpenGL/OpenGL ES extension 535bd8deadSopenharmony_ci 545bd8deadSopenharmony_ci Reason - We would like to expose this extension in both OpenGL and 555bd8deadSopenharmony_ci OpenGL ES which makes EGL an unsuitable choice. Further, support for 565bd8deadSopenharmony_ci EGL is not a requirement and there are platforms that support OpenGL ES 575bd8deadSopenharmony_ci but not EGL, making it difficult to make this an EGL extension. 585bd8deadSopenharmony_ci 595bd8deadSopenharmony_ci 2. Should the API support multipassing? 605bd8deadSopenharmony_ci 615bd8deadSopenharmony_ci Decision - No. 625bd8deadSopenharmony_ci 635bd8deadSopenharmony_ci Reason - Multipassing should really be left to the application to do. 645bd8deadSopenharmony_ci This makes the API unnecessarily complicated. A major issue is that 655bd8deadSopenharmony_ci depending on which counters are to be sampled, the # of passes and which 665bd8deadSopenharmony_ci counters get selected in each pass can be difficult to determine. It is 675bd8deadSopenharmony_ci much easier to give a list of counters categorized by groups with 685bd8deadSopenharmony_ci specific information on the number of counters that can be selected from 695bd8deadSopenharmony_ci each group. 705bd8deadSopenharmony_ci 715bd8deadSopenharmony_ci 3. Should we define a 64-bit data type for UNSIGNED_INT64_AMD? 725bd8deadSopenharmony_ci 735bd8deadSopenharmony_ci Decision - No. 745bd8deadSopenharmony_ci 755bd8deadSopenharmony_ci Reason - While counters can be returned as 64-bit unsigned integers, the 765bd8deadSopenharmony_ci data is passed back to the application inside of a void*. Therefore, 775bd8deadSopenharmony_ci there is no need in this extension to define a 64-bit data type (e.g., 785bd8deadSopenharmony_ci GLuint64). It will be up the application to declare a native 64-bit 795bd8deadSopenharmony_ci unsigned integer and cast the returned data to that type. 805bd8deadSopenharmony_ci 815bd8deadSopenharmony_ci 825bd8deadSopenharmony_ciNew Procedures and Functions 835bd8deadSopenharmony_ci 845bd8deadSopenharmony_ci void GetPerfMonitorGroupsAMD(int *numGroups, sizei groupsSize, 855bd8deadSopenharmony_ci uint *groups) 865bd8deadSopenharmony_ci 875bd8deadSopenharmony_ci void GetPerfMonitorCountersAMD(uint group, int *numCounters, 885bd8deadSopenharmony_ci int *maxActiveCounters, sizei countersSize, 895bd8deadSopenharmony_ci uint *counters) 905bd8deadSopenharmony_ci 915bd8deadSopenharmony_ci void GetPerfMonitorGroupStringAMD(uint group, sizei bufSize, sizei *length, 925bd8deadSopenharmony_ci char *groupString) 935bd8deadSopenharmony_ci 945bd8deadSopenharmony_ci void GetPerfMonitorCounterStringAMD(uint group, uint counter, sizei bufSize, 955bd8deadSopenharmony_ci sizei *length, char *counterString) 965bd8deadSopenharmony_ci 975bd8deadSopenharmony_ci void GetPerfMonitorCounterInfoAMD(uint group, uint counter, 985bd8deadSopenharmony_ci enum pname, void *data) 995bd8deadSopenharmony_ci 1005bd8deadSopenharmony_ci void GenPerfMonitorsAMD(sizei n, uint *monitors) 1015bd8deadSopenharmony_ci 1025bd8deadSopenharmony_ci void DeletePerfMonitorsAMD(sizei n, uint *monitors) 1035bd8deadSopenharmony_ci 1045bd8deadSopenharmony_ci void SelectPerfMonitorCountersAMD(uint monitor, boolean enable, 1055bd8deadSopenharmony_ci uint group, int numCounters, 1065bd8deadSopenharmony_ci uint *counterList) 1075bd8deadSopenharmony_ci 1085bd8deadSopenharmony_ci void BeginPerfMonitorAMD(uint monitor) 1095bd8deadSopenharmony_ci 1105bd8deadSopenharmony_ci void EndPerfMonitorAMD(uint monitor) 1115bd8deadSopenharmony_ci 1125bd8deadSopenharmony_ci void GetPerfMonitorCounterDataAMD(uint monitor, enum pname, sizei dataSize, 1135bd8deadSopenharmony_ci uint *data, int *bytesWritten) 1145bd8deadSopenharmony_ci 1155bd8deadSopenharmony_ci 1165bd8deadSopenharmony_ciNew Tokens 1175bd8deadSopenharmony_ci 1185bd8deadSopenharmony_ci Accepted by the <pame> parameter of GetPerfMonitorCounterInfoAMD 1195bd8deadSopenharmony_ci 1205bd8deadSopenharmony_ci COUNTER_TYPE_AMD 0x8BC0 1215bd8deadSopenharmony_ci COUNTER_RANGE_AMD 0x8BC1 1225bd8deadSopenharmony_ci 1235bd8deadSopenharmony_ci Returned as a valid value in <data> parameter of 1245bd8deadSopenharmony_ci GetPerfMonitorCounterInfoAMD if <pname> = COUNTER_TYPE_AMD 1255bd8deadSopenharmony_ci 1265bd8deadSopenharmony_ci UNSIGNED_INT 0x1405 1275bd8deadSopenharmony_ci FLOAT 0x1406 1285bd8deadSopenharmony_ci UNSIGNED_INT64_AMD 0x8BC2 1295bd8deadSopenharmony_ci PERCENTAGE_AMD 0x8BC3 1305bd8deadSopenharmony_ci 1315bd8deadSopenharmony_ci Accepted by the <pname> parameter of GetPerfMonitorCounterDataAMD 1325bd8deadSopenharmony_ci 1335bd8deadSopenharmony_ci PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 1345bd8deadSopenharmony_ci PERFMON_RESULT_SIZE_AMD 0x8BC5 1355bd8deadSopenharmony_ci PERFMON_RESULT_AMD 0x8BC6 1365bd8deadSopenharmony_ci 1375bd8deadSopenharmony_ciAddition to the GL specification 1385bd8deadSopenharmony_ci 1395bd8deadSopenharmony_ci Add a new section called Performance Monitoring 1405bd8deadSopenharmony_ci 1415bd8deadSopenharmony_ci A performance monitor consists of a number of hardware and software counters 1425bd8deadSopenharmony_ci that can be sampled by the GPU and reported back to the application. 1435bd8deadSopenharmony_ci Performance counters are organized as a single hierarchy where counters are 1445bd8deadSopenharmony_ci categorized into groups. Each group has a list of counters that belong to 1455bd8deadSopenharmony_ci the counter and can be sampled, and a maximum number of counters that can be 1465bd8deadSopenharmony_ci sampled. 1475bd8deadSopenharmony_ci 1485bd8deadSopenharmony_ci The command 1495bd8deadSopenharmony_ci 1505bd8deadSopenharmony_ci void GetPerfMonitorGroupsAMD(int *numGroups, sizei groupsSize, 1515bd8deadSopenharmony_ci uint *groups); 1525bd8deadSopenharmony_ci 1535bd8deadSopenharmony_ci returns the number of available groups in <numGroups>, if <numGroups> is 1545bd8deadSopenharmony_ci not NULL. If <groupsSize> is not 0 and <groups> is not NULL, then the list 1555bd8deadSopenharmony_ci of available groups is returned. The number of entries that will be 1565bd8deadSopenharmony_ci returned in <groups> is determined by <groupsSize>. If <groupsSize> is 0, 1575bd8deadSopenharmony_ci no information is copied. Each group is identified by a unique unsigned int 1585bd8deadSopenharmony_ci identifier. 1595bd8deadSopenharmony_ci 1605bd8deadSopenharmony_ci The command 1615bd8deadSopenharmony_ci 1625bd8deadSopenharmony_ci void GetPerfMonitorCountersAMD(uint group, int *numCounters, 1635bd8deadSopenharmony_ci int *maxActiveCounters, 1645bd8deadSopenharmony_ci sizei countersSize, 1655bd8deadSopenharmony_ci uint *counters); 1665bd8deadSopenharmony_ci 1675bd8deadSopenharmony_ci returns the following information. For each group, it returns the number of 1685bd8deadSopenharmony_ci available counters in <numCounters>, the max number of counters that can be 1695bd8deadSopenharmony_ci active at any time in <maxActiveCounters>, and the list of counters in 1705bd8deadSopenharmony_ci <counters>. The number of entries that can be returned in <counters> is 1715bd8deadSopenharmony_ci determined by <countersSize>. If <countersSize> is 0, no information is 1725bd8deadSopenharmony_ci copied. Each counter in a group is identified by a unique unsigned int 1735bd8deadSopenharmony_ci identifier. If <group> does not reference a valid group ID, an 1745bd8deadSopenharmony_ci INVALID_VALUE error is generated. 1755bd8deadSopenharmony_ci 1765bd8deadSopenharmony_ci 1775bd8deadSopenharmony_ci The command 1785bd8deadSopenharmony_ci 1795bd8deadSopenharmony_ci void GetPerfMonitorGroupStringAMD(uint group, sizei bufSize, 1805bd8deadSopenharmony_ci sizei *length, char *groupString) 1815bd8deadSopenharmony_ci 1825bd8deadSopenharmony_ci 1835bd8deadSopenharmony_ci returns the string that describes the group name identified by <group> in 1845bd8deadSopenharmony_ci <groupString>. The actual number of characters written to <groupString>, 1855bd8deadSopenharmony_ci excluding the null terminator, is returned in <length>. If <length> is 1865bd8deadSopenharmony_ci NULL, then no length is returned. The maximum number of characters that 1875bd8deadSopenharmony_ci may be written into <groupString>, including the null terminator, is 1885bd8deadSopenharmony_ci specified by <bufSize>. If <bufSize> is 0 and <groupString> is NULL, the 1895bd8deadSopenharmony_ci number of characters that would be required to hold the group string, 1905bd8deadSopenharmony_ci excluding the null terminator, is returned in <length>. If <group> 1915bd8deadSopenharmony_ci does not reference a valid group ID, an INVALID_VALUE error is generated. 1925bd8deadSopenharmony_ci 1935bd8deadSopenharmony_ci 1945bd8deadSopenharmony_ci The command 1955bd8deadSopenharmony_ci 1965bd8deadSopenharmony_ci void GetPerfMonitorCounterStringAMD(uint group, uint counter, 1975bd8deadSopenharmony_ci sizei bufSize, sizei *length, 1985bd8deadSopenharmony_ci char *counterString); 1995bd8deadSopenharmony_ci 2005bd8deadSopenharmony_ci 2015bd8deadSopenharmony_ci returns the string that describes the counter name identified by <group> 2025bd8deadSopenharmony_ci and <counter> in <counterString>. The actual number of characters written 2035bd8deadSopenharmony_ci to <counterString>, excluding the null terminator, is returned in <length>. 2045bd8deadSopenharmony_ci If <length> is NULL, then no length is returned. The maximum number of 2055bd8deadSopenharmony_ci characters that may be written into <counterString>, including the null 2065bd8deadSopenharmony_ci terminator, is specified by <bufSize>. If <bufSize> is 0 and 2075bd8deadSopenharmony_ci <counterString> is NULL, the number of characters that would be required to 2085bd8deadSopenharmony_ci hold the counter string, excluding the null terminator, is returned in 2095bd8deadSopenharmony_ci <length>. If <group> does not reference a valid group ID, or <counter> 2105bd8deadSopenharmony_ci does not reference a valid counter within the group ID, an INVALID_VALUE 2115bd8deadSopenharmony_ci error is generated. 2125bd8deadSopenharmony_ci 2135bd8deadSopenharmony_ci The command 2145bd8deadSopenharmony_ci 2155bd8deadSopenharmony_ci void GetPerfMonitorCounterInfoAMD(uint group, uint counter, 2165bd8deadSopenharmony_ci enum pname, void *data); 2175bd8deadSopenharmony_ci 2185bd8deadSopenharmony_ci returns the following information about a counter. For a <counter> 2195bd8deadSopenharmony_ci belonging to <group>, we can query the counter type and counter range. If 2205bd8deadSopenharmony_ci <pname> is COUNTER_TYPE_AMD, then <data> returns the type. Valid type 2215bd8deadSopenharmony_ci values returned are UNSIGNED_INT, UNSIGNED_INT64_AMD, PERCENTAGE_AMD, FLOAT. 2225bd8deadSopenharmony_ci If type value returned is PERCENTAGE_AMD, then this describes a float 2235bd8deadSopenharmony_ci value that is in the range [0.0 .. 100.0]. If <pname> is COUNTER_RANGE_AMD, 2245bd8deadSopenharmony_ci <data> returns two values representing a minimum and a maximum. The 2255bd8deadSopenharmony_ci counter's type is used to determine the format in which the range values 2265bd8deadSopenharmony_ci are returned. If <group> does not reference a valid group ID, or <counter> 2275bd8deadSopenharmony_ci does not reference a valid counter within the group ID, an INVALID_VALUE 2285bd8deadSopenharmony_ci error is generated. 2295bd8deadSopenharmony_ci 2305bd8deadSopenharmony_ci 2315bd8deadSopenharmony_ci The command 2325bd8deadSopenharmony_ci 2335bd8deadSopenharmony_ci void GenPerfMonitorsAMD(sizei n, uint *monitors) 2345bd8deadSopenharmony_ci 2355bd8deadSopenharmony_ci returns a list of monitors. These monitors can then be used to select 2365bd8deadSopenharmony_ci groups/counters to be sampled, to start multiple monitoring sessions and to 2375bd8deadSopenharmony_ci return counter information sampled by the GPU. At creation time, the 2385bd8deadSopenharmony_ci performance monitor object has all counters disabled. The value of the 2395bd8deadSopenharmony_ci PERFMON_RESULT_AVAILABLE_AMD, PERFMON_RESULT_AMD, and 2405bd8deadSopenharmony_ci PERFMON_RESULT_SIZE_AMD queries will all initially be 0. 2415bd8deadSopenharmony_ci 2425bd8deadSopenharmony_ci The command 2435bd8deadSopenharmony_ci 2445bd8deadSopenharmony_ci void DeletePerfMonitorsAMD(sizei n, uint *monitors) 2455bd8deadSopenharmony_ci 2465bd8deadSopenharmony_ci is used to delete the list of monitors created by a previous call to 2475bd8deadSopenharmony_ci GenPerfMonitors. If a monitor ID in the list <monitors> does not 2485bd8deadSopenharmony_ci reference a previously generated performance monitor, an INVALID_VALUE 2495bd8deadSopenharmony_ci error is generated. 2505bd8deadSopenharmony_ci 2515bd8deadSopenharmony_ci The command 2525bd8deadSopenharmony_ci 2535bd8deadSopenharmony_ci void SelectPerfMonitorCountersAMD(uint monitor, boolean enable, 2545bd8deadSopenharmony_ci uint group, int numCounters, 2555bd8deadSopenharmony_ci uint *counterList); 2565bd8deadSopenharmony_ci 2575bd8deadSopenharmony_ci is used to enable or disable a list of counters from a group to be monitored 2585bd8deadSopenharmony_ci as identified by <monitor>. The <enable> argument determines whether the 2595bd8deadSopenharmony_ci counters should be enabled or disabled. <group> specifies the group 2605bd8deadSopenharmony_ci ID under which counters will be enabled or disabled. The <numCounters> 2615bd8deadSopenharmony_ci argument gives the number of counters to be selected from the list 2625bd8deadSopenharmony_ci <counterList>. If <monitor> is not a valid monitor created by 2635bd8deadSopenharmony_ci GenPerfMonitorsAMD, then INVALID_VALUE error will be generated. If <group> 2645bd8deadSopenharmony_ci is not a valid group, the INVALID_VALUE error will be generated. If 2655bd8deadSopenharmony_ci <numCounters> is less than 0, an INVALID_VALUE error will be generated. 2665bd8deadSopenharmony_ci 2675bd8deadSopenharmony_ci When SelectPerfMonitorCountersAMD is called on a monitor, any outstanding 2685bd8deadSopenharmony_ci results for that monitor become invalidated and the result queries 2695bd8deadSopenharmony_ci PERFMON_RESULT_SIZE_AMD and PERFMON_RESULT_AVAILABLE_AMD are reset to 0. 2705bd8deadSopenharmony_ci 2715bd8deadSopenharmony_ci The command 2725bd8deadSopenharmony_ci 2735bd8deadSopenharmony_ci void BeginPerfMonitorAMD(uint monitor); 2745bd8deadSopenharmony_ci 2755bd8deadSopenharmony_ci is used to start a monitor session. Note that BeginPerfMonitor calls cannot 2765bd8deadSopenharmony_ci be nested. In addition, it is quite possible that given the list of groups 2775bd8deadSopenharmony_ci and counters/group enabled for a monitor, it may not be able to sample the 2785bd8deadSopenharmony_ci necessary counters and so the monitor session will fail. In such a case, 2795bd8deadSopenharmony_ci an INVALID_OPERATION error will be generated. 2805bd8deadSopenharmony_ci 2815bd8deadSopenharmony_ci While BeginPerfMonitorAMD does mark the beginning of performance counter 2825bd8deadSopenharmony_ci collection, the counters do not begin collecting immediately. Rather, the 2835bd8deadSopenharmony_ci counters begin collection when BeginPerfMonitorAMD is processed by 2845bd8deadSopenharmony_ci the hardware. That is, the API is asynchronous, and performance counter 2855bd8deadSopenharmony_ci collection does not begin until the graphics hardware processes the 2865bd8deadSopenharmony_ci BeginPerfMonitorAMD command. 2875bd8deadSopenharmony_ci 2885bd8deadSopenharmony_ci The command 2895bd8deadSopenharmony_ci 2905bd8deadSopenharmony_ci void EndPerfMonitorAMD(uint monitor); 2915bd8deadSopenharmony_ci 2925bd8deadSopenharmony_ci ends a monitor session started by BeginPerfMonitorAMD. If a performance 2935bd8deadSopenharmony_ci monitor is not currently started, an INVALID_OPERATION error will be 2945bd8deadSopenharmony_ci generated. 2955bd8deadSopenharmony_ci 2965bd8deadSopenharmony_ci Note that there is an implied overhead to collecting performance counters 2975bd8deadSopenharmony_ci that may or may not distort performance depending on the implementation. 2985bd8deadSopenharmony_ci For example, some counters may require a pipeline flush thereby causing a 2995bd8deadSopenharmony_ci change in the performance of the application. Further, the frequency at 3005bd8deadSopenharmony_ci which an application samples may distort the accuracy of counters which are 3015bd8deadSopenharmony_ci variant (e.g., non-deterministic based on the input). While the effects 3025bd8deadSopenharmony_ci of sampling frequency are implementation dependent, general guidance can 3035bd8deadSopenharmony_ci be given that sampling at a high frequency may distort both performance 3045bd8deadSopenharmony_ci of the application and the accuracy of variant counters. 3055bd8deadSopenharmony_ci 3065bd8deadSopenharmony_ci The command 3075bd8deadSopenharmony_ci 3085bd8deadSopenharmony_ci void GetPerfMonitorCounterDataAMD(uint monitor, enum pname, 3095bd8deadSopenharmony_ci sizei dataSize, 3105bd8deadSopenharmony_ci uint *data, sizei *bytesWritten); 3115bd8deadSopenharmony_ci 3125bd8deadSopenharmony_ci is used to return counter values that have been sampled for a monitor 3135bd8deadSopenharmony_ci session. If <pname> is PERFMON_RESULT_AVAILABLE_AMD, then <data> will 3145bd8deadSopenharmony_ci indicate whether the result is available or not. If <pname> is 3155bd8deadSopenharmony_ci PERFMON_RESULT_SIZE_AMD, <data> will contain actual size of all counter 3165bd8deadSopenharmony_ci results being sampled. If <pname> is PERFMON_RESULT_AMD, <data> will 3175bd8deadSopenharmony_ci contain results. For each counter of a group that was selected to be 3185bd8deadSopenharmony_ci sampled, the information is returned as group ID, followed by counter ID, 3195bd8deadSopenharmony_ci followed by counter value. The size of counter value returned will depend 3205bd8deadSopenharmony_ci on the counter value type. The argument <dataSize> specifies the number of 3215bd8deadSopenharmony_ci bytes available in the <data> buffer for writing. If <bytesWritten> is not 3225bd8deadSopenharmony_ci NULL, it gives the number of bytes written into the <data> buffer. It is an 3235bd8deadSopenharmony_ci INVALID_OPERATION error for <data> to be NULL. If <pname> is 3245bd8deadSopenharmony_ci PERFMON_RESULT_AMD and <dataSize> is less than the number of bytes required 3255bd8deadSopenharmony_ci to store the results as reported by a PERFMON_RESULT_SIZE_AMD query, then 3265bd8deadSopenharmony_ci results will be written only up to the number of bytes specified by 3275bd8deadSopenharmony_ci <dataSize>. 3285bd8deadSopenharmony_ci 3295bd8deadSopenharmony_ci If no BeginPerfMonitorAMD/EndPerfMonitorAMD has been issued for a monitor, 3305bd8deadSopenharmony_ci then the result of querying for PERFMON_RESULT_AVAILABLE and 3315bd8deadSopenharmony_ci PERFMON_RESULT_SIZE will be 0. When SelectPerfMonitorCountersAMD is called 3325bd8deadSopenharmony_ci on a monitor, the results stored for the monitor become invalidated and 3335bd8deadSopenharmony_ci the value of PERFMON_RESULT_AVAILABLE and PERFMON_RESULT_SIZE queries should 3345bd8deadSopenharmony_ci behave as if no BeginPerfMonitorAMD/EndPerfMonitorAMD has been issued for 3355bd8deadSopenharmony_ci the monitor. 3365bd8deadSopenharmony_ci 3375bd8deadSopenharmony_ciErrors 3385bd8deadSopenharmony_ci 3395bd8deadSopenharmony_ci INVALID_OPERATION error will be generated if BeginPerfMonitorAMD is unable 3405bd8deadSopenharmony_ci to begin monitoring with the currently selected counters. 3415bd8deadSopenharmony_ci 3425bd8deadSopenharmony_ci INVALID_OPERATION error will be generated if BeginPerfMonitorAMD is called 3435bd8deadSopenharmony_ci when a performance monitor is already active. 3445bd8deadSopenharmony_ci 3455bd8deadSopenharmony_ci INVALID_OPERATION error will be generated if EndPerfMonitorAMD is called 3465bd8deadSopenharmony_ci when a performance monitor is not currently started. 3475bd8deadSopenharmony_ci 3485bd8deadSopenharmony_ci INVALID_VALUE error will be generated if the <group> parameter to 3495bd8deadSopenharmony_ci GetPerfMonitorCountersAMD, GetPerfMonitorCounterStringAMD, 3505bd8deadSopenharmony_ci GetPerfMonitorCounterStringAMD, GetPerfMonitorCounterInfoAMD, or 3515bd8deadSopenharmony_ci SelectPerfMonitorCountersAMD does not reference a valid group ID. 3525bd8deadSopenharmony_ci 3535bd8deadSopenharmony_ci INVALID_VALUE error will be generated if the <counter> parameter to 3545bd8deadSopenharmony_ci GetPerfMonitorCounterInfoAMD does not reference a valid counter ID 3555bd8deadSopenharmony_ci in the group specified by <group>. 3565bd8deadSopenharmony_ci 3575bd8deadSopenharmony_ci INVALID_VALUE error will be generated if any of the monitor IDs 3585bd8deadSopenharmony_ci in the <monitors> parameter to DeletePerfMonitorsAMD do not reference 3595bd8deadSopenharmony_ci a valid generated monitor ID. 3605bd8deadSopenharmony_ci 3615bd8deadSopenharmony_ci INVALID_VALUE error will be generated if the <monitor> parameter to 3625bd8deadSopenharmony_ci SelectPerfMonitorCountersAMD does not reference a monitor created by 3635bd8deadSopenharmony_ci GenPerfMonitorsAMD. 3645bd8deadSopenharmony_ci 3655bd8deadSopenharmony_ci INVALID_VALUE error will be generated if the <numCounters> parameter to 3665bd8deadSopenharmony_ci SelectPerfMonitorCountersAMD is less than 0. 3675bd8deadSopenharmony_ci 3685bd8deadSopenharmony_ci 3695bd8deadSopenharmony_ci 3705bd8deadSopenharmony_ciNew State 3715bd8deadSopenharmony_ci 3725bd8deadSopenharmony_ciSample Usage 3735bd8deadSopenharmony_ci 3745bd8deadSopenharmony_ci typedef struct 3755bd8deadSopenharmony_ci { 3765bd8deadSopenharmony_ci GLuint *counterList; 3775bd8deadSopenharmony_ci int numCounters; 3785bd8deadSopenharmony_ci int maxActiveCounters; 3795bd8deadSopenharmony_ci } CounterInfo; 3805bd8deadSopenharmony_ci 3815bd8deadSopenharmony_ci void 3825bd8deadSopenharmony_ci getGroupAndCounterList(GLuint **groupsList, int *numGroups, 3835bd8deadSopenharmony_ci CounterInfo **counterInfo) 3845bd8deadSopenharmony_ci { 3855bd8deadSopenharmony_ci GLint n; 3865bd8deadSopenharmony_ci GLuint *groups; 3875bd8deadSopenharmony_ci CounterInfo *counters; 3885bd8deadSopenharmony_ci 3895bd8deadSopenharmony_ci glGetPerfMonitorGroupsAMD(&n, 0, NULL); 3905bd8deadSopenharmony_ci groups = (GLuint*) malloc(n * sizeof(GLuint)); 3915bd8deadSopenharmony_ci glGetPerfMonitorGroupsAMD(NULL, n, groups); 3925bd8deadSopenharmony_ci *numGroups = n; 3935bd8deadSopenharmony_ci 3945bd8deadSopenharmony_ci *groupsList = groups; 3955bd8deadSopenharmony_ci counters = (CounterInfo*) malloc(sizeof(CounterInfo) * n); 3965bd8deadSopenharmony_ci for (int i = 0 ; i < n; i++ ) 3975bd8deadSopenharmony_ci { 3985bd8deadSopenharmony_ci glGetPerfMonitorCountersAMD(groups[i], &counters[i].numCounters, 3995bd8deadSopenharmony_ci &counters[i].maxActiveCounters, 0, NULL); 4005bd8deadSopenharmony_ci 4015bd8deadSopenharmony_ci counters[i].counterList = (GLuint*)malloc(counters[i].numCounters * 4025bd8deadSopenharmony_ci sizeof(int)); 4035bd8deadSopenharmony_ci 4045bd8deadSopenharmony_ci glGetPerfMonitorCountersAMD(groups[i], NULL, NULL, 4055bd8deadSopenharmony_ci counters[i].numCounters, 4065bd8deadSopenharmony_ci counters[i].counterList); 4075bd8deadSopenharmony_ci } 4085bd8deadSopenharmony_ci 4095bd8deadSopenharmony_ci *counterInfo = counters; 4105bd8deadSopenharmony_ci } 4115bd8deadSopenharmony_ci 4125bd8deadSopenharmony_ci static int countersInitialized = 0; 4135bd8deadSopenharmony_ci 4145bd8deadSopenharmony_ci int 4155bd8deadSopenharmony_ci getCounterByName(char *groupName, char *counterName, GLuint *groupID, 4165bd8deadSopenharmony_ci GLuint *counterID) 4175bd8deadSopenharmony_ci { 4185bd8deadSopenharmony_ci int numGroups; 4195bd8deadSopenharmony_ci GLuint *groups; 4205bd8deadSopenharmony_ci CounterInfo *counters; 4215bd8deadSopenharmony_ci int i = 0; 4225bd8deadSopenharmony_ci 4235bd8deadSopenharmony_ci if (!countersInitialized) 4245bd8deadSopenharmony_ci { 4255bd8deadSopenharmony_ci getGroupAndCounterList(&groups, &numGroups, &counters); 4265bd8deadSopenharmony_ci countersInitialized = 1; 4275bd8deadSopenharmony_ci } 4285bd8deadSopenharmony_ci 4295bd8deadSopenharmony_ci for ( i = 0; i < numGroups; i++ ) 4305bd8deadSopenharmony_ci { 4315bd8deadSopenharmony_ci char curGroupName[256]; 4325bd8deadSopenharmony_ci glGetPerfMonitorGroupStringAMD(groups[i], 256, NULL, curGroupName); 4335bd8deadSopenharmony_ci if (strcmp(groupName, curGroupName) == 0) 4345bd8deadSopenharmony_ci { 4355bd8deadSopenharmony_ci *groupID = groups[i]; 4365bd8deadSopenharmony_ci break; 4375bd8deadSopenharmony_ci } 4385bd8deadSopenharmony_ci } 4395bd8deadSopenharmony_ci 4405bd8deadSopenharmony_ci if ( i == numGroups ) 4415bd8deadSopenharmony_ci return -1; // error - could not find the group name 4425bd8deadSopenharmony_ci 4435bd8deadSopenharmony_ci for ( int j = 0; j < counters[i].numCounters; j++ ) 4445bd8deadSopenharmony_ci { 4455bd8deadSopenharmony_ci char curCounterName[256]; 4465bd8deadSopenharmony_ci 4475bd8deadSopenharmony_ci glGetPerfMonitorCounterStringAMD(groups[i], 4485bd8deadSopenharmony_ci counters[i].counterList[j], 4495bd8deadSopenharmony_ci 256, NULL, curCounterName); 4505bd8deadSopenharmony_ci if (strcmp(counterName, curCounterName) == 0) 4515bd8deadSopenharmony_ci { 4525bd8deadSopenharmony_ci *counterID = counters[i].counterList[j]; 4535bd8deadSopenharmony_ci return 0; 4545bd8deadSopenharmony_ci } 4555bd8deadSopenharmony_ci } 4565bd8deadSopenharmony_ci 4575bd8deadSopenharmony_ci return -1; // error - could not find the counter name 4585bd8deadSopenharmony_ci } 4595bd8deadSopenharmony_ci 4605bd8deadSopenharmony_ci void 4615bd8deadSopenharmony_ci drawFrameWithCounters(void) 4625bd8deadSopenharmony_ci { 4635bd8deadSopenharmony_ci GLuint group[2]; 4645bd8deadSopenharmony_ci GLuint counter[2]; 4655bd8deadSopenharmony_ci GLuint monitor; 4665bd8deadSopenharmony_ci GLuint *counterData; 4675bd8deadSopenharmony_ci 4685bd8deadSopenharmony_ci // Get group/counter IDs by name. Note that normally the 4695bd8deadSopenharmony_ci // counter and group names need to be queried for because 4705bd8deadSopenharmony_ci // each implementation of this extension on different hardware 4715bd8deadSopenharmony_ci // could define different names and groups. This is just provided 4725bd8deadSopenharmony_ci // to demonstrate the API. 4735bd8deadSopenharmony_ci getCounterByName("HW", "Hardware Busy", &group[0], 4745bd8deadSopenharmony_ci &counter[0]); 4755bd8deadSopenharmony_ci getCounterByName("API", "Draw Calls", &group[1], 4765bd8deadSopenharmony_ci &counter[1]); 4775bd8deadSopenharmony_ci 4785bd8deadSopenharmony_ci // create perf monitor ID 4795bd8deadSopenharmony_ci glGenPerfMonitorsAMD(1, &monitor); 4805bd8deadSopenharmony_ci 4815bd8deadSopenharmony_ci // enable the counters 4825bd8deadSopenharmony_ci glSelectPerfMonitorCountersAMD(monitor, GL_TRUE, group[0], 1, 4835bd8deadSopenharmony_ci &counter[0]); 4845bd8deadSopenharmony_ci glSelectPerfMonitorCountersAMD(monitor, GL_TRUE, group[1], 1, 4855bd8deadSopenharmony_ci &counter[1]); 4865bd8deadSopenharmony_ci 4875bd8deadSopenharmony_ci glBeginPerfMonitorAMD(monitor); 4885bd8deadSopenharmony_ci 4895bd8deadSopenharmony_ci // RENDER FRAME HERE 4905bd8deadSopenharmony_ci // ... 4915bd8deadSopenharmony_ci 4925bd8deadSopenharmony_ci glEndPerfMonitorAMD(monitor); 4935bd8deadSopenharmony_ci 4945bd8deadSopenharmony_ci // read the counters 4955bd8deadSopenharmony_ci GLint resultSize; 4965bd8deadSopenharmony_ci glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD, 4975bd8deadSopenharmony_ci sizeof(GLint), &resultSize, NULL); 4985bd8deadSopenharmony_ci 4995bd8deadSopenharmony_ci counterData = (GLuint*) malloc(resultSize); 5005bd8deadSopenharmony_ci 5015bd8deadSopenharmony_ci GLsizei bytesWritten; 5025bd8deadSopenharmony_ci glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AMD, 5035bd8deadSopenharmony_ci resultSize, counterData, &bytesWritten); 5045bd8deadSopenharmony_ci 5055bd8deadSopenharmony_ci // display or log counter info 5065bd8deadSopenharmony_ci GLsizei wordCount = 0; 5075bd8deadSopenharmony_ci 5085bd8deadSopenharmony_ci while ( (4 * wordCount) < bytesWritten ) 5095bd8deadSopenharmony_ci { 5105bd8deadSopenharmony_ci GLuint groupId = counterData[wordCount]; 5115bd8deadSopenharmony_ci GLuint counterId = counterData[wordCount + 1]; 5125bd8deadSopenharmony_ci 5135bd8deadSopenharmony_ci // Determine the counter type 5145bd8deadSopenharmony_ci GLuint counterType; 5155bd8deadSopenharmony_ci glGetPerfMonitorCounterInfoAMD(groupId, counterId, 5165bd8deadSopenharmony_ci GL_COUNTER_TYPE_AMD, &counterType); 5175bd8deadSopenharmony_ci 5185bd8deadSopenharmony_ci if ( counterType == GL_UNSIGNED_INT64_AMD ) 5195bd8deadSopenharmony_ci { 5205bd8deadSopenharmony_ci unsigned __int64 counterResult = 5215bd8deadSopenharmony_ci *(unsigned __int64*)(&counterData[wordCount + 2]); 5225bd8deadSopenharmony_ci 5235bd8deadSopenharmony_ci // Print counter result 5245bd8deadSopenharmony_ci 5255bd8deadSopenharmony_ci wordCount += 4; 5265bd8deadSopenharmony_ci } 5275bd8deadSopenharmony_ci else if ( counterType == GL_FLOAT ) 5285bd8deadSopenharmony_ci { 5295bd8deadSopenharmony_ci float counterResult = *(float*)(&counterData[wordCount + 2]); 5305bd8deadSopenharmony_ci 5315bd8deadSopenharmony_ci // Print counter result 5325bd8deadSopenharmony_ci 5335bd8deadSopenharmony_ci wordCount += 3; 5345bd8deadSopenharmony_ci } 5355bd8deadSopenharmony_ci // else if ( ... ) check for other counter types 5365bd8deadSopenharmony_ci // (GL_UNSIGNED_INT and GL_PERCENTAGE_AMD) 5375bd8deadSopenharmony_ci } 5385bd8deadSopenharmony_ci } 5395bd8deadSopenharmony_ci 5405bd8deadSopenharmony_ciRevision History 5415bd8deadSopenharmony_ci 11/29/2007 - dginsburg 5425bd8deadSopenharmony_ci + Clarified the default state of a performance monitor object on creation 5435bd8deadSopenharmony_ci 5445bd8deadSopenharmony_ci 11/09/2007 - dginsbur 5455bd8deadSopenharmony_ci + Clarify what happens if SelectPerfMonitorCountersAMD is called on 5465bd8deadSopenharmony_ci a monitor with outstanding query results. 5475bd8deadSopenharmony_ci + Rename counterSize to countersSize 5485bd8deadSopenharmony_ci + Remove some ';' typos 5495bd8deadSopenharmony_ci 5505bd8deadSopenharmony_ci 06/13/2007 - dginsbur 5515bd8deadSopenharmony_ci + Add language on the asynchronous nature of the API and 5525bd8deadSopenharmony_ci counter accuracy/performance distortion. 5535bd8deadSopenharmony_ci + Add myself as the contact 5545bd8deadSopenharmony_ci + Remove INVALID_OPERATION error when countersList is NULL 5555bd8deadSopenharmony_ci + Clarify 64-bit issue 5565bd8deadSopenharmony_ci + Make PERCENTAGE_AMD counters float rather than uint 5575bd8deadSopenharmony_ci + Clarify accuracy distortion on variant counters only 5585bd8deadSopenharmony_ci + Tweak to overview language 5595bd8deadSopenharmony_ci 5605bd8deadSopenharmony_ci 06/09/2007 - dginsbur 5615bd8deadSopenharmony_ci + Fill in errors section and make many more errors explicit 5625bd8deadSopenharmony_ci + Fix the example code so it compiles 5635bd8deadSopenharmony_ci 5645bd8deadSopenharmony_ci 06/08/2007 - dginsbur 5655bd8deadSopenharmony_ci + Modified GetPerfMonitorGroupString and GetPerfMonitorCounterString to 5665bd8deadSopenharmony_ci be more client/server friendly. 5675bd8deadSopenharmony_ci + Modified example. 5685bd8deadSopenharmony_ci + Renamed parameters/variables to follow GL conventions. 5695bd8deadSopenharmony_ci + Modified several 'int' param types to 'sizei' 5705bd8deadSopenharmony_ci + Modifid counters type from 'int' to 'uint' 5715bd8deadSopenharmony_ci + Renamed argument 'cb' and 'cbret' 5725bd8deadSopenharmony_ci + Better documented GetPerfMonitorCounterData 5735bd8deadSopenharmony_ci + Add AMD adornment in many places that were missing it 5745bd8deadSopenharmony_ci 5755bd8deadSopenharmony_ci 06/07/2007 - dginsbur 5765bd8deadSopenharmony_ci + Cleanup formatting, remove tabs, make fit in proper page width 5775bd8deadSopenharmony_ci + Add FLOAT and UNSIGNED_INT to list of COUNTER_TYPEs 5785bd8deadSopenharmony_ci + Fix some bugs in the example code 5795bd8deadSopenharmony_ci + Rewrite introduction 5805bd8deadSopenharmony_ci + Clarified Issue 1 reasoning 5815bd8deadSopenharmony_ci + Added Issue 3 regarding use of 64-bit data types 5825bd8deadSopenharmony_ci + Added revision history 5835bd8deadSopenharmony_ci 5845bd8deadSopenharmony_ci 03/21/2007 - Initial version written. Written by amunshi. 5855bd8deadSopenharmony_ci 5865bd8deadSopenharmony_ci 587