void MetricBackend_AMD_perfmon::freeMonitor(unsigned monitorId) {
    unsigned monitor = monitors[monitorId];
    GLuint dataAvail = 0;
    GLuint size;

    glFlush();
    while (!dataAvail) {
        glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD,
                                       sizeof(GLuint), &dataAvail, nullptr);
    }
    glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD,
                                   sizeof(GLuint), &size, nullptr);
    // collect data
    unsigned* buf = collector.newDataBuffer(monitorEvent[monitorId],
                                            size/sizeof(unsigned));
    glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AMD, size, buf, nullptr);

    /* populate metricOffsets */
    if (metricOffsets.size() < curPass + 1) {
        std::map<std::pair<unsigned, unsigned>, unsigned> pairOffsets;
        unsigned offset = 0;
        unsigned id, gid;
        for (int k = 0; k < passes[curPass].size(); k++) {
            gid = buf[offset++];
            id = buf[offset++];
            pairOffsets[std::make_pair(gid, id)] = offset;
            Metric_AMD_perfmon metric(gid, id);
            offset += metric.size() / sizeof(unsigned);
        }
        // translate to existing metrics in passes variable
        std::map<Metric_AMD_perfmon*, unsigned> temp;
        for (auto &m : passes[curPass]) {
            id = m.id();
            gid = m.groupId();
            temp[&m] = pairOffsets[std::make_pair(gid, id)];
        }
        metricOffsets.push_back(std::move(temp));
    }
}
Пример #2
0
/**
 * Poll until PERFMON_RESULT_AVAILABLE returns 1; glFinish() on each iteration.
 *
 * Only loop for 5 times to guard against implementations that never finish.
 */
static bool
wait_until_available(unsigned monitor)
{
	int i;
	unsigned available = 0;
	for (i = 0; !available && i < 5; i++) {
		glFinish();
		glGetPerfMonitorCounterDataAMD(monitor,
					       GL_PERFMON_RESULT_AVAILABLE_AMD,
					       sizeof(unsigned), &available,
					       NULL);
	}
	return available;
}
Пример #3
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);
}
Пример #4
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);
}