* Set GALLIUM_HUD=help for more info.
*/
+#include <stdio.h>
+
#include "hud/hud_context.h"
#include "hud/hud_private.h"
#include "hud/font.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_math.h"
+#include "util/u_sampler.h"
#include "util/u_simple_shaders.h"
#include "util/u_string.h"
#include "util/u_upload_mgr.h"
/* states */
struct pipe_blend_state alpha_blend;
struct pipe_depth_stencil_alpha_state dsa;
- void *fs_color, *fs_texture;
+ void *fs_color, *fs_text;
struct pipe_rasterizer_state rasterizer;
void *vs;
struct pipe_vertex_element velems[2];
hud->constants.color[1] = g;
hud->constants.color[2] = b;
hud->constants.color[3] = a;
- hud->constants.translate[0] = xoffset;
- hud->constants.translate[1] = yoffset;
+ hud->constants.translate[0] = (float) xoffset;
+ hud->constants.translate[1] = (float) yoffset;
hud->constants.scale[0] = 1;
hud->constants.scale[1] = yscale;
cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf);
float r, float g, float b, float a)
{
float buffer[] = {
- x1, y1,
- x1, y2,
- x2, y2,
- x2, y1,
+ (float) x1, (float) y1,
+ (float) x1, (float) y2,
+ (float) x2, (float) y2,
+ (float) x2, (float) y1,
};
hud_draw_colored_prims(hud, prim, buffer, 4, r, g, b, a, 0, 0, 1);
assert(hud->bg.num_vertices + 4 <= hud->bg.max_num_vertices);
- vertices[num++] = x1;
- vertices[num++] = y1;
+ vertices[num++] = (float) x1;
+ vertices[num++] = (float) y1;
- vertices[num++] = x1;
- vertices[num++] = y2;
+ vertices[num++] = (float) x1;
+ vertices[num++] = (float) y2;
- vertices[num++] = x2;
- vertices[num++] = y2;
+ vertices[num++] = (float) x2;
+ vertices[num++] = (float) y2;
- vertices[num++] = x2;
- vertices[num++] = y1;
+ vertices[num++] = (float) x2;
+ vertices[num++] = (float) y1;
hud->bg.num_vertices += num/2;
}
assert(hud->text.num_vertices + num/4 + 4 <= hud->text.max_num_vertices);
- vertices[num++] = x1;
- vertices[num++] = y1;
- vertices[num++] = tx1;
- vertices[num++] = ty1;
+ vertices[num++] = (float) x1;
+ vertices[num++] = (float) y1;
+ vertices[num++] = (float) tx1;
+ vertices[num++] = (float) ty1;
- vertices[num++] = x1;
- vertices[num++] = y2;
- vertices[num++] = tx1;
- vertices[num++] = ty2;
+ vertices[num++] = (float) x1;
+ vertices[num++] = (float) y2;
+ vertices[num++] = (float) tx1;
+ vertices[num++] = (float) ty2;
- vertices[num++] = x2;
- vertices[num++] = y2;
- vertices[num++] = tx2;
- vertices[num++] = ty2;
+ vertices[num++] = (float) x2;
+ vertices[num++] = (float) y2;
+ vertices[num++] = (float) tx2;
+ vertices[num++] = (float) ty2;
- vertices[num++] = x2;
- vertices[num++] = y1;
- vertices[num++] = tx2;
- vertices[num++] = ty1;
+ vertices[num++] = (float) x2;
+ vertices[num++] = (float) y1;
+ vertices[num++] = (float) tx2;
+ vertices[num++] = (float) ty1;
x += hud->font.glyph_width;
s++;
}
static void
-number_to_human_readable(uint64_t num, boolean is_in_bytes, char *out)
+number_to_human_readable(uint64_t num, enum pipe_driver_query_type type,
+ char *out)
{
static const char *byte_units[] =
{"", " KB", " MB", " GB", " TB", " PB", " EB"};
static const char *metric_units[] =
{"", " k", " M", " G", " T", " P", " E"};
- const char **units = is_in_bytes ? byte_units : metric_units;
- double divisor = is_in_bytes ? 1024 : 1000;
+ static const char *time_units[] =
+ {" us", " ms", " s"}; /* based on microseconds */
+ const char *suffix;
+ double divisor = (type == PIPE_DRIVER_QUERY_TYPE_BYTES) ? 1024 : 1000;
int unit = 0;
double d = num;
unit++;
}
+ switch (type) {
+ case PIPE_DRIVER_QUERY_TYPE_MICROSECONDS:
+ assert(unit < ARRAY_SIZE(time_units));
+ suffix = time_units[unit];
+ break;
+ case PIPE_DRIVER_QUERY_TYPE_PERCENTAGE:
+ suffix = "%";
+ break;
+ case PIPE_DRIVER_QUERY_TYPE_BYTES:
+ assert(unit < ARRAY_SIZE(byte_units));
+ suffix = byte_units[unit];
+ break;
+ default:
+ assert(unit < ARRAY_SIZE(metric_units));
+ suffix = metric_units[unit];
+ }
+
if (d >= 100 || d == (int)d)
- sprintf(out, "%.0f%s", d, units[unit]);
+ sprintf(out, "%.0f%s", d, suffix);
else if (d >= 10 || d*10 == (int)(d*10))
- sprintf(out, "%.1f%s", d, units[unit]);
+ sprintf(out, "%.1f%s", d, suffix);
else
- sprintf(out, "%.2f%s", d, units[unit]);
+ sprintf(out, "%.2f%s", d, suffix);
}
static void
hud->font.glyph_height / 2;
number_to_human_readable(pane->max_value * i / 5,
- pane->uses_byte_units, str);
+ pane->type, str);
hud_draw_string(hud, x, y, str);
}
unsigned y = pane->y2 + 2 + i*hud->font.glyph_height;
number_to_human_readable(gr->current_value,
- pane->uses_byte_units, str);
+ pane->type, str);
hud_draw_string(hud, x, y, " %s: %s", gr->name, str);
i++;
}
/* draw border */
assert(hud->whitelines.num_vertices + num/2 + 8 <= hud->whitelines.max_num_vertices);
- line_verts[num++] = pane->x1;
- line_verts[num++] = pane->y1;
- line_verts[num++] = pane->x2;
- line_verts[num++] = pane->y1;
-
- line_verts[num++] = pane->x2;
- line_verts[num++] = pane->y1;
- line_verts[num++] = pane->x2;
- line_verts[num++] = pane->y2;
-
- line_verts[num++] = pane->x1;
- line_verts[num++] = pane->y2;
- line_verts[num++] = pane->x2;
- line_verts[num++] = pane->y2;
-
- line_verts[num++] = pane->x1;
- line_verts[num++] = pane->y1;
- line_verts[num++] = pane->x1;
- line_verts[num++] = pane->y2;
+ line_verts[num++] = (float) pane->x1;
+ line_verts[num++] = (float) pane->y1;
+ line_verts[num++] = (float) pane->x2;
+ line_verts[num++] = (float) pane->y1;
+
+ line_verts[num++] = (float) pane->x2;
+ line_verts[num++] = (float) pane->y1;
+ line_verts[num++] = (float) pane->x2;
+ line_verts[num++] = (float) pane->y2;
+
+ line_verts[num++] = (float) pane->x1;
+ line_verts[num++] = (float) pane->y2;
+ line_verts[num++] = (float) pane->x2;
+ line_verts[num++] = (float) pane->y2;
+
+ line_verts[num++] = (float) pane->x1;
+ line_verts[num++] = (float) pane->y1;
+ line_verts[num++] = (float) pane->x1;
+ line_verts[num++] = (float) pane->y2;
/* draw horizontal lines inside the graph */
for (i = 0; i <= 5; i++) {
hud->fb_width = tex->width0;
hud->fb_height = tex->height0;
- hud->constants.two_div_fb_width = 2.0 / hud->fb_width;
- hud->constants.two_div_fb_height = 2.0 / hud->fb_height;
+ hud->constants.two_div_fb_width = 2.0f / hud->fb_width;
+ hud->constants.two_div_fb_height = 2.0f / hud->fb_height;
cso_save_framebuffer(cso);
cso_save_sample_mask(cso);
+ cso_save_min_samples(cso);
cso_save_blend(cso);
cso_save_depth_stencil_alpha(cso);
cso_save_fragment_shader(cso);
- cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
+ cso_save_fragment_sampler_views(cso);
cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
cso_save_rasterizer(cso);
cso_save_viewport(cso);
cso_save_stream_outputs(cso);
cso_save_geometry_shader(cso);
+ cso_save_tessctrl_shader(cso);
+ cso_save_tesseval_shader(cso);
cso_save_vertex_shader(cso);
cso_save_vertex_elements(cso);
cso_save_aux_vertex_buffer_slot(cso);
viewport.scale[0] = 0.5f * hud->fb_width;
viewport.scale[1] = 0.5f * hud->fb_height;
viewport.scale[2] = 1.0f;
- viewport.scale[3] = 1.0f;
viewport.translate[0] = 0.5f * hud->fb_width;
viewport.translate[1] = 0.5f * hud->fb_height;
viewport.translate[2] = 0.0f;
- viewport.translate[3] = 0.0f;
cso_set_framebuffer(cso, &fb);
cso_set_sample_mask(cso, ~0);
+ cso_set_min_samples(cso, 1);
cso_set_blend(cso, &hud->alpha_blend);
cso_set_depth_stencil_alpha(cso, &hud->dsa);
cso_set_rasterizer(cso, &hud->rasterizer);
cso_set_viewport(cso, &viewport);
- cso_set_stream_outputs(cso, 0, NULL, 0);
+ cso_set_stream_outputs(cso, 0, NULL, NULL);
+ cso_set_tessctrl_shader_handle(cso, NULL);
+ cso_set_tesseval_shader_handle(cso, NULL);
cso_set_geometry_shader_handle(cso, NULL);
cso_set_vertex_shader_handle(cso, hud->vs);
cso_set_vertex_elements(cso, 2, hud->velems);
- cso_set_render_condition(cso, NULL, 0);
+ cso_set_render_condition(cso, NULL, FALSE, 0);
cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, 1,
&hud->font_sampler_view);
cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 1, sampler_states);
cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf);
/* prepare vertex buffers */
- hud_alloc_vertices(hud, &hud->bg, 4 * 64, 2 * sizeof(float));
+ hud_alloc_vertices(hud, &hud->bg, 4 * 128, 2 * sizeof(float));
hud_alloc_vertices(hud, &hud->whitelines, 4 * 256, 2 * sizeof(float));
hud_alloc_vertices(hud, &hud->text, 4 * 512, 4 * sizeof(float));
hud_pane_accumulate_vertices(hud, pane);
}
+ /* unmap the uploader's vertex buffer before drawing */
+ u_upload_unmap(hud->uploader);
+
/* draw accumulated vertices for background quads */
cso_set_fragment_shader_handle(hud->cso, hud->fs_color);
hud->constants.color[0] = 0;
hud->constants.color[1] = 0;
hud->constants.color[2] = 0;
- hud->constants.color[3] = 0.666;
+ hud->constants.color[3] = 0.666f;
hud->constants.translate[0] = 0;
hud->constants.translate[1] = 0;
hud->constants.scale[0] = 1;
if (hud->text.num_vertices) {
cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1,
&hud->text.vbuf);
- cso_set_fragment_shader_handle(hud->cso, hud->fs_texture);
+ cso_set_fragment_shader_handle(hud->cso, hud->fs_text);
cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->text.num_vertices);
}
pipe_resource_reference(&hud->text.vbuf.buffer, NULL);
/* restore states */
cso_restore_framebuffer(cso);
cso_restore_sample_mask(cso);
+ cso_restore_min_samples(cso);
cso_restore_blend(cso);
cso_restore_depth_stencil_alpha(cso);
cso_restore_fragment_shader(cso);
- cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
+ cso_restore_fragment_sampler_views(cso);
cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
cso_restore_rasterizer(cso);
cso_restore_viewport(cso);
cso_restore_stream_outputs(cso);
+ cso_restore_tessctrl_shader(cso);
+ cso_restore_tesseval_shader(cso);
cso_restore_geometry_shader(cso);
cso_restore_vertex_shader(cso);
cso_restore_vertex_elements(cso);
hud_pane_set_max_value(struct hud_pane *pane, uint64_t value)
{
pane->max_value = value;
- pane->yscale = -(int)pane->inner_height / (double)pane->max_value;
+ pane->yscale = -(int)pane->inner_height / (float)pane->max_value;
+}
+
+static void
+hud_pane_update_dyn_ceiling(struct hud_graph *gr, struct hud_pane *pane)
+{
+ unsigned i;
+ float tmp = 0.0f;
+
+ if (pane->dyn_ceil_last_ran != gr->index) {
+ LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) {
+ for (i = 0; i < gr->num_vertices; ++i) {
+ tmp = gr->vertices[i * 2 + 1] > tmp ?
+ gr->vertices[i * 2 + 1] : tmp;
+ }
+ }
+
+ /* Avoid setting it lower than the initial starting height. */
+ tmp = tmp > pane->initial_max_value ? tmp : pane->initial_max_value;
+ hud_pane_set_max_value(pane, tmp);
+ }
+
+ /*
+ * Mark this adjustment run so we could avoid repeating a full update
+ * again needlessly in case the pane has more than one graph.
+ */
+ pane->dyn_ceil_last_ran = gr->index;
}
static struct hud_pane *
hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
- unsigned period, uint64_t max_value)
+ unsigned period, uint64_t max_value, uint64_t ceiling,
+ boolean dyn_ceiling)
{
struct hud_pane *pane = CALLOC_STRUCT(hud_pane);
pane->inner_height = pane->inner_y2 - pane->inner_y1;
pane->period = period;
pane->max_num_vertices = (x2 - x1 + 2) / 2;
+ pane->ceiling = ceiling;
+ pane->dyn_ceiling = dyn_ceiling;
+ pane->dyn_ceil_last_ran = 0;
+ pane->initial_max_value = max_value;
hud_pane_set_max_value(pane, max_value);
LIST_INITHEAD(&pane->graph_list);
return pane;
}
assert(pane->num_graphs < Elements(colors));
- gr->vertices = malloc(pane->max_num_vertices * sizeof(float) * 2);
+ gr->vertices = MALLOC(pane->max_num_vertices * sizeof(float) * 2);
gr->color[0] = colors[pane->num_graphs][0];
gr->color[1] = colors[pane->num_graphs][1];
gr->color[2] = colors[pane->num_graphs][2];
void
hud_graph_add_value(struct hud_graph *gr, uint64_t value)
{
+ gr->current_value = value;
+ value = value > gr->pane->ceiling ? gr->pane->ceiling : value;
+
if (gr->index == gr->pane->max_num_vertices) {
gr->vertices[0] = 0;
gr->vertices[1] = gr->vertices[(gr->index-1)*2+1];
gr->index = 1;
}
- gr->vertices[(gr->index)*2+0] = gr->index*2;
- gr->vertices[(gr->index)*2+1] = value;
+ gr->vertices[(gr->index)*2+0] = (float) (gr->index * 2);
+ gr->vertices[(gr->index)*2+1] = (float) value;
gr->index++;
if (gr->num_vertices < gr->pane->max_num_vertices) {
gr->num_vertices++;
}
- gr->current_value = value;
+ if (gr->pane->dyn_ceiling == true) {
+ hud_pane_update_dyn_ceiling(gr, gr->pane);
+ }
if (value > gr->pane->max_value) {
hud_pane_set_max_value(gr->pane, value);
}
return i;
}
+static char *
+read_pane_settings(char *str, unsigned * const x, unsigned * const y,
+ unsigned * const width, unsigned * const height,
+ uint64_t * const ceiling, boolean * const dyn_ceiling)
+{
+ char *ret = str;
+ unsigned tmp;
+
+ while (*str == '.') {
+ ++str;
+ switch (*str) {
+ case 'x':
+ ++str;
+ *x = strtoul(str, &ret, 10);
+ str = ret;
+ break;
+
+ case 'y':
+ ++str;
+ *y = strtoul(str, &ret, 10);
+ str = ret;
+ break;
+
+ case 'w':
+ ++str;
+ tmp = strtoul(str, &ret, 10);
+ *width = tmp > 80 ? tmp : 80; /* 80 is chosen arbitrarily */
+ str = ret;
+ break;
+
+ /*
+ * Prevent setting height to less than 50. If the height is set to less,
+ * the text of the Y axis labels on the graph will start overlapping.
+ */
+ case 'h':
+ ++str;
+ tmp = strtoul(str, &ret, 10);
+ *height = tmp > 50 ? tmp : 50;
+ str = ret;
+ break;
+
+ case 'c':
+ ++str;
+ tmp = strtoul(str, &ret, 10);
+ *ceiling = tmp > 10 ? tmp : 10;
+ str = ret;
+ break;
+
+ case 'd':
+ ++str;
+ ret = str;
+ *dyn_ceiling = true;
+ break;
+
+ default:
+ fprintf(stderr, "gallium_hud: syntax error: unexpected '%c'\n", *str);
+ }
+
+ }
+
+ return ret;
+}
+
static boolean
has_occlusion_query(struct pipe_screen *screen)
{
return screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
}
+static boolean
+has_pipeline_stats_query(struct pipe_screen *screen)
+{
+ return screen->get_param(screen, PIPE_CAP_QUERY_PIPELINE_STATISTICS) != 0;
+}
+
static void
hud_parse_env_var(struct hud_context *hud, const char *env)
{
unsigned num, i;
- char name[256], s[256];
+ char name_a[256], s[256];
+ char *name;
struct hud_pane *pane = NULL;
unsigned x = 10, y = 10;
unsigned width = 251, height = 100;
+ unsigned period = 500 * 1000; /* default period (1/2 second) */
+ uint64_t ceiling = UINT64_MAX;
+ unsigned column_width = 251;
+ boolean dyn_ceiling = false;
+ const char *period_env;
+
+ /*
+ * The GALLIUM_HUD_PERIOD env var sets the graph update rate.
+ * The env var is in seconds (a float).
+ * Zero means update after every frame.
+ */
+ period_env = getenv("GALLIUM_HUD_PERIOD");
+ if (period_env) {
+ float p = (float) atof(period_env);
+ if (p >= 0.0f) {
+ period = (unsigned) (p * 1000 * 1000);
+ }
+ }
- while ((num = parse_string(env, name)) != 0) {
+ while ((num = parse_string(env, name_a)) != 0) {
env += num;
+ /* check for explicit location, size and etc. settings */
+ name = read_pane_settings(name_a, &x, &y, &width, &height, &ceiling,
+ &dyn_ceiling);
+
+ /*
+ * Keep track of overall column width to avoid pane overlapping in case
+ * later we create a new column while the bottom pane in the current
+ * column is less wide than the rest of the panes in it.
+ */
+ column_width = width > column_width ? width : column_width;
+
if (!pane) {
- pane = hud_pane_create(x, y, x + width, y + height, 40000, 10);
+ pane = hud_pane_create(x, y, x + width, y + height, period, 10,
+ ceiling, dyn_ceiling);
if (!pane)
return;
}
- /* add a graph */
+ /* Add a graph. */
+ /* IF YOU CHANGE THIS, UPDATE print_help! */
if (strcmp(name, "fps") == 0) {
hud_fps_graph_install(pane);
}
else if (sscanf(name, "cpu%u%s", &i, s) == 1) {
hud_cpu_graph_install(pane, i);
}
- else if (strcmp(name, "pixels-rendered") == 0 &&
+ else if (strcmp(name, "samples-passed") == 0 &&
has_occlusion_query(hud->pipe->screen)) {
- hud_pipe_query_install(pane, hud->pipe, "pixels-rendered",
- PIPE_QUERY_OCCLUSION_COUNTER, 0, FALSE);
+ hud_pipe_query_install(pane, hud->pipe, "samples-passed",
+ PIPE_QUERY_OCCLUSION_COUNTER, 0, 0,
+ PIPE_DRIVER_QUERY_TYPE_UINT64);
}
else if (strcmp(name, "primitives-generated") == 0 &&
has_streamout(hud->pipe->screen)) {
hud_pipe_query_install(pane, hud->pipe, "primitives-generated",
- PIPE_QUERY_PRIMITIVES_GENERATED, 0, FALSE);
+ PIPE_QUERY_PRIMITIVES_GENERATED, 0, 0,
+ PIPE_DRIVER_QUERY_TYPE_UINT64);
}
else {
- if (!hud_driver_query_install(pane, hud->pipe, name)){
- fprintf(stderr, "gallium_hud: unknown driver query '%s'\n", name);
+ boolean processed = FALSE;
+
+ /* pipeline statistics queries */
+ if (has_pipeline_stats_query(hud->pipe->screen)) {
+ static const char *pipeline_statistics_names[] =
+ {
+ "ia-vertices",
+ "ia-primitives",
+ "vs-invocations",
+ "gs-invocations",
+ "gs-primitives",
+ "clipper-invocations",
+ "clipper-primitives-generated",
+ "ps-invocations",
+ "hs-invocations",
+ "ds-invocations",
+ "cs-invocations"
+ };
+ for (i = 0; i < Elements(pipeline_statistics_names); ++i)
+ if (strcmp(name, pipeline_statistics_names[i]) == 0)
+ break;
+ if (i < Elements(pipeline_statistics_names)) {
+ hud_pipe_query_install(pane, hud->pipe, name,
+ PIPE_QUERY_PIPELINE_STATISTICS, i,
+ 0, PIPE_DRIVER_QUERY_TYPE_UINT64);
+ processed = TRUE;
+ }
+ }
+
+ /* driver queries */
+ if (!processed) {
+ if (!hud_driver_query_install(pane, hud->pipe, name)){
+ fprintf(stderr, "gallium_hud: unknown driver query '%s'\n", name);
+ }
}
}
if (num && sscanf(s, "%u", &i) == 1) {
hud_pane_set_max_value(pane, i);
+ pane->initial_max_value = i;
}
else {
fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) "
case ',':
env++;
y += height + hud->font.glyph_height * (pane->num_graphs + 2);
+ height = 100;
if (pane && pane->num_graphs) {
LIST_ADDTAIL(&pane->head, &hud->pane_list);
case ';':
env++;
y = 10;
- x += width + hud->font.glyph_width * 7;
+ x += column_width + hud->font.glyph_width * 7;
+ height = 100;
if (pane && pane->num_graphs) {
LIST_ADDTAIL(&pane->head, &hud->pane_list);
pane = NULL;
}
+
+ /* Starting a new column; reset column width. */
+ column_width = 251;
break;
default:
fprintf(stderr, "gallium_hud: syntax error: unexpected '%c'\n", *env);
}
+
+ /* Reset to defaults for the next pane in case these were modified. */
+ width = 251;
+ ceiling = UINT64_MAX;
+ dyn_ceiling = false;
+
}
if (pane) {
puts("");
puts(" Example: GALLIUM_HUD=\"cpu,fps;primitives-generated\"");
puts("");
+ puts(" Additionally, by prepending '.[identifier][value]' modifiers to");
+ puts(" a name, it is possible to explicitly set the location and size");
+ puts(" of a pane, along with limiting overall maximum value of the");
+ puts(" Y axis and activating dynamic readjustment of the Y axis.");
+ puts(" Several modifiers may be applied to the same pane simultaneously.");
+ puts("");
+ puts(" 'x[value]' sets the location of the pane on the x axis relative");
+ puts(" to the upper-left corner of the viewport, in pixels.");
+ puts(" 'y[value]' sets the location of the pane on the y axis relative");
+ puts(" to the upper-left corner of the viewport, in pixels.");
+ puts(" 'w[value]' sets width of the graph pixels.");
+ puts(" 'h[value]' sets height of the graph in pixels.");
+ puts(" 'c[value]' sets the ceiling of the value of the Y axis.");
+ puts(" If the graph needs to draw values higher than");
+ puts(" the ceiling allows, the value is clamped.");
+ puts(" 'd' activates dynamic Y axis readjustment to set the value of");
+ puts(" the Y axis to match the highest value still visible in the graph.");
+ puts("");
+ puts(" If 'c' and 'd' modifiers are used simultaneously, both are in effect:");
+ puts(" the Y axis does not go above the restriction imposed by 'c' while");
+ puts(" still adjusting the value of the Y axis down when appropriate.");
+ puts("");
+ puts(" Example: GALLIUM_HUD=\".w256.h64.x1600.y520.d.c1000fps+cpu,.datom-count\"");
+ puts("");
puts(" Available names:");
puts(" fps");
puts(" cpu");
printf(" cpu%i\n", i);
if (has_occlusion_query(screen))
- puts(" pixels-rendered");
+ puts(" samples-passed");
if (has_streamout(screen))
puts(" primitives-generated");
+ if (has_pipeline_stats_query(screen)) {
+ puts(" ia-vertices");
+ puts(" ia-primitives");
+ puts(" vs-invocations");
+ puts(" gs-invocations");
+ puts(" gs-primitives");
+ puts(" clipper-invocations");
+ puts(" clipper-primitives-generated");
+ puts(" ps-invocations");
+ puts(" hs-invocations");
+ puts(" ds-invocations");
+ puts(" cs-invocations");
+ }
+
if (screen->get_driver_query_info){
struct pipe_driver_query_info info;
num_queries = screen->get_driver_query_info(screen, 0, NULL);
}
puts("");
+ fflush(stdout);
}
struct hud_context *
hud->fs_color =
util_make_fragment_passthrough_shader(pipe,
TGSI_SEMANTIC_COLOR,
- TGSI_INTERPOLATE_CONSTANT);
+ TGSI_INTERPOLATE_CONSTANT,
+ TRUE);
+
+ {
+ /* Read a texture and do .xxxx swizzling. */
+ static const char *fragment_shader_text = {
+ "FRAG\n"
+ "DCL IN[0], GENERIC[0], LINEAR\n"
+ "DCL SAMP[0]\n"
+ "DCL OUT[0], COLOR[0]\n"
+ "DCL TEMP[0]\n"
+
+ "TEX TEMP[0], IN[0], SAMP[0], RECT\n"
+ "MOV OUT[0], TEMP[0].xxxx\n"
+ "END\n"
+ };
- hud->fs_texture =
- util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_RECT,
- TGSI_INTERPOLATE_PERSPECTIVE);
+ struct tgsi_token tokens[1000];
+ struct pipe_shader_state state = {tokens};
+
+ if (!tgsi_text_translate(fragment_shader_text, tokens, Elements(tokens))) {
+ assert(0);
+ pipe_resource_reference(&hud->font.texture, NULL);
+ u_upload_destroy(hud->uploader);
+ FREE(hud);
+ return NULL;
+ }
+
+ hud->fs_text = pipe->create_fs_state(pipe, &state);
+ }
/* rasterizer */
- hud->rasterizer.gl_rasterization_rules = 1;
+ hud->rasterizer.half_pixel_center = 1;
+ hud->rasterizer.bottom_edge_rule = 1;
hud->rasterizer.depth_clip = 1;
hud->rasterizer.line_width = 1;
hud->rasterizer.line_last_pixel = 1;
}
/* sampler view */
- memset(&view_templ, 0, sizeof(view_templ));
- view_templ.format = hud->font.texture->format;
- view_templ.swizzle_r = PIPE_SWIZZLE_RED;
- view_templ.swizzle_g = PIPE_SWIZZLE_GREEN;
- view_templ.swizzle_b = PIPE_SWIZZLE_BLUE;
- view_templ.swizzle_a = PIPE_SWIZZLE_ALPHA;
+ u_sampler_view_default_template(
+ &view_templ, hud->font.texture, hud->font.texture->format);
hud->font_sampler_view = pipe->create_sampler_view(pipe, hud->font.texture,
&view_templ);
+ /* sampler state (for font drawing) */
+ hud->font_sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ hud->font_sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ hud->font_sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ hud->font_sampler_state.normalized_coords = 0;
+
/* constants */
hud->constbuf.buffer_size = sizeof(hud->constants);
hud->constbuf.user_buffer = &hud->constants;
}
pipe->delete_fs_state(pipe, hud->fs_color);
- pipe->delete_fs_state(pipe, hud->fs_texture);
+ pipe->delete_fs_state(pipe, hud->fs_text);
pipe->delete_vs_state(pipe, hud->vs);
pipe_sampler_view_reference(&hud->font_sampler_view, NULL);
pipe_resource_reference(&hud->font.texture, NULL);