bool
MetricBackend_AMD_perfmon::testMetrics(std::vector<Metric_AMD_perfmon>* metrics) {
    unsigned monitor;
    unsigned id;
    glGenPerfMonitorsAMD(1, &monitor);
    for (Metric_AMD_perfmon &c : *metrics) {
        id = c.id();
        glSelectPerfMonitorCountersAMD(monitor, 1, c.groupId(), 1, &id);
    }
    glGetError();
    glBeginPerfMonitorAMD(monitor);
    GLenum err = glGetError();
    glEndPerfMonitorAMD(monitor);
    glDeletePerfMonitorsAMD(1, &monitor);
    if (err == GL_INVALID_OPERATION) {
        return 0;
    }
    return 1;
}
void MetricBackend_AMD_perfmon::beginPass() {
    if (!numPasses) return;
    /* First process per-frame passes, then per-call passes */
    if (curPass < numFramePasses) {
        perFrame = true;
    } else {
        perFrame = false;
    }
    /* Generate monitor */
    glGenPerfMonitorsAMD(NUM_MONITORS, monitors);
    for (Metric_AMD_perfmon &c : passes[curPass]) {
        unsigned id = c.id();
        for (auto & monitor : monitors) {
            glSelectPerfMonitorCountersAMD(monitor, 1, c.groupId(), 1, &id);
        }
    }
    curMonitor = 0;
    firstRound = true;
    curEvent = 0;
    supported = true; // can change if context is switched, so revert back
}
int MetricBackend_AMD_perfmon::enableMetric(Metric* metric_, QueryBoundary pollingRule) {
    unsigned id = metric_->id();
    unsigned gid = metric_->groupId();
    unsigned monitor;

    // profiling only draw calls
    if (pollingRule == QUERY_BOUNDARY_CALL) return 1;

    // check that Metric is valid metric
    glGenPerfMonitorsAMD(1, &monitor);
    glGetError();
    glSelectPerfMonitorCountersAMD(monitor, 1, gid, 1, &id);
    GLenum err = glGetError();
    glDeletePerfMonitorsAMD(1, &monitor);
    if (err == GL_INVALID_VALUE) {
        return 1;
    }

    Metric_AMD_perfmon metric(gid, id);
    metric.numType(); // triggers metric vars precache (in case context changes)
    metrics[pollingRule].push_back(metric);
    return 0;
}
Esempio n. 4
0
/**
 * Make sure that calling SelectPerfMonitorCountersAMD on an active monitor
 * is possible, resets active queries, and restarts monitoring (so it remains
 * active).
 *
 * This is not actually specified, but matches the behavior of AMD's driver.
 * Being an AMD extension, other implementations should probably match theirs.
 */
static void
test_change_counters_while_active(unsigned group)
{
	unsigned monitor;
	unsigned *counters;
	int num_counters;
	int max_active_counters;
	unsigned usable_counters;
	unsigned data;
	const char *test_name = "change counters while active";

	get_counters(group, &counters, &num_counters,
		     &max_active_counters);
	verify(max_active_counters >= 0);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	usable_counters = MIN2(num_counters, max_active_counters);

	if (usable_counters == 0)
		return; /* skip */

	glGenPerfMonitorsAMD(1, &monitor);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Enable counters 0 .. usable_counters from the list. */
	glSelectPerfMonitorCountersAMD(monitor, true, group, usable_counters,
				       counters);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Start monitoring */
	glBeginPerfMonitorAMD(monitor);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Turn off the first counter.  The specification is unclear whether
	 * or not this should be allowed while monitoring is active, but it
	 * apparently is (Catalyst 12.06 on a Radeon 3650).
	 */
	glSelectPerfMonitorCountersAMD(monitor, false, group, 1, counters);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Verify that all queries have been reset to 0 */
	data = 0xd0d0d0d0;
	glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD,
				       sizeof(unsigned), &data, NULL);
	verify(piglit_check_gl_error(GL_NO_ERROR));
	verify(data == 0);

	data = 0xd0d0d0d0;
	glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD,
				       sizeof(unsigned), &data, NULL);
	verify(piglit_check_gl_error(GL_NO_ERROR));
	verify(data == 0);

	/* The spec doesn't explicitly mention whether or not monitoring
	 * is still active, but apparently it is.
	 */
	glEndPerfMonitorAMD(monitor);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	glDeletePerfMonitorsAMD(1, &monitor);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	piglit_report_subtest_result(PIGLIT_PASS, "%s", test_name);
}
Esempio n. 5
0
/**
 * Basic functional test: enable all the counters in the first group
 * (up to the maximum that can be active at a time), begin monitoring,
 * end monitoring, make sure results are available, sanity check the
 * result size, and get the results.
 */
static void
test_basic_measurement(unsigned group)
{
	unsigned monitor;
	unsigned *counters;
	int num_counters;
	int max_active_counters;
	unsigned usable_counters;
	unsigned result_size = 0;
	GLsizei bytes_written = 0;
	unsigned *data;

	uint32_t *p;
	unsigned value;

	const char *test_name;

	/**
	 * Test #1: Basic Measurement.
	 *
	 * Enable all the counters in the first group (up to the maximum that
	 * can be active at a time), begin monitoring, end monitoring, make
	 * sure results are available, sanity check the result size, and get
	 * the results.
	 */
	test_name = "basic measurement";

	get_counters(group, &counters, &num_counters,
		     &max_active_counters);
	verify(max_active_counters >= 0);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	usable_counters = MIN2(num_counters, max_active_counters);

	glGenPerfMonitorsAMD(1, &monitor);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Enable counters 0 .. usable_counters from the list. */
	glSelectPerfMonitorCountersAMD(monitor, true, group, usable_counters,
				       counters);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Start monitoring */
	glBeginPerfMonitorAMD(monitor);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Drawing...meh */
	glFinish();

	/* End monitoring */
	glEndPerfMonitorAMD(monitor);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Wait for the result to be available. */
	verify(wait_until_available(monitor));
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Get the result size. */
	glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD,
				       sizeof(unsigned), &result_size, NULL);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Make sure the size is in bytes. */
	verify(result_size % sizeof(unsigned) == 0);

	/* The format is <Group ID, Group, Value>.  The first two are
	 * uint32_ts.  Value is either a float, uint32_t, or uint64_t.
	 * As a sanity check, make sure the result size is within
	 * reasonable limits.  Don't bother checking the actual types
	 * since that's a bunch of work.
	 */
	verify(result_size >= 3 * sizeof(uint32_t) * usable_counters)
	verify(result_size <=
	       (2 * sizeof(uint32_t) + sizeof(uint64_t)) * usable_counters);

	/* Get the results. */
	data = calloc(1, result_size);
	glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AMD,
				       result_size, data, &bytes_written);

	verify(bytes_written == result_size);

	piglit_report_subtest_result(PIGLIT_PASS, "%s", test_name);

	/**
	 * Test #2: Verify counter results against specified range.
	 */
	test_name = "counters in range";
	p = data;
	while ((char *) p < ((char *) data) + bytes_written) {
		uint32_t group_id = p[0];
		uint32_t counter_id = p[1];

		/* Counter values */
		uint32_t u32 = p[2];
		float f = ((float *) p)[2];

		/* Query results */
		GLenum counter_type = GL_NONE;
		uint64_t range[2];

		/* There's only one group, so it better match */
		verify(group_id == group);

		/* Getting the counter data also validates the counter ID
		 * without having to walk through the whole list of counters.
		 */
		glGetPerfMonitorCounterInfoAMD(group_id, counter_id,
					       GL_COUNTER_TYPE_AMD,
					       &counter_type);
		verify(piglit_check_gl_error(GL_NO_ERROR));

		glGetPerfMonitorCounterInfoAMD(group_id, counter_id,
					       GL_COUNTER_RANGE_AMD,
					       range);
		verify(piglit_check_gl_error(GL_NO_ERROR));

		/* Make sure it falls within the proper range */
		switch (counter_type) {
		case GL_UNSIGNED_INT: {
			uint32_t min = ((uint32_t *) range)[0];
			uint32_t max = ((uint32_t *) range)[1];
			verify(u32 >= min);
			verify(u32 <= max);
			break;
		}
		case GL_UNSIGNED_INT64_AMD: {
			uint64_t u64 = ((uint64_t *) p)[1];
			verify(u64 >= range[0]);
			verify(u64 <= range[1]);
			break;
		}
		case GL_PERCENTAGE_AMD:
		case GL_FLOAT: {
			float min = ((float *) range)[0];
			float max = ((float *) range)[1];
			verify(f >= min);
			verify(f <= max);
			break;
		}
		}

		p += (counter_type == GL_UNSIGNED_INT64_AMD) ? 4 : 3;
	}
	verify(result_size == ((char *) p - (char *) data));

	free(data);

	/**
	 * Test #3: Changing the set of active counters resets queries.
	 *
	 * "When SelectPerfMonitorCountersAMD is called on a monitor, any
	 *  outstanding results for that monitor become invalidated and the
	 *  result queries PERFMON_RESULT_SIZE_AMD and
	 *  PERFMON_RESULT_AVAILABLE_AMD are reset to 0."
	 */
	test_name = "selecting counters resets queries";

	/* Turn off the first counter. */
	glSelectPerfMonitorCountersAMD(monitor, false, group, 1, counters);
	verify(piglit_check_gl_error(GL_NO_ERROR));

	/* Results should no longer be available.  All queries should
	 * return 0.
	 */
	value = 0xd0d0d0d0;
	glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD,
				       sizeof(unsigned), &value, NULL);
	verify(piglit_check_gl_error(GL_NO_ERROR));
	verify(value == 0);

	value = 0xd0d0d0d0;
	glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD,
				       sizeof(unsigned), &value, NULL);
	verify(piglit_check_gl_error(GL_NO_ERROR));
	verify(value == 0);

	piglit_report_subtest_result(PIGLIT_PASS, "%s", test_name);

	glDeletePerfMonitorsAMD(1, &monitor);
}