From 12ce67b228078ca5b91fe2ec8bbe5efbfff73943 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Sat, 20 Oct 2018 11:54:06 +0100 Subject: [PATCH] Add GL Intel performance counters support Intel published a performance query extension support defined back in 2013. This is available on Windows & Linux (in the Mesa driver). This should provide the same types of counters as the MDAPI backend for DX11. Frameretrace [1] (a fork/branch of Apitrace) uses the same extension. v2: Fix build without OpenGL Simplify logic to enable counters Warn about non enabled counters on Linux/Mesa Generate counter Uuid v3: Turn asserts into errors Don't load perf entry points manually v4: More clang-format v5: Fix some Windows conversion warnings v6: Fix errors on Windows where the driver reports an error on glGetPerfQueryInfoINTEL as a mean to say that the queryId cannot be used through the extension v7: clang-format v8: Initialize variable passed by pointers to GL entry points v9: Only try to use the INTEL_performance_query on Mesa, experience shows the Intel Windows driver doesn't report anything useful. [1]: https://github.com/janesma/apitrace/wiki/screen-shots --- renderdoc/CMakeLists.txt | 7 +- renderdoc/driver/gl/gl_common.h | 12 + renderdoc/driver/gl/gl_counters.cpp | 107 ++++++ renderdoc/driver/gl/gl_dispatch_table.h | 14 +- renderdoc/driver/gl/gl_dispatch_table_defs.h | 40 +-- renderdoc/driver/gl/gl_driver.cpp | 10 + renderdoc/driver/gl/gl_driver.h | 20 ++ renderdoc/driver/gl/gl_replay.cpp | 31 +- renderdoc/driver/gl/gl_replay.h | 9 + .../driver/gl/wrappers/gl_query_funcs.cpp | 61 ++++ renderdoc/driver/ihv/intel/CMakeLists.txt | 9 + renderdoc/driver/ihv/intel/Intel.vcxproj | 2 + .../driver/ihv/intel/intel_gl_counters.cpp | 318 ++++++++++++++++++ .../driver/ihv/intel/intel_gl_counters.h | 132 ++++++++ 14 files changed, 744 insertions(+), 28 deletions(-) create mode 100644 renderdoc/driver/ihv/intel/CMakeLists.txt create mode 100644 renderdoc/driver/ihv/intel/intel_gl_counters.cpp create mode 100644 renderdoc/driver/ihv/intel/intel_gl_counters.h diff --git a/renderdoc/CMakeLists.txt b/renderdoc/CMakeLists.txt index 4b5da789c..059095207 100644 --- a/renderdoc/CMakeLists.txt +++ b/renderdoc/CMakeLists.txt @@ -430,6 +430,12 @@ endif() add_subdirectory(driver/ihv/amd) list(APPEND renderdoc_objects $) +# pull in the intel folder for GL perf queries +if(ENABLE_GL OR ENABLE_GLES) + add_subdirectory(driver/ihv/intel) + list(APPEND renderdoc_objects $) +endif() + add_library(rdoc OBJECT ${sources}) target_compile_definitions(rdoc ${RDOC_DEFINITIONS}) target_include_directories(rdoc ${RDOC_INCLUDES}) @@ -491,4 +497,3 @@ install (TARGETS renderdoc DESTINATION lib${LIB_SUFFIX}/${LIB_SUBFOLDER}) # Copy in application API header to include install (FILES api/app/renderdoc_app.h DESTINATION include RENAME renderdoc.h) - diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index c6557aa3b..9eac4cc3b 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -689,6 +689,7 @@ extern bool IsGLES; EXT_TO_CHECK(99, 30, EXT_texture_swizzle) \ EXT_TO_CHECK(99, 99, KHR_blend_equation_advanced_coherent) \ EXT_TO_CHECK(99, 99, EXT_texture_sRGB_decode) \ + EXT_TO_CHECK(99, 99, INTEL_performance_query) \ /* OpenGL ES extensions */ \ EXT_TO_CHECK(99, 32, EXT_color_buffer_float) \ EXT_TO_CHECK(99, 32, EXT_primitive_bounding_box) \ @@ -2084,6 +2085,17 @@ enum class GLChunk : uint32_t CoherentMapWrite, + glBeginPerfQueryINTEL, + glCreatePerfQueryINTEL, + glDeletePerfQueryINTEL, + glEndPerfQueryINTEL, + glGetFirstPerfQueryIdINTEL, + glGetNextPerfQueryIdINTEL, + glGetPerfCounterInfoINTEL, + glGetPerfQueryDataINTEL, + glGetPerfQueryIdByNameINTEL, + glGetPerfQueryInfoINTEL, + Max, }; diff --git a/renderdoc/driver/gl/gl_counters.cpp b/renderdoc/driver/gl/gl_counters.cpp index 153547e4e..9fa59d48c 100644 --- a/renderdoc/driver/gl/gl_counters.cpp +++ b/renderdoc/driver/gl/gl_counters.cpp @@ -25,6 +25,7 @@ #include #include #include "driver/ihv/amd/amd_counters.h" +#include "driver/ihv/intel/intel_gl_counters.h" #include "gl_driver.h" #include "gl_replay.h" #include "gl_resources.h" @@ -59,6 +60,12 @@ vector GLReplay::EnumerateCounters() ret.insert(ret.end(), amdCounters.begin(), amdCounters.end()); } + if(m_pIntelCounters) + { + vector intelCounters = m_pIntelCounters->GetPublicCounterIds(); + ret.insert(ret.end(), intelCounters.begin(), intelCounters.end()); + } + return ret; } @@ -79,6 +86,17 @@ CounterDescription GLReplay::DescribeCounter(GPUCounter counterID) } } + /////Intel///// + if(IsIntelCounter(counterID)) + { + if(m_pIntelCounters) + { + desc = m_pIntelCounters->GetCounterDescription(counterID); + + return desc; + } + } + // FFBA5548-FBF8-405D-BA18-F0329DA370A0 desc.uuid.words[0] = 0xFFBA5548; desc.uuid.words[1] = 0xFBF8405D; @@ -368,6 +386,82 @@ vector GLReplay::FetchCountersAMD(const vector &count return ret; } +void GLReplay::FillTimersIntel(uint32_t *eventStartID, uint32_t *sampleIndex, + vector *eventIDs, const DrawcallDescription &drawnode) +{ + if(drawnode.children.empty()) + return; + + for(size_t i = 0; i < drawnode.children.size(); i++) + { + const DrawcallDescription &d = drawnode.children[i]; + + FillTimersIntel(eventStartID, sampleIndex, eventIDs, drawnode.children[i]); + + if(d.events.empty()) + continue; + + eventIDs->push_back(d.eventId); + + m_pDriver->ReplayLog(*eventStartID, d.eventId, eReplay_WithoutDraw); + + m_pIntelCounters->BeginSample(*sampleIndex); + + m_pDriver->ReplayLog(*eventStartID, d.eventId, eReplay_OnlyDraw); + + m_pIntelCounters->EndSample(); + + *eventStartID = d.eventId + 1; + ++*sampleIndex; + } +} + +vector GLReplay::FetchCountersIntel(const vector &counters) +{ + m_pIntelCounters->DisableAllCounters(); + + // enable counters it needs + for(size_t i = 0; i < counters.size(); i++) + { + // This function is only called internally, and violating this assertion means our + // caller has invoked this method incorrectly + RDCASSERT(IsIntelCounter(counters[i])); + m_pIntelCounters->EnableCounter(counters[i]); + } + + m_pIntelCounters->BeginSession(); + + uint32_t passCount = m_pIntelCounters->GetPassCount(); + + uint32_t sampleIndex = 0; + + vector eventIDs; + + m_pDriver->ReplayMarkers(false); + + for(uint32_t p = 0; p < passCount; p++) + { + m_pIntelCounters->BeginPass(p); + + uint32_t eventStartID = 0; + + sampleIndex = 0; + + eventIDs.clear(); + + FillTimersIntel(&eventStartID, &sampleIndex, &eventIDs, m_pDriver->GetRootDraw()); + m_pIntelCounters->EndPass(); + } + + m_pDriver->ReplayMarkers(true); + + std::vector ret = m_pIntelCounters->GetCounterData(sampleIndex, eventIDs, counters); + + m_pIntelCounters->EndSession(); + + return ret; +} + vector GLReplay::FetchCounters(const vector &allCounters) { vector ret; @@ -397,6 +491,19 @@ vector GLReplay::FetchCounters(const vector &allCount } } + if(m_pIntelCounters) + { + // Filter out the Intel counters + vector intelCounters; + std::copy_if(allCounters.begin(), allCounters.end(), std::back_inserter(intelCounters), + [](const GPUCounter &c) { return IsIntelCounter(c); }); + + if(!intelCounters.empty()) + { + ret = FetchCountersIntel(intelCounters); + } + } + if(counters.empty()) { return ret; diff --git a/renderdoc/driver/gl/gl_dispatch_table.h b/renderdoc/driver/gl/gl_dispatch_table.h index 3c198cba6..aa13bb8a1 100644 --- a/renderdoc/driver/gl/gl_dispatch_table.h +++ b/renderdoc/driver/gl/gl_dispatch_table.h @@ -942,7 +942,19 @@ struct GLDispatchTable PFNGLGETQUERYBUFFEROBJECTIVPROC glGetQueryBufferObjectiv; PFNGLGETQUERYBUFFEROBJECTUI64VPROC glGetQueryBufferObjectui64v; PFNGLGETQUERYBUFFEROBJECTUIVPROC glGetQueryBufferObjectuiv; - + + // INTEL_performance_query + PFNGLBEGINPERFQUERYINTELPROC glBeginPerfQueryINTEL; + PFNGLCREATEPERFQUERYINTELPROC glCreatePerfQueryINTEL; + PFNGLDELETEPERFQUERYINTELPROC glDeletePerfQueryINTEL; + PFNGLENDPERFQUERYINTELPROC glEndPerfQueryINTEL; + PFNGLGETFIRSTPERFQUERYIDINTELPROC glGetFirstPerfQueryIdINTEL; + PFNGLGETNEXTPERFQUERYIDINTELPROC glGetNextPerfQueryIdINTEL; + PFNGLGETPERFCOUNTERINFOINTELPROC glGetPerfCounterInfoINTEL; + PFNGLGETPERFQUERYDATAINTELPROC glGetPerfQueryDataINTEL; + PFNGLGETPERFQUERYIDBYNAMEINTELPROC glGetPerfQueryIdByNameINTEL; + PFNGLGETPERFQUERYINFOINTELPROC glGetPerfQueryInfoINTEL; + // stubbed on all non-windows platforms PFNWGLDXSETRESOURCESHAREHANDLENVPROC wglDXSetResourceShareHandleNV; PFNWGLDXOPENDEVICENVPROC wglDXOpenDeviceNV; diff --git a/renderdoc/driver/gl/gl_dispatch_table_defs.h b/renderdoc/driver/gl/gl_dispatch_table_defs.h index 607d732f4..0726534d7 100644 --- a/renderdoc/driver/gl/gl_dispatch_table_defs.h +++ b/renderdoc/driver/gl/gl_dispatch_table_defs.h @@ -1271,6 +1271,16 @@ FUNC(glGetQueryBufferObjectiv, glGetQueryBufferObjectiv); \ FUNC(glGetQueryBufferObjectui64v, glGetQueryBufferObjectui64v); \ FUNC(glGetQueryBufferObjectuiv, glGetQueryBufferObjectuiv); \ + FUNC(glBeginPerfQueryINTEL, glBeginPerfQueryINTEL); \ + FUNC(glCreatePerfQueryINTEL, glCreatePerfQueryINTEL); \ + FUNC(glDeletePerfQueryINTEL, glDeletePerfQueryINTEL); \ + FUNC(glEndPerfQueryINTEL, glEndPerfQueryINTEL); \ + FUNC(glGetFirstPerfQueryIdINTEL, glGetFirstPerfQueryIdINTEL); \ + FUNC(glGetNextPerfQueryIdINTEL, glGetNextPerfQueryIdINTEL); \ + FUNC(glGetPerfCounterInfoINTEL, glGetPerfCounterInfoINTEL); \ + FUNC(glGetPerfQueryDataINTEL, glGetPerfQueryDataINTEL); \ + FUNC(glGetPerfQueryIdByNameINTEL, glGetPerfQueryIdByNameINTEL); \ + FUNC(glGetPerfQueryInfoINTEL, glGetPerfQueryInfoINTEL); \ FUNC(wglDXSetResourceShareHandleNV, wglDXSetResourceShareHandleNV); \ FUNC(wglDXOpenDeviceNV, wglDXOpenDeviceNV); \ FUNC(wglDXCloseDeviceNV, wglDXCloseDeviceNV); \ @@ -2520,6 +2530,16 @@ FuncWrapper4(void, glGetQueryBufferObjectiv, GLuint, id, GLuint, buffer, GLenum, pname, GLintptr, offset); \ FuncWrapper4(void, glGetQueryBufferObjectui64v, GLuint, id, GLuint, buffer, GLenum, pname, GLintptr, offset); \ FuncWrapper4(void, glGetQueryBufferObjectuiv, GLuint, id, GLuint, buffer, GLenum, pname, GLintptr, offset); \ + FuncWrapper1(void, glBeginPerfQueryINTEL, GLuint, queryHandle); \ + FuncWrapper2(void, glCreatePerfQueryINTEL, GLuint, queryId, GLuint *, queryHandle); \ + FuncWrapper1(void, glDeletePerfQueryINTEL, GLuint, queryHandle); \ + FuncWrapper1(void, glEndPerfQueryINTEL, GLuint, queryHandle); \ + FuncWrapper1(void, glGetFirstPerfQueryIdINTEL, GLuint *, queryId); \ + FuncWrapper2(void, glGetNextPerfQueryIdINTEL, GLuint, queryId, GLuint *, nextQueryId); \ + FuncWrapper11(void, glGetPerfCounterInfoINTEL, GLuint, queryId, GLuint, counterId, GLuint, counterNameLength, GLchar *, counterName, GLuint, counterDescLength, GLchar *, counterDesc, GLuint *, counterOffset, GLuint *, counterDataSize, GLuint *, counterTypeEnum, GLuint *, counterDataTypeEnum, GLuint64 *, rawCounterMaxValue); \ + FuncWrapper5(void, glGetPerfQueryDataINTEL, GLuint, queryHandle, GLuint, flags, GLsizei, dataSize, void *, data, GLuint *, bytesWritten); \ + FuncWrapper2(void, glGetPerfQueryIdByNameINTEL, GLchar *, queryName, GLuint *, queryId); \ + FuncWrapper7(void, glGetPerfQueryInfoINTEL, GLuint, queryId, GLuint, queryNameLength, GLchar *, queryName, GLuint *, dataSize, GLuint *, noCounters, GLuint *, noInstances, GLuint *, capsMask); \ FuncWrapper2(BOOL, wglDXSetResourceShareHandleNV, void *, dxObject, HANDLE, shareHandle); \ FuncWrapper1(HANDLE, wglDXOpenDeviceNV, void *, dxDevice); \ FuncWrapper1(BOOL, wglDXCloseDeviceNV, HANDLE, hDevice); \ @@ -2560,7 +2580,6 @@ FUNC(glBeginFragmentShaderATI); \ FUNC(glBeginOcclusionQueryNV); \ FUNC(glBeginPerfMonitorAMD); \ - FUNC(glBeginPerfQueryINTEL); \ FUNC(glBegin); \ FUNC(glBeginTransformFeedbackNV); \ FUNC(glBeginVertexShaderEXT); \ @@ -2760,7 +2779,6 @@ FUNC(glCoverStrokePathInstancedNV); \ FUNC(glCoverStrokePathNV); \ FUNC(glCreateCommandListsNV); \ - FUNC(glCreatePerfQueryINTEL); \ FUNC(glCreateProgramObjectARB); \ FUNC(glCreateShaderObjectARB); \ FUNC(glCreateShaderProgramEXT); \ @@ -2786,7 +2804,6 @@ FUNC(glDeleteOcclusionQueriesNV); \ FUNC(glDeletePathsNV); \ FUNC(glDeletePerfMonitorsAMD); \ - FUNC(glDeletePerfQueryINTEL); \ FUNC(glDeleteProgramsARB); \ FUNC(glDeleteProgramsNV); \ FUNC(glDeleteQueryResourceTagNV); \ @@ -2857,7 +2874,6 @@ FUNC(glEndList); \ FUNC(glEndOcclusionQueryNV); \ FUNC(glEndPerfMonitorAMD); \ - FUNC(glEndPerfQueryINTEL); \ FUNC(glEnd); \ FUNC(glEndTilingQCOM); \ FUNC(glEndTransformFeedbackNV); \ @@ -3022,7 +3038,6 @@ FUNC(glGetFenceivNV); \ FUNC(glGetFinalCombinerInputParameterfvNV); \ FUNC(glGetFinalCombinerInputParameterivNV); \ - FUNC(glGetFirstPerfQueryIdINTEL); \ FUNC(glGetFixedvOES); \ FUNC(glGetFogFuncSGIS); \ FUNC(glGetFragDataIndexEXT); \ @@ -3098,7 +3113,6 @@ FUNC(glGetnColorTable); \ FUNC(glGetnConvolutionFilterARB); \ FUNC(glGetnConvolutionFilter); \ - FUNC(glGetNextPerfQueryIdINTEL); \ FUNC(glGetnHistogramARB); \ FUNC(glGetnHistogram); \ FUNC(glGetnMapdvARB); \ @@ -3144,16 +3158,12 @@ FUNC(glGetPathSpacingNV); \ FUNC(glGetPathTexGenfvNV); \ FUNC(glGetPathTexGenivNV); \ - FUNC(glGetPerfCounterInfoINTEL); \ FUNC(glGetPerfMonitorCounterDataAMD); \ FUNC(glGetPerfMonitorCounterInfoAMD); \ FUNC(glGetPerfMonitorCountersAMD); \ FUNC(glGetPerfMonitorCounterStringAMD); \ FUNC(glGetPerfMonitorGroupsAMD); \ FUNC(glGetPerfMonitorGroupStringAMD); \ - FUNC(glGetPerfQueryDataINTEL); \ - FUNC(glGetPerfQueryIdByNameINTEL); \ - FUNC(glGetPerfQueryInfoINTEL); \ FUNC(glGetPixelMapfv); \ FUNC(glGetPixelMapuiv); \ FUNC(glGetPixelMapusv); \ @@ -4483,7 +4493,6 @@ UnsupportedWrapper0(void, glBeginFragmentShaderATI); \ UnsupportedWrapper1(void, glBeginOcclusionQueryNV, GLuint, id); \ UnsupportedWrapper1(void, glBeginPerfMonitorAMD, GLuint, monitor); \ - UnsupportedWrapper1(void, glBeginPerfQueryINTEL, GLuint, queryHandle); \ UnsupportedWrapper1(void, glBegin, GLenum, mode); \ UnsupportedWrapper1(void, glBeginTransformFeedbackNV, GLenum, primitiveMode); \ UnsupportedWrapper0(void, glBeginVertexShaderEXT); \ @@ -4683,7 +4692,6 @@ UnsupportedWrapper7(void, glCoverStrokePathInstancedNV, GLsizei, numPaths, GLenum, pathNameType, const void *, paths, GLuint, pathBase, GLenum, coverMode, GLenum, transformType, const GLfloat *, transformValues); \ UnsupportedWrapper2(void, glCoverStrokePathNV, GLuint, path, GLenum, coverMode); \ UnsupportedWrapper2(void, glCreateCommandListsNV, GLsizei, n, GLuint *, lists); \ - UnsupportedWrapper2(void, glCreatePerfQueryINTEL, GLuint, queryId, GLuint *, queryHandle); \ UnsupportedWrapper0(GLhandleARB, glCreateProgramObjectARB); \ UnsupportedWrapper1(GLhandleARB, glCreateShaderObjectARB, GLenum, shaderType); \ UnsupportedWrapper2(GLuint, glCreateShaderProgramEXT, GLenum, type, const GLchar *, string); \ @@ -4709,7 +4717,6 @@ UnsupportedWrapper2(void, glDeleteOcclusionQueriesNV, GLsizei, n, const GLuint *, ids); \ UnsupportedWrapper2(void, glDeletePathsNV, GLuint, path, GLsizei, range); \ UnsupportedWrapper2(void, glDeletePerfMonitorsAMD, GLsizei, n, GLuint *, monitors); \ - UnsupportedWrapper1(void, glDeletePerfQueryINTEL, GLuint, queryHandle); \ UnsupportedWrapper2(void, glDeleteProgramsARB, GLsizei, n, const GLuint *, programs); \ UnsupportedWrapper2(void, glDeleteProgramsNV, GLsizei, n, const GLuint *, programs); \ UnsupportedWrapper2(void, glDeleteQueryResourceTagNV, GLsizei, n, const GLint *, tagIds); \ @@ -4780,7 +4787,6 @@ UnsupportedWrapper0(void, glEndList); \ UnsupportedWrapper0(void, glEndOcclusionQueryNV); \ UnsupportedWrapper1(void, glEndPerfMonitorAMD, GLuint, monitor); \ - UnsupportedWrapper1(void, glEndPerfQueryINTEL, GLuint, queryHandle); \ UnsupportedWrapper0(void, glEnd); \ UnsupportedWrapper1(void, glEndTilingQCOM, GLbitfield, preserveMask); \ UnsupportedWrapper0(void, glEndTransformFeedbackNV); \ @@ -4945,7 +4951,6 @@ UnsupportedWrapper3(void, glGetFenceivNV, GLuint, fence, GLenum, pname, GLint *, params); \ UnsupportedWrapper3(void, glGetFinalCombinerInputParameterfvNV, GLenum, variable, GLenum, pname, GLfloat *, params); \ UnsupportedWrapper3(void, glGetFinalCombinerInputParameterivNV, GLenum, variable, GLenum, pname, GLint *, params); \ - UnsupportedWrapper1(void, glGetFirstPerfQueryIdINTEL, GLuint *, queryId); \ UnsupportedWrapper2(void, glGetFixedvOES, GLenum, pname, GLfixed *, params); \ UnsupportedWrapper1(void, glGetFogFuncSGIS, GLfloat *, points); \ UnsupportedWrapper2(GLint, glGetFragDataIndexEXT, GLuint, program, const GLchar *, name); \ @@ -5021,7 +5026,6 @@ UnsupportedWrapper5(void, glGetnColorTable, GLenum, target, GLenum, format, GLenum, type, GLsizei, bufSize, void *, table); \ UnsupportedWrapper5(void, glGetnConvolutionFilterARB, GLenum, target, GLenum, format, GLenum, type, GLsizei, bufSize, void *, image); \ UnsupportedWrapper5(void, glGetnConvolutionFilter, GLenum, target, GLenum, format, GLenum, type, GLsizei, bufSize, void *, image); \ - UnsupportedWrapper2(void, glGetNextPerfQueryIdINTEL, GLuint, queryId, GLuint *, nextQueryId); \ UnsupportedWrapper6(void, glGetnHistogramARB, GLenum, target, GLboolean, reset, GLenum, format, GLenum, type, GLsizei, bufSize, void *, values); \ UnsupportedWrapper6(void, glGetnHistogram, GLenum, target, GLboolean, reset, GLenum, format, GLenum, type, GLsizei, bufSize, void *, values); \ UnsupportedWrapper4(void, glGetnMapdvARB, GLenum, target, GLenum, query, GLsizei, bufSize, GLdouble *, v); \ @@ -5067,16 +5071,12 @@ UnsupportedWrapper9(void, glGetPathSpacingNV, GLenum, pathListMode, GLsizei, numPaths, GLenum, pathNameType, const void *, paths, GLuint, pathBase, GLfloat, advanceScale, GLfloat, kerningScale, GLenum, transformType, GLfloat *, returnedSpacing); \ UnsupportedWrapper3(void, glGetPathTexGenfvNV, GLenum, texCoordSet, GLenum, pname, GLfloat *, value); \ UnsupportedWrapper3(void, glGetPathTexGenivNV, GLenum, texCoordSet, GLenum, pname, GLint *, value); \ - UnsupportedWrapper11(void, glGetPerfCounterInfoINTEL, GLuint, queryId, GLuint, counterId, GLuint, counterNameLength, GLchar *, counterName, GLuint, counterDescLength, GLchar *, counterDesc, GLuint *, counterOffset, GLuint *, counterDataSize, GLuint *, counterTypeEnum, GLuint *, counterDataTypeEnum, GLuint64 *, rawCounterMaxValue); \ UnsupportedWrapper5(void, glGetPerfMonitorCounterDataAMD, GLuint, monitor, GLenum, pname, GLsizei, dataSize, GLuint *, data, GLint *, bytesWritten); \ UnsupportedWrapper4(void, glGetPerfMonitorCounterInfoAMD, GLuint, group, GLuint, counter, GLenum, pname, void *, data); \ UnsupportedWrapper5(void, glGetPerfMonitorCountersAMD, GLuint, group, GLint *, numCounters, GLint *, maxActiveCounters, GLsizei, counterSize, GLuint *, counters); \ UnsupportedWrapper5(void, glGetPerfMonitorCounterStringAMD, GLuint, group, GLuint, counter, GLsizei, bufSize, GLsizei *, length, GLchar *, counterString); \ UnsupportedWrapper3(void, glGetPerfMonitorGroupsAMD, GLint *, numGroups, GLsizei, groupsSize, GLuint *, groups); \ UnsupportedWrapper4(void, glGetPerfMonitorGroupStringAMD, GLuint, group, GLsizei, bufSize, GLsizei *, length, GLchar *, groupString); \ - UnsupportedWrapper5(void, glGetPerfQueryDataINTEL, GLuint, queryHandle, GLuint, flags, GLsizei, dataSize, void *, data, GLuint *, bytesWritten); \ - UnsupportedWrapper2(void, glGetPerfQueryIdByNameINTEL, GLchar *, queryName, GLuint *, queryId); \ - UnsupportedWrapper7(void, glGetPerfQueryInfoINTEL, GLuint, queryId, GLuint, queryNameLength, GLchar *, queryName, GLuint *, dataSize, GLuint *, noCounters, GLuint *, noInstances, GLuint *, capsMask); \ UnsupportedWrapper2(void, glGetPixelMapfv, GLenum, map, GLfloat *, values); \ UnsupportedWrapper2(void, glGetPixelMapuiv, GLenum, map, GLuint *, values); \ UnsupportedWrapper2(void, glGetPixelMapusv, GLenum, map, GLushort *, values); \ diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 4fae0c453..224266b44 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -4368,6 +4368,16 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk) case GLChunk::glDeleteSemaphoresEXT: case GLChunk::glIsSemaphoreEXT: case GLChunk::glGetSemaphoreParameterui64vEXT: + case GLChunk::glBeginPerfQueryINTEL: + case GLChunk::glCreatePerfQueryINTEL: + case GLChunk::glDeletePerfQueryINTEL: + case GLChunk::glEndPerfQueryINTEL: + case GLChunk::glGetFirstPerfQueryIdINTEL: + case GLChunk::glGetNextPerfQueryIdINTEL: + case GLChunk::glGetPerfCounterInfoINTEL: + case GLChunk::glGetPerfQueryDataINTEL: + case GLChunk::glGetPerfQueryIdByNameINTEL: + case GLChunk::glGetPerfQueryInfoINTEL: case GLChunk::Max: RDCERR("Unexpected chunk %s, or missing case for processing! Skipping...", diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 42c7a9c77..10ae6e2a7 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -2359,6 +2359,26 @@ public: IMPLEMENT_FUNCTION_SERIALISED(GLboolean, glAcquireKeyedMutexWin32EXT, GLuint memory, GLuint64 key, GLuint timeout); IMPLEMENT_FUNCTION_SERIALISED(GLboolean, glReleaseKeyedMutexWin32EXT, GLuint memory, GLuint64 key); + + // INTEL_performance_query + IMPLEMENT_FUNCTION_SERIALISED(void, glBeginPerfQueryINTEL, GLuint queryHandle); + IMPLEMENT_FUNCTION_SERIALISED(void, glCreatePerfQueryINTEL, GLuint queryId, GLuint *queryHandle); + IMPLEMENT_FUNCTION_SERIALISED(void, glDeletePerfQueryINTEL, GLuint queryHandle); + IMPLEMENT_FUNCTION_SERIALISED(void, glEndPerfQueryINTEL, GLuint queryHandle); + IMPLEMENT_FUNCTION_SERIALISED(void, glGetFirstPerfQueryIdINTEL, GLuint *queryId); + IMPLEMENT_FUNCTION_SERIALISED(void, glGetNextPerfQueryIdINTEL, GLuint queryId, GLuint *nextQueryId); + IMPLEMENT_FUNCTION_SERIALISED(void, glGetPerfCounterInfoINTEL, GLuint queryId, GLuint counterId, + GLuint counterNameLength, GLchar *counterName, + GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, + GLuint *counterDataSize, GLuint *counterTypeEnum, + GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); + IMPLEMENT_FUNCTION_SERIALISED(void, glGetPerfQueryDataINTEL, GLuint queryHandle, GLuint flags, + GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); + IMPLEMENT_FUNCTION_SERIALISED(void, glGetPerfQueryIdByNameINTEL, GLchar *queryName, + GLuint *queryId); + IMPLEMENT_FUNCTION_SERIALISED(void, glGetPerfQueryInfoINTEL, GLuint queryId, + GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, + GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); }; class ScopedDebugContext diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 7c75c926d..38f66f26e 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -25,6 +25,7 @@ #include "gl_replay.h" #include "driver/ihv/amd/amd_counters.h" +#include "driver/ihv/intel/intel_gl_counters.h" #include "maths/matrix.h" #include "serialise/rdcfile.h" #include "strings/string_utils.h" @@ -60,6 +61,7 @@ GLReplay::GLReplay() void GLReplay::Shutdown() { SAFE_DELETE(m_pAMDCounters); + SAFE_DELETE(m_pIntelCounters); DeleteDebugData(); @@ -222,7 +224,8 @@ void GLReplay::SetReplayData(GLWindowingData data) InitDebugData(); - AMDCounters *counters = NULL; + AMDCounters *countersAMD = NULL; + IntelGlCounters *countersIntel = NULL; bool isMesa = false; @@ -256,14 +259,20 @@ void GLReplay::SetReplayData(GLWindowingData data) if(isMesa) { - RDCLOG("Mesa driver detected - skipping IHV counter initialisation"); + if(m_DriverInfo.vendor == GPUVendor::Intel) + { + RDCLOG("Intel GPU detected - trying to initialise Intel GL counters"); + countersIntel = new IntelGlCounters(); + } + else + RDCLOG("Non Intel Mesa driver detected - skipping IHV counter initialisation"); } else { if(m_DriverInfo.vendor == GPUVendor::AMD) { RDCLOG("AMD GPU detected - trying to initialise AMD counters"); - counters = new AMDCounters(); + countersAMD = new AMDCounters(); } else { @@ -271,15 +280,25 @@ void GLReplay::SetReplayData(GLWindowingData data) } } - if(counters && counters->Init(AMDCounters::ApiType::Ogl, m_ReplayCtx.ctx)) + if(countersAMD && countersAMD->Init(AMDCounters::ApiType::Ogl, m_ReplayCtx.ctx)) { - m_pAMDCounters = counters; + m_pAMDCounters = countersAMD; } else { - delete counters; + delete countersAMD; m_pAMDCounters = NULL; } + + if(countersIntel && countersIntel->Init()) + { + m_pIntelCounters = countersIntel; + } + else + { + delete countersIntel; + m_pIntelCounters = NULL; + } } void GLReplay::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &ret) diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 577f0de15..3d571093d 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -34,6 +34,7 @@ using std::map; using std::pair; class AMDCounters; +class IntelGlCounters; class WrappedOpenGL; struct GLCounterContext; @@ -438,4 +439,12 @@ private: const DrawcallDescription &drawnode); vector FetchCountersAMD(const vector &counters); + + // Intel counter instance + IntelGlCounters *m_pIntelCounters = NULL; + + void FillTimersIntel(uint32_t *eventStartID, uint32_t *sampleIndex, vector *eventIDs, + const DrawcallDescription &drawnode); + + vector FetchCountersIntel(const vector &counters); }; diff --git a/renderdoc/driver/gl/wrappers/gl_query_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_query_funcs.cpp index 260cdd727..4f9a33c99 100644 --- a/renderdoc/driver/gl/wrappers/gl_query_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_query_funcs.cpp @@ -573,6 +573,67 @@ void WrappedOpenGL::glDeleteQueries(GLsizei n, const GLuint *ids) GL.glDeleteQueries(n, ids); } +void WrappedOpenGL::glBeginPerfQueryINTEL(GLuint queryHandle) +{ + GL.glBeginPerfQueryINTEL(queryHandle); +} + +void WrappedOpenGL::glCreatePerfQueryINTEL(GLuint queryId, GLuint *queryHandle) +{ + GL.glCreatePerfQueryINTEL(queryId, queryHandle); +} + +void WrappedOpenGL::glDeletePerfQueryINTEL(GLuint queryHandle) +{ + GL.glDeletePerfQueryINTEL(queryHandle); +} + +void WrappedOpenGL::glEndPerfQueryINTEL(GLuint queryHandle) +{ + GL.glEndPerfQueryINTEL(queryHandle); +} + +void WrappedOpenGL::glGetFirstPerfQueryIdINTEL(GLuint *queryId) +{ + GL.glGetFirstPerfQueryIdINTEL(queryId); +} + +void WrappedOpenGL::glGetNextPerfQueryIdINTEL(GLuint queryId, GLuint *nextQueryId) +{ + GL.glGetNextPerfQueryIdINTEL(queryId, nextQueryId); +} + +void WrappedOpenGL::glGetPerfCounterInfoINTEL(GLuint queryId, GLuint counterId, + GLuint counterNameLength, GLchar *counterName, + GLuint counterDescLength, GLchar *counterDesc, + GLuint *counterOffset, GLuint *counterDataSize, + GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, + GLuint64 *rawCounterMaxValue) +{ + GL.glGetPerfCounterInfoINTEL(queryId, counterId, counterNameLength, counterName, + counterDescLength, counterDesc, counterOffset, counterDataSize, + counterTypeEnum, counterDataTypeEnum, rawCounterMaxValue); +} + +void WrappedOpenGL::glGetPerfQueryDataINTEL(GLuint queryHandle, GLuint flags, GLsizei dataSize, + GLvoid *data, GLuint *bytesWritten) +{ + GL.glGetPerfQueryDataINTEL(queryHandle, flags, dataSize, data, bytesWritten); +} + +void WrappedOpenGL::glGetPerfQueryIdByNameINTEL(GLchar *queryName, GLuint *queryId) +{ + GL.glGetPerfQueryIdByNameINTEL(queryName, queryId); +} + +void WrappedOpenGL::glGetPerfQueryInfoINTEL(GLuint queryId, GLuint queryNameLength, + GLchar *queryName, GLuint *dataSize, GLuint *noCounters, + GLuint *noInstances, GLuint *capsMask) +{ + GL.glGetPerfQueryInfoINTEL(queryId, queryNameLength, queryName, dataSize, noCounters, noInstances, + capsMask); +} + INSTANTIATE_FUNCTION_SERIALISED(void, glFenceSync, GLsync real, GLenum condition, GLbitfield flags); INSTANTIATE_FUNCTION_SERIALISED(void, glClientWaitSync, GLsync sync_, GLbitfield flags, GLuint64 timeout); diff --git a/renderdoc/driver/ihv/intel/CMakeLists.txt b/renderdoc/driver/ihv/intel/CMakeLists.txt new file mode 100644 index 000000000..79816d1bc --- /dev/null +++ b/renderdoc/driver/ihv/intel/CMakeLists.txt @@ -0,0 +1,9 @@ +set(sources + intel_gl_counters.cpp + intel_gl_counters.h) + +set(include_dirs ${RDOC_INCLUDES}) + +add_library(rdoc_intel OBJECT ${sources}) +target_compile_definitions(rdoc_intel ${RDOC_DEFINITIONS}) +target_include_directories(rdoc_intel ${include_dirs}) diff --git a/renderdoc/driver/ihv/intel/Intel.vcxproj b/renderdoc/driver/ihv/intel/Intel.vcxproj index c7d5f8f01..25e4f1597 100644 --- a/renderdoc/driver/ihv/intel/Intel.vcxproj +++ b/renderdoc/driver/ihv/intel/Intel.vcxproj @@ -96,9 +96,11 @@ + + diff --git a/renderdoc/driver/ihv/intel/intel_gl_counters.cpp b/renderdoc/driver/ihv/intel/intel_gl_counters.cpp new file mode 100644 index 000000000..bc5770a7f --- /dev/null +++ b/renderdoc/driver/ihv/intel/intel_gl_counters.cpp @@ -0,0 +1,318 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2018 Baldur Karlsson + * + * 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. + ******************************************************************************/ + +#include +#include + +#include "common/common.h" +#include "driver/gl/gl_dispatch_table.h" +#include "driver/gl/gl_driver.h" +#include "strings/string_utils.h" + +#include "intel_gl_counters.h" + +const static std::vector metricSetBlacklist = { + // Used for testing HW is programmed correctly. + "TestOa", + // Used to plumb raw data from the GL driver to metrics-discovery. + "Intel_Raw_Hardware_Counters_Set_0_Query", "Intel_Raw_Pipeline_Statistics_Query"}; + +IntelGlCounters::IntelGlCounters() : m_passIndex(0) +{ +} + +IntelGlCounters::~IntelGlCounters() +{ +} + +std::vector IntelGlCounters::GetPublicCounterIds() const +{ + vector counters; + + for(const IntelGlCounter &c : m_Counters) + counters.push_back(c.desc.counter); + + return counters; +} + +CounterDescription IntelGlCounters::GetCounterDescription(GPUCounter index) const +{ + return m_Counters[GPUCounterToCounterIndex(index)].desc; +} + +static CompType glToRdcCounterType(GLuint glDataType) +{ + switch(glDataType) + { + case GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL: return CompType::UInt; + case GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL: return CompType::UInt; + case GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL: return CompType::Float; + case GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL: return CompType::Double; + case GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL: return CompType::UInt; + default: RDCERR("Wrong counter data type: %u", glDataType); + } + return CompType::Typeless; +} + +void IntelGlCounters::addCounter(const IntelGlQuery &query, GLuint counterId) +{ + IntelGlCounter counter; + + counter.queryId = query.queryId; + counter.desc.counter = (GPUCounter)((int)GPUCounter::FirstIntel + m_Counters.size()); + counter.desc.category = query.name; + + GLint len = 0; + GL.glGetIntegerv(eGL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL, &len); + counter.desc.name.resize(len); + GL.glGetIntegerv(eGL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL, &len); + counter.desc.description.resize(len); + + GL.glGetPerfCounterInfoINTEL( + query.queryId, counterId, (GLuint)counter.desc.name.size(), &counter.desc.name[0], + (GLuint)counter.desc.description.size(), &counter.desc.description[0], &counter.offset, + &counter.desc.resultByteWidth, &counter.type, &counter.dataType, NULL); + + if(m_CounterNames.find(counter.desc.name) != m_CounterNames.end()) + return; + + uint32_t query_hash = strhash(query.name.c_str()); + uint32_t name_hash = strhash(counter.desc.name.c_str()); + uint32_t desc_hash = strhash(counter.desc.description.c_str()); + counter.desc.uuid = Uuid(0x8086, query_hash, name_hash, desc_hash); + counter.desc.resultType = glToRdcCounterType(counter.dataType); + + m_Counters.push_back(counter); + m_CounterNames[counter.desc.name] = counter; +} + +void IntelGlCounters::addQuery(GLuint queryId) +{ + IntelGlQuery query; + + query.queryId = queryId; + + GLint len = 0; + GL.glGetIntegerv(eGL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL, &len); + query.name.resize(len); + GLuint nCounters = 0; + GL.glGetPerfQueryInfoINTEL(queryId, (GLuint)query.name.size(), &query.name[0], &query.size, + &nCounters, NULL, NULL); + // Some drivers raise an error when we query some of its IDs because those + // are used to plumb external library with raw counter data. + if(GL.glGetError() != eGL_NONE) + return; + + if(std::find(metricSetBlacklist.begin(), metricSetBlacklist.end(), query.name) != + metricSetBlacklist.end()) + return; + + m_Queries[query.queryId] = query; + + for(GLuint c = 1; c <= nCounters; c++) + addCounter(query, c); +} + +bool IntelGlCounters::Init() +{ + if(!HasExt[INTEL_performance_query]) + return false; + + GLuint queryId; + GL.glGetFirstPerfQueryIdINTEL(&queryId); + GLenum err = GL.glGetError(); + if(err != eGL_NONE) + return false; + +#if defined(RENDERDOC_PLATFORM_ANDROID) || defined(RENDERDOC_PLATFORM_LINUX) + std::ifstream f("/proc/sys/dev/i915/perf_stream_paranoid"); + std::string contents; + std::getline(f, contents); + if(!contents.empty()) + { + int paranoid = std::stoi(contents); + if(paranoid) + { + RDCWARN( + "Not all counters available, run " + "'sudo sysctl dev.i915.perf_stream_paranoid=0' to enable more counters!"); + } + } +#endif + + do + { + addQuery(queryId); + + GL.glGetNextPerfQueryIdINTEL(queryId, &queryId); + } while(queryId != 0); + + return true; +} + +void IntelGlCounters::EnableCounter(GPUCounter index) +{ + const IntelGlCounter &counter = m_Counters[GPUCounterToCounterIndex(index)]; + + for(uint32_t p = 0; p < m_EnabledQueries.size(); p++) + { + if(m_EnabledQueries[p] == counter.queryId) + return; + } + m_EnabledQueries.push_back(counter.queryId); +} + +void IntelGlCounters::DisableAllCounters() +{ + m_EnabledQueries.clear(); +} + +uint32_t IntelGlCounters::GetPassCount() +{ + return (uint32_t)m_EnabledQueries.size(); +} + +void IntelGlCounters::BeginSession() +{ + RDCASSERT(m_glQueries.empty()); +} + +void IntelGlCounters::EndSession() +{ + for(uint32_t queryHandle : m_glQueries) + GL.glDeletePerfQueryINTEL(queryHandle); + m_glQueries.clear(); +} + +void IntelGlCounters::BeginPass(uint32_t passID) +{ + m_passIndex = passID; +} + +void IntelGlCounters::EndPass() +{ + // Flush all of the pass' queries to ensure we can begin further samples + // with a different pass. + std::vector data(m_Queries[m_EnabledQueries[m_passIndex]].size); + GLuint len; + uint32_t nSamples = (uint32_t)m_glQueries.size() / (m_passIndex + 1); + + for(uint32_t q = nSamples * m_passIndex; q < m_glQueries.size(); q++) + { + GL.glGetPerfQueryDataINTEL(m_glQueries[q], GL_PERFQUERY_WAIT_INTEL, (GLsizei)data.size(), + &data[0], &len); + } +} + +void IntelGlCounters::BeginSample(uint32_t sampleID) +{ + GLuint queryId = m_EnabledQueries[m_passIndex]; + GLuint queryHandle = 0; + + GL.glCreatePerfQueryINTEL(queryId, &queryHandle); + m_glQueries.push_back(queryHandle); + + GLenum err = GL.glGetError(); + if(err != eGL_NONE) + return; + + GL.glBeginPerfQueryINTEL(m_glQueries.back()); +} + +void IntelGlCounters::EndSample() +{ + GLuint queryHandle = m_glQueries.back(); + + if(queryHandle == 0) + return; + + GL.glEndPerfQueryINTEL(queryHandle); +} + +uint32_t IntelGlCounters::CounterPass(const IntelGlCounter &counter) +{ + for(uint32_t p = 0; p < m_EnabledQueries.size(); p++) + if(m_EnabledQueries[p] == counter.queryId) + return p; + + RDCERR("Counters not enabled"); + return 0; +} + +void IntelGlCounters::CopyData(void *dest, const IntelGlCounter &counter, uint32_t sample, + uint32_t maxSampleIndex) +{ + uint32_t pass = CounterPass(counter); + uint32_t queryHandle = m_glQueries[maxSampleIndex * pass + sample]; + + std::vector data(m_Queries[m_EnabledQueries[pass]].size); + GLuint len; + GL.glGetPerfQueryDataINTEL(queryHandle, 0, (GLsizei)data.size(), &data[0], &len); + + memcpy(dest, &data[counter.offset], counter.desc.resultByteWidth); +} + +std::vector IntelGlCounters::GetCounterData(uint32_t maxSampleIndex, + const std::vector &eventIDs, + const std::vector &counters) +{ + std::vector ret; + + RDCASSERT((maxSampleIndex * m_EnabledQueries.size()) == m_glQueries.size()); + + for(uint32_t s = 0; s < maxSampleIndex; s++) + { + for(const GPUCounter &c : counters) + { + const IntelGlCounter &counter = m_Counters[GPUCounterToCounterIndex(c)]; + switch(counter.desc.resultType) + { + case CompType::Double: + { + double r; + CopyData(&r, counter, s, maxSampleIndex); + ret.push_back(CounterResult(eventIDs[s], counter.desc.counter, r)); + break; + } + case CompType::Float: + { + float r; + CopyData(&r, counter, s, maxSampleIndex); + ret.push_back(CounterResult(eventIDs[s], counter.desc.counter, r)); + break; + } + case CompType::UInt: + { + uint64_t r; + CopyData(&r, counter, s, maxSampleIndex); + ret.push_back(CounterResult(eventIDs[s], counter.desc.counter, r)); + break; + } + default: RDCERR("Wrong counter result type: %u", counter.desc.resultType); + } + } + } + + return ret; +} diff --git a/renderdoc/driver/ihv/intel/intel_gl_counters.h b/renderdoc/driver/ihv/intel/intel_gl_counters.h new file mode 100644 index 000000000..b73dc3bf2 --- /dev/null +++ b/renderdoc/driver/ihv/intel/intel_gl_counters.h @@ -0,0 +1,132 @@ +/****************************************************************************** +* The MIT License (MIT) +* +* Copyright (c) 2018 Baldur Karlsson +* +* 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. +******************************************************************************/ + +#pragma once + +#include +#include + +#include "api/replay/renderdoc_replay.h" +#include "driver/gl/gl_common.h" +#include "replay/replay_driver.h" + +class WrappedOpenGL; + +inline constexpr GPUCounter MakeIntelGlCounter(int index) +{ + return GPUCounter((int)GPUCounter::FirstIntel + index); +} + +class IntelGlCounters +{ +public: + IntelGlCounters(); + + bool Init(); + ~IntelGlCounters(); + + std::vector GetPublicCounterIds() const; + CounterDescription GetCounterDescription(GPUCounter index) const; + + void EnableCounter(GPUCounter index); + void DisableAllCounters(); + + uint32_t GetPassCount(); + + void BeginSession(); + void EndSession(); + + void BeginPass(uint32_t passID); + void EndPass(); + + void BeginSample(uint32_t sampleID); + void EndSample(); + + std::vector GetCounterData(uint32_t maxSampleIndex, + const std::vector &eventIDs, + const std::vector &counters); + +private: + static uint32_t GPUCounterToCounterIndex(GPUCounter counter) + { + return (uint32_t)(counter) - (uint32_t)(GPUCounter::FirstIntel); + } + + struct IntelGlCounter + { + IntelGlCounter() + { + desc = CounterDescription(); + queryId = offset = type = dataType = 0; + } + IntelGlCounter(const IntelGlCounter &other) + { + desc = other.desc; + queryId = other.queryId; + offset = other.offset; + type = other.type; + dataType = other.dataType; + } + + CounterDescription desc; + GLuint queryId; + GLuint offset; + GLuint type; + GLuint dataType; + }; + std::vector m_Counters; + std::map m_CounterNames; + + struct IntelGlQuery + { + IntelGlQuery() + { + queryId = 0; + name = ""; + size = 0; + } + IntelGlQuery(const IntelGlQuery &other) + { + queryId = other.queryId; + name = other.name; + size = other.size; + } + + GLuint queryId; + std::string name; + GLuint size; + }; + std::map m_Queries; + + void addCounter(const IntelGlQuery &query, GLuint counterId); + void addQuery(GLuint queryId); + uint32_t CounterPass(const IntelGlCounter &counter); + void CopyData(void *dest, const IntelGlCounter &counter, uint32_t sample, uint32_t maxSampleIndex); + + std::vector m_EnabledQueries; + + uint32_t m_passIndex; + + std::vector m_glQueries; +};