This has the advantage of allowing full-system,
multi-process data collection.
+
+Things to change while replaying to isolate impact of different pieces
+of the pipeline (list by Eero)
+==============================
+ The interesting "what is a bottleneck" experiments are
+ (from back of 3D pipeline to front):
+ - Disable blend (= disable related dst reads)
+ - Binding 1x1 / NULL texture instead of real ones [1]
+ - Using simple pass-through pixel shader instead of real ones [2]
+ - Use kill / discard pixel shader instead of real ones
+ - Use 0x0 / 1x1 scissor rect
+ - Front+backface cull
+ - Disable draws
+
gl_cflags=$(pkg-config --cflags gl)
gl_ldflags=$(pkg-config --libs gl)
else
- printf"No.\n"
+ printf "No.\n"
have_gl=0
errors=$((errors + 1))
fi
void
context_enter (fips_api_t api, void *system_context_id)
{
+ /* Do nothing for a NULL system_context_id. (Don't ask me why,
+ * but Dota 2 likes to call MakeCurrent with a NULL context ID
+ * just before calling MakeCurrent with the same context it
+ * had been using before. We want to do nothing in this case.)
+ */
+ if (system_context_id == NULL)
+ return;
+
/* Do nothing if the application is setting the same context
* as is already current. */
if (current_context && current_context->system_id == system_context_id)
if (ctx == NULL)
return;
- metrics_destroy (ctx->metrics);
+ metrics_fini (ctx->metrics);
}
void
PFNGLGETPERFMONITORCOUNTERDATAAMDPROC
fips_dispatch_glGetPerfMonitorCounterDataAMD =
stub_glGetPerfMonitorCounterDataAMD;
+
+static void
+stub_glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize,
+ GLsizei *length, GLchar *label)
+{
+ check_initialized ();
+ resolve (fips_dispatch_glGetObjectLabel, "glGetObjectLabel");
+ fips_dispatch_glGetObjectLabel (identifier, name, bufSize,
+ length, label);
+}
+
+PFNGLGETOBJECTLABELPROC
+fips_dispatch_glGetObjectLabel =
+ stub_glGetObjectLabel;
typedef void (*PFNGLGETPERFMONITORCOUNTERDATAAMDPROC)(GLuint, GLenum,
GLsizei, GLuint *, GLint *);
+typedef void (*PFNGLGETOBJECTLABELPROC)(GLenum, GLuint, GLsizei, GLsizei *, GLchar *);
+
extern PFNGLGETINTEGERVPROC fips_dispatch_glGetIntegerv;
#define glGetIntegerv fips_dispatch_glGetIntegerv
extern PFNGLGETPERFMONITORCOUNTERDATAAMDPROC fips_dispatch_glGetPerfMonitorCounterDataAMD;
#define glGetPerfMonitorCounterDataAMD fips_dispatch_glGetPerfMonitorCounterDataAMD
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+
+extern PFNGLGETOBJECTLABELPROC fips_dispatch_glGetObjectLabel;
+#define glGetObjectLabel fips_dispatch_glGetObjectLabel
+
#endif /* FIPS_DISPATCH_GL_H */
/* Discard and cleanup any outstanding queries. */
if (metrics->timer_begun_id) {
- glEndQuery (GL_TIME_ELAPSED);
glDeleteQueries (1, &metrics->timer_begun_id);
metrics->timer_begun_id = 0;
}
if (metrics->info->have_perfmon) {
if (metrics->monitor_begun_id) {
- glEndPerfMonitorAMD (metrics->monitor_begun_id);
glDeletePerfMonitorsAMD (1, &metrics->monitor_begun_id);
metrics->monitor_begun_id = 0;
}
const char *op_string;
unsigned group_index, counter;
double value;
+ int program_name_length = 0;
/* Don't print anything for stages with no alloted time. */
if (per_stage->time_ns == 0.0)
op_string = metrics_op_string (op_metrics->op);
- printf ("%21s", op_string);
-
if (op_metrics->op >= METRICS_OP_SHADER) {
- printf (" %3d", op_metrics->op - METRICS_OP_SHADER);
- } else {
- printf (" ");
+ int program = op_metrics->op - METRICS_OP_SHADER;
+ glGetObjectLabel (GL_PROGRAM, program, 0,
+ &program_name_length, NULL);
+ if (program_name_length) {
+ char *program_name;
+
+ program_name = malloc(program_name_length + 1);
+ if (program_name == 0) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+ glGetObjectLabel (GL_PROGRAM, program,
+ program_name_length + 1,
+ NULL, program_name);
+ printf ("%21s ", program_name);
+ } else {
+ printf ("%21s %3d", op_string, program);
+ }
+ }
+ else {
+ printf ("%21s ", op_string);
}
if (per_stage->stage)
frames++;
- if (frames % 15 == 0) {
+ if (frames) {
double fps;
gettimeofday (&tv_now, NULL);