Merge remote-tracking branch 'mesa-public/master' into vulkan

This commit is contained in:
Jason Ekstrand 2015-08-26 11:04:30 -07:00
commit 36134e1050
97 changed files with 3176 additions and 3496 deletions

View file

@ -2330,6 +2330,7 @@ AC_CONFIG_FILES([Makefile
src/gallium/auxiliary/Makefile
src/gallium/auxiliary/pipe-loader/Makefile
src/gallium/drivers/freedreno/Makefile
src/gallium/drivers/ddebug/Makefile
src/gallium/drivers/i915/Makefile
src/gallium/drivers/ilo/Makefile
src/gallium/drivers/llvmpipe/Makefile

View file

@ -11,6 +11,7 @@ SUBDIRS += auxiliary
##
SUBDIRS += \
drivers/ddebug \
drivers/noop \
drivers/trace \
drivers/rbug

View file

@ -11,6 +11,10 @@
* one or more debug driver: rbug, trace.
*/
#ifdef GALLIUM_DDEBUG
#include "ddebug/dd_public.h"
#endif
#ifdef GALLIUM_TRACE
#include "trace/tr_public.h"
#endif
@ -30,6 +34,10 @@
static inline struct pipe_screen *
debug_screen_wrap(struct pipe_screen *screen)
{
#if defined(GALLIUM_DDEBUG)
screen = ddebug_screen_create(screen);
#endif
#if defined(GALLIUM_RBUG)
screen = rbug_screen_create(screen);
#endif

View file

@ -21,7 +21,8 @@
* DEALINGS IN THE SOFTWARE.
*/
/* Copied from EXT_texture_shared_exponent and edited. */
/* Copied from EXT_texture_shared_exponent and edited, getting rid of
* expensive float math bits too. */
#ifndef RGB9E5_H
#define RGB9E5_H
@ -39,7 +40,6 @@
#define RGB9E5_MANTISSA_VALUES (1<<RGB9E5_MANTISSA_BITS)
#define MAX_RGB9E5_MANTISSA (RGB9E5_MANTISSA_VALUES-1)
#define MAX_RGB9E5 (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP))
#define EPSILON_RGB9E5 ((1.0/RGB9E5_MANTISSA_VALUES) / (1<<RGB9E5_EXP_BIAS))
typedef union {
unsigned int raw;
@ -74,63 +74,59 @@ typedef union {
} field;
} rgb9e5;
static inline float rgb9e5_ClampRange(float x)
{
if (x > 0.0f) {
if (x >= MAX_RGB9E5) {
return MAX_RGB9E5;
} else {
return x;
}
} else {
/* NaN gets here too since comparisons with NaN always fail! */
return 0.0;
}
}
/* Ok, FloorLog2 is not correct for the denorm and zero values, but we
are going to do a max of this value with the minimum rgb9e5 exponent
that will hide these problem cases. */
static inline int rgb9e5_FloorLog2(float x)
static inline int rgb9e5_ClampRange(float x)
{
float754 f;
float754 max;
f.value = x;
return (f.field.biasedexponent - 127);
max.value = MAX_RGB9E5;
if (f.raw > 0x7f800000)
/* catches neg, NaNs */
return 0;
else if (f.raw >= max.raw)
return max.raw;
else
return f.raw;
}
static inline unsigned float3_to_rgb9e5(const float rgb[3])
{
rgb9e5 retval;
float maxrgb;
int rm, gm, bm;
float rc, gc, bc;
int exp_shared, maxm;
double denom;
int rm, gm, bm, exp_shared;
float754 revdenom = {0};
float754 rc, bc, gc, maxrgb;
rc = rgb9e5_ClampRange(rgb[0]);
gc = rgb9e5_ClampRange(rgb[1]);
bc = rgb9e5_ClampRange(rgb[2]);
rc.raw = rgb9e5_ClampRange(rgb[0]);
gc.raw = rgb9e5_ClampRange(rgb[1]);
bc.raw = rgb9e5_ClampRange(rgb[2]);
maxrgb.raw = MAX3(rc.raw, gc.raw, bc.raw);
maxrgb = MAX3(rc, gc, bc);
exp_shared = MAX2(-RGB9E5_EXP_BIAS-1, rgb9e5_FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS;
/*
* Compared to what the spec suggests, instead of conditionally adjusting
* the exponent after the fact do it here by doing the equivalent of +0.5 -
* the int add will spill over into the exponent in this case.
*/
maxrgb.raw += maxrgb.raw & (1 << (23-9));
exp_shared = MAX2((maxrgb.raw >> 23), -RGB9E5_EXP_BIAS - 1 + 127) +
1 + RGB9E5_EXP_BIAS - 127;
revdenom.field.biasedexponent = 127 - (exp_shared - RGB9E5_EXP_BIAS -
RGB9E5_MANTISSA_BITS) + 1;
assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
assert(exp_shared >= 0);
/* This exp2 function could be replaced by a table. */
denom = exp2(exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS);
maxm = (int) floor(maxrgb / denom + 0.5);
if (maxm == MAX_RGB9E5_MANTISSA+1) {
denom *= 2;
exp_shared += 1;
assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
} else {
assert(maxm <= MAX_RGB9E5_MANTISSA);
}
rm = (int) floor(rc / denom + 0.5);
gm = (int) floor(gc / denom + 0.5);
bm = (int) floor(bc / denom + 0.5);
/*
* The spec uses strict round-up behavior (d3d10 disagrees, but in any case
* must match what is done above for figuring out exponent).
* We avoid the doubles ((int) rc * revdenom + 0.5) by doing the rounding
* ourselves (revdenom was adjusted by +1, above).
*/
rm = (int) (rc.value * revdenom.value);
gm = (int) (gc.value * revdenom.value);
bm = (int) (bc.value * revdenom.value);
rm = (rm & 1) + (rm >> 1);
gm = (gm & 1) + (gm >> 1);
bm = (bm & 1) + (bm >> 1);
assert(rm <= MAX_RGB9E5_MANTISSA);
assert(gm <= MAX_RGB9E5_MANTISSA);
@ -151,15 +147,15 @@ static inline void rgb9e5_to_float3(unsigned rgb, float retval[3])
{
rgb9e5 v;
int exponent;
float scale;
float754 scale = {0};
v.raw = rgb;
exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS;
scale = exp2f(exponent);
scale.field.biasedexponent = exponent + 127;
retval[0] = v.field.r * scale;
retval[1] = v.field.g * scale;
retval[2] = v.field.b * scale;
retval[0] = v.field.r * scale.value;
retval[1] = v.field.g * scale.value;
retval[2] = v.field.b * scale.value;
}
#endif

View file

@ -457,7 +457,7 @@ null_constant_buffer(struct pipe_context *ctx)
void
util_run_tests(struct pipe_screen *screen)
{
struct pipe_context *ctx = screen->context_create(screen, NULL);
struct pipe_context *ctx = screen->context_create(screen, NULL, 0);
tgsi_vs_window_space_position(ctx);
null_sampler_view(ctx, TGSI_TEXTURE_2D);

View file

@ -1120,7 +1120,7 @@ vl_create_mpeg12_decoder(struct pipe_context *context,
dec->base = *templat;
dec->base.context = context;
dec->context = context->screen->context_create(context->screen, NULL);
dec->context = context->screen->context_create(context->screen, NULL, 0);
dec->base.destroy = vl_mpeg12_destroy;
dec->base.begin_frame = vl_mpeg12_begin_frame;

View file

@ -0,0 +1,9 @@
include Makefile.sources
include $(top_srcdir)/src/gallium/Automake.inc
AM_CFLAGS = \
$(GALLIUM_DRIVER_CFLAGS)
noinst_LTLIBRARIES = libddebug.la
libddebug_la_SOURCES = $(C_SOURCES)

View file

@ -0,0 +1,6 @@
C_SOURCES := \
dd_pipe.h \
dd_public.h \
dd_context.c \
dd_draw.c \
dd_screen.c

View file

@ -0,0 +1,771 @@
/**************************************************************************
*
* Copyright 2015 Advanced Micro Devices, Inc.
* Copyright 2008 VMware, Inc.
* All Rights Reserved.
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, 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 (including the next
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "dd_pipe.h"
#include "tgsi/tgsi_parse.h"
#include "util/u_memory.h"
static void
safe_memcpy(void *dst, const void *src, size_t size)
{
if (src)
memcpy(dst, src, size);
else
memset(dst, 0, size);
}
/********************************************************************
* queries
*/
static struct dd_query *
dd_query(struct pipe_query *query)
{
return (struct dd_query *)query;
}
static struct pipe_query *
dd_query_unwrap(struct pipe_query *query)
{
if (query) {
return dd_query(query)->query;
} else {
return NULL;
}
}
static struct pipe_query *
dd_context_create_query(struct pipe_context *_pipe, unsigned query_type,
unsigned index)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
struct pipe_query *query;
query = pipe->create_query(pipe, query_type, index);
/* Wrap query object. */
if (query) {
struct dd_query *dd_query = CALLOC_STRUCT(dd_query);
if (dd_query) {
dd_query->type = query_type;
dd_query->query = query;
query = (struct pipe_query *)dd_query;
} else {
pipe->destroy_query(pipe, query);
query = NULL;
}
}
return query;
}
static void
dd_context_destroy_query(struct pipe_context *_pipe,
struct pipe_query *query)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->destroy_query(pipe, dd_query_unwrap(query));
FREE(query);
}
static boolean
dd_context_begin_query(struct pipe_context *_pipe, struct pipe_query *query)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
return pipe->begin_query(pipe, dd_query_unwrap(query));
}
static void
dd_context_end_query(struct pipe_context *_pipe, struct pipe_query *query)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
pipe->end_query(pipe, dd_query_unwrap(query));
}
static boolean
dd_context_get_query_result(struct pipe_context *_pipe,
struct pipe_query *query, boolean wait,
union pipe_query_result *result)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
return pipe->get_query_result(pipe, dd_query_unwrap(query), wait, result);
}
static void
dd_context_render_condition(struct pipe_context *_pipe,
struct pipe_query *query, boolean condition,
uint mode)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
pipe->render_condition(pipe, dd_query_unwrap(query), condition, mode);
dctx->render_cond.query = dd_query(query);
dctx->render_cond.condition = condition;
dctx->render_cond.mode = mode;
}
/********************************************************************
* constant (immutable) non-shader states
*/
#define DD_CSO_CREATE(name, shortname) \
static void * \
dd_context_create_##name##_state(struct pipe_context *_pipe, \
const struct pipe_##name##_state *state) \
{ \
struct pipe_context *pipe = dd_context(_pipe)->pipe; \
struct dd_state *hstate = CALLOC_STRUCT(dd_state); \
\
if (!hstate) \
return NULL; \
hstate->cso = pipe->create_##name##_state(pipe, state); \
hstate->state.shortname = *state; \
return hstate; \
}
#define DD_CSO_BIND(name, shortname) \
static void \
dd_context_bind_##name##_state(struct pipe_context *_pipe, void *state) \
{ \
struct dd_context *dctx = dd_context(_pipe); \
struct pipe_context *pipe = dctx->pipe; \
struct dd_state *hstate = state; \
\
dctx->shortname = hstate; \
pipe->bind_##name##_state(pipe, hstate ? hstate->cso : NULL); \
}
#define DD_CSO_DELETE(name) \
static void \
dd_context_delete_##name##_state(struct pipe_context *_pipe, void *state) \
{ \
struct dd_context *dctx = dd_context(_pipe); \
struct pipe_context *pipe = dctx->pipe; \
struct dd_state *hstate = state; \
\
pipe->delete_##name##_state(pipe, hstate->cso); \
FREE(hstate); \
}
#define DD_CSO_WHOLE(name, shortname) \
DD_CSO_CREATE(name, shortname) \
DD_CSO_BIND(name, shortname) \
DD_CSO_DELETE(name)
DD_CSO_WHOLE(blend, blend)
DD_CSO_WHOLE(rasterizer, rs)
DD_CSO_WHOLE(depth_stencil_alpha, dsa)
DD_CSO_CREATE(sampler, sampler)
DD_CSO_DELETE(sampler)
static void
dd_context_bind_sampler_states(struct pipe_context *_pipe, unsigned shader,
unsigned start, unsigned count, void **states)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
memcpy(&dctx->sampler_states[shader][start], states,
sizeof(void*) * count);
if (states) {
void *samp[PIPE_MAX_SAMPLERS];
int i;
for (i = 0; i < count; i++) {
struct dd_state *s = states[i];
samp[i] = s ? s->cso : NULL;
}
pipe->bind_sampler_states(pipe, shader, start, count, samp);
}
else
pipe->bind_sampler_states(pipe, shader, start, count, NULL);
}
static void *
dd_context_create_vertex_elements_state(struct pipe_context *_pipe,
unsigned num_elems,
const struct pipe_vertex_element *elems)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
struct dd_state *hstate = CALLOC_STRUCT(dd_state);
if (!hstate)
return NULL;
hstate->cso = pipe->create_vertex_elements_state(pipe, num_elems, elems);
memcpy(hstate->state.velems.velems, elems, sizeof(elems[0]) * num_elems);
hstate->state.velems.count = num_elems;
return hstate;
}
DD_CSO_BIND(vertex_elements, velems)
DD_CSO_DELETE(vertex_elements)
/********************************************************************
* shaders
*/
#define DD_SHADER(NAME, name) \
static void * \
dd_context_create_##name##_state(struct pipe_context *_pipe, \
const struct pipe_shader_state *state) \
{ \
struct pipe_context *pipe = dd_context(_pipe)->pipe; \
struct dd_state *hstate = CALLOC_STRUCT(dd_state); \
\
if (!hstate) \
return NULL; \
hstate->cso = pipe->create_##name##_state(pipe, state); \
hstate->state.shader = *state; \
hstate->state.shader.tokens = tgsi_dup_tokens(state->tokens); \
return hstate; \
} \
\
static void \
dd_context_bind_##name##_state(struct pipe_context *_pipe, void *state) \
{ \
struct dd_context *dctx = dd_context(_pipe); \
struct pipe_context *pipe = dctx->pipe; \
struct dd_state *hstate = state; \
\
dctx->shaders[PIPE_SHADER_##NAME] = hstate; \
pipe->bind_##name##_state(pipe, hstate ? hstate->cso : NULL); \
} \
\
static void \
dd_context_delete_##name##_state(struct pipe_context *_pipe, void *state) \
{ \
struct dd_context *dctx = dd_context(_pipe); \
struct pipe_context *pipe = dctx->pipe; \
struct dd_state *hstate = state; \
\
pipe->delete_##name##_state(pipe, hstate->cso); \
tgsi_free_tokens(hstate->state.shader.tokens); \
FREE(hstate); \
}
DD_SHADER(FRAGMENT, fs)
DD_SHADER(VERTEX, vs)
DD_SHADER(GEOMETRY, gs)
DD_SHADER(TESS_CTRL, tcs)
DD_SHADER(TESS_EVAL, tes)
/********************************************************************
* immediate states
*/
#define DD_IMM_STATE(name, type, deref, ref) \
static void \
dd_context_set_##name(struct pipe_context *_pipe, type deref) \
{ \
struct dd_context *dctx = dd_context(_pipe); \
struct pipe_context *pipe = dctx->pipe; \
\
dctx->name = deref; \
pipe->set_##name(pipe, ref); \
}
DD_IMM_STATE(blend_color, const struct pipe_blend_color, *state, state)
DD_IMM_STATE(stencil_ref, const struct pipe_stencil_ref, *state, state)
DD_IMM_STATE(clip_state, const struct pipe_clip_state, *state, state)
DD_IMM_STATE(sample_mask, unsigned, sample_mask, sample_mask)
DD_IMM_STATE(min_samples, unsigned, min_samples, min_samples)
DD_IMM_STATE(framebuffer_state, const struct pipe_framebuffer_state, *state, state)
DD_IMM_STATE(polygon_stipple, const struct pipe_poly_stipple, *state, state)
static void
dd_context_set_constant_buffer(struct pipe_context *_pipe,
uint shader, uint index,
struct pipe_constant_buffer *constant_buffer)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
safe_memcpy(&dctx->constant_buffers[shader][index], constant_buffer,
sizeof(*constant_buffer));
pipe->set_constant_buffer(pipe, shader, index, constant_buffer);
}
static void
dd_context_set_scissor_states(struct pipe_context *_pipe,
unsigned start_slot, unsigned num_scissors,
const struct pipe_scissor_state *states)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
safe_memcpy(&dctx->scissors[start_slot], states,
sizeof(*states) * num_scissors);
pipe->set_scissor_states(pipe, start_slot, num_scissors, states);
}
static void
dd_context_set_viewport_states(struct pipe_context *_pipe,
unsigned start_slot, unsigned num_viewports,
const struct pipe_viewport_state *states)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
safe_memcpy(&dctx->viewports[start_slot], states,
sizeof(*states) * num_viewports);
pipe->set_viewport_states(pipe, start_slot, num_viewports, states);
}
static void dd_context_set_tess_state(struct pipe_context *_pipe,
const float default_outer_level[4],
const float default_inner_level[2])
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
memcpy(dctx->tess_default_levels, default_outer_level, sizeof(float) * 4);
memcpy(dctx->tess_default_levels+4, default_inner_level, sizeof(float) * 2);
pipe->set_tess_state(pipe, default_outer_level, default_inner_level);
}
/********************************************************************
* views
*/
static struct pipe_surface *
dd_context_create_surface(struct pipe_context *_pipe,
struct pipe_resource *resource,
const struct pipe_surface *surf_tmpl)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
struct pipe_surface *view =
pipe->create_surface(pipe, resource, surf_tmpl);
if (!view)
return NULL;
view->context = _pipe;
return view;
}
static void
dd_context_surface_destroy(struct pipe_context *_pipe,
struct pipe_surface *surf)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->surface_destroy(pipe, surf);
}
static struct pipe_sampler_view *
dd_context_create_sampler_view(struct pipe_context *_pipe,
struct pipe_resource *resource,
const struct pipe_sampler_view *templ)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
struct pipe_sampler_view *view =
pipe->create_sampler_view(pipe, resource, templ);
if (!view)
return NULL;
view->context = _pipe;
return view;
}
static void
dd_context_sampler_view_destroy(struct pipe_context *_pipe,
struct pipe_sampler_view *view)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->sampler_view_destroy(pipe, view);
}
static struct pipe_image_view *
dd_context_create_image_view(struct pipe_context *_pipe,
struct pipe_resource *resource,
const struct pipe_image_view *templ)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
struct pipe_image_view *view =
pipe->create_image_view(pipe, resource, templ);
if (!view)
return NULL;
view->context = _pipe;
return view;
}
static void
dd_context_image_view_destroy(struct pipe_context *_pipe,
struct pipe_image_view *view)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->image_view_destroy(pipe, view);
}
static struct pipe_stream_output_target *
dd_context_create_stream_output_target(struct pipe_context *_pipe,
struct pipe_resource *res,
unsigned buffer_offset,
unsigned buffer_size)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
struct pipe_stream_output_target *view =
pipe->create_stream_output_target(pipe, res, buffer_offset,
buffer_size);
if (!view)
return NULL;
view->context = _pipe;
return view;
}
static void
dd_context_stream_output_target_destroy(struct pipe_context *_pipe,
struct pipe_stream_output_target *target)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->stream_output_target_destroy(pipe, target);
}
/********************************************************************
* set states
*/
static void
dd_context_set_sampler_views(struct pipe_context *_pipe, unsigned shader,
unsigned start, unsigned num,
struct pipe_sampler_view **views)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
safe_memcpy(&dctx->sampler_views[shader][start], views,
sizeof(views[0]) * num);
pipe->set_sampler_views(pipe, shader, start, num, views);
}
static void
dd_context_set_shader_images(struct pipe_context *_pipe, unsigned shader,
unsigned start, unsigned num,
struct pipe_image_view **views)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
safe_memcpy(&dctx->shader_images[shader][start], views,
sizeof(views[0]) * num);
pipe->set_shader_images(pipe, shader, start, num, views);
}
static void
dd_context_set_shader_buffers(struct pipe_context *_pipe, unsigned shader,
unsigned start, unsigned num_buffers,
struct pipe_shader_buffer *buffers)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
safe_memcpy(&dctx->shader_buffers[shader][start], buffers,
sizeof(buffers[0]) * num_buffers);
pipe->set_shader_buffers(pipe, shader, start, num_buffers, buffers);
}
static void
dd_context_set_vertex_buffers(struct pipe_context *_pipe,
unsigned start, unsigned num_buffers,
const struct pipe_vertex_buffer *buffers)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
safe_memcpy(&dctx->vertex_buffers[start], buffers,
sizeof(buffers[0]) * num_buffers);
pipe->set_vertex_buffers(pipe, start, num_buffers, buffers);
}
static void
dd_context_set_index_buffer(struct pipe_context *_pipe,
const struct pipe_index_buffer *ib)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
safe_memcpy(&dctx->index_buffer, ib, sizeof(*ib));
pipe->set_index_buffer(pipe, ib);
}
static void
dd_context_set_stream_output_targets(struct pipe_context *_pipe,
unsigned num_targets,
struct pipe_stream_output_target **tgs,
const unsigned *offsets)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
dctx->num_so_targets = num_targets;
safe_memcpy(dctx->so_targets, tgs, sizeof(*tgs) * num_targets);
safe_memcpy(dctx->so_offsets, offsets, sizeof(*offsets) * num_targets);
pipe->set_stream_output_targets(pipe, num_targets, tgs, offsets);
}
static void
dd_context_destroy(struct pipe_context *_pipe)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
pipe->destroy(pipe);
FREE(dctx);
}
/********************************************************************
* transfer
*/
static void *
dd_context_transfer_map(struct pipe_context *_pipe,
struct pipe_resource *resource, unsigned level,
unsigned usage, const struct pipe_box *box,
struct pipe_transfer **transfer)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
return pipe->transfer_map(pipe, resource, level, usage, box, transfer);
}
static void
dd_context_transfer_flush_region(struct pipe_context *_pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->transfer_flush_region(pipe, transfer, box);
}
static void
dd_context_transfer_unmap(struct pipe_context *_pipe,
struct pipe_transfer *transfer)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->transfer_unmap(pipe, transfer);
}
static void
dd_context_transfer_inline_write(struct pipe_context *_pipe,
struct pipe_resource *resource,
unsigned level, unsigned usage,
const struct pipe_box *box,
const void *data, unsigned stride,
unsigned layer_stride)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->transfer_inline_write(pipe, resource, level, usage, box, data,
stride, layer_stride);
}
/********************************************************************
* miscellaneous
*/
static void
dd_context_texture_barrier(struct pipe_context *_pipe)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->texture_barrier(pipe);
}
static void
dd_context_memory_barrier(struct pipe_context *_pipe, unsigned flags)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->memory_barrier(pipe, flags);
}
static void
dd_context_get_sample_position(struct pipe_context *_pipe,
unsigned sample_count, unsigned sample_index,
float *out_value)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
return pipe->get_sample_position(pipe, sample_count, sample_index,
out_value);
}
static void
dd_context_invalidate_resource(struct pipe_context *_pipe,
struct pipe_resource *resource)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
pipe->invalidate_resource(pipe, resource);
}
static enum pipe_reset_status
dd_context_get_device_reset_status(struct pipe_context *_pipe)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
return pipe->get_device_reset_status(pipe);
}
static void
dd_context_dump_debug_state(struct pipe_context *_pipe, FILE *stream,
unsigned flags)
{
struct pipe_context *pipe = dd_context(_pipe)->pipe;
return pipe->dump_debug_state(pipe, stream, flags);
}
struct pipe_context *
dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe)
{
struct dd_context *dctx;
if (!pipe)
return NULL;
dctx = CALLOC_STRUCT(dd_context);
if (!dctx) {
pipe->destroy(pipe);
return NULL;
}
dctx->pipe = pipe;
dctx->base.priv = pipe->priv; /* expose wrapped priv data */
dctx->base.screen = &dscreen->base;
dctx->base.destroy = dd_context_destroy;
CTX_INIT(render_condition);
CTX_INIT(create_query);
CTX_INIT(destroy_query);
CTX_INIT(begin_query);
CTX_INIT(end_query);
CTX_INIT(get_query_result);
CTX_INIT(create_blend_state);
CTX_INIT(bind_blend_state);
CTX_INIT(delete_blend_state);
CTX_INIT(create_sampler_state);
CTX_INIT(bind_sampler_states);
CTX_INIT(delete_sampler_state);
CTX_INIT(create_rasterizer_state);
CTX_INIT(bind_rasterizer_state);
CTX_INIT(delete_rasterizer_state);
CTX_INIT(create_depth_stencil_alpha_state);
CTX_INIT(bind_depth_stencil_alpha_state);
CTX_INIT(delete_depth_stencil_alpha_state);
CTX_INIT(create_fs_state);
CTX_INIT(bind_fs_state);
CTX_INIT(delete_fs_state);
CTX_INIT(create_vs_state);
CTX_INIT(bind_vs_state);
CTX_INIT(delete_vs_state);
CTX_INIT(create_gs_state);
CTX_INIT(bind_gs_state);
CTX_INIT(delete_gs_state);
CTX_INIT(create_tcs_state);
CTX_INIT(bind_tcs_state);
CTX_INIT(delete_tcs_state);
CTX_INIT(create_tes_state);
CTX_INIT(bind_tes_state);
CTX_INIT(delete_tes_state);
CTX_INIT(create_vertex_elements_state);
CTX_INIT(bind_vertex_elements_state);
CTX_INIT(delete_vertex_elements_state);
CTX_INIT(set_blend_color);
CTX_INIT(set_stencil_ref);
CTX_INIT(set_sample_mask);
CTX_INIT(set_min_samples);
CTX_INIT(set_clip_state);
CTX_INIT(set_constant_buffer);
CTX_INIT(set_framebuffer_state);
CTX_INIT(set_polygon_stipple);
CTX_INIT(set_scissor_states);
CTX_INIT(set_viewport_states);
CTX_INIT(set_sampler_views);
CTX_INIT(set_tess_state);
CTX_INIT(set_shader_buffers);
CTX_INIT(set_shader_images);
CTX_INIT(set_vertex_buffers);
CTX_INIT(set_index_buffer);
CTX_INIT(create_stream_output_target);
CTX_INIT(stream_output_target_destroy);
CTX_INIT(set_stream_output_targets);
CTX_INIT(create_sampler_view);
CTX_INIT(sampler_view_destroy);
CTX_INIT(create_surface);
CTX_INIT(surface_destroy);
CTX_INIT(create_image_view);
CTX_INIT(image_view_destroy);
CTX_INIT(transfer_map);
CTX_INIT(transfer_flush_region);
CTX_INIT(transfer_unmap);
CTX_INIT(transfer_inline_write);
CTX_INIT(texture_barrier);
CTX_INIT(memory_barrier);
/* create_video_codec */
/* create_video_buffer */
/* create_compute_state */
/* bind_compute_state */
/* delete_compute_state */
/* set_compute_resources */
/* set_global_binding */
CTX_INIT(get_sample_position);
CTX_INIT(invalidate_resource);
CTX_INIT(get_device_reset_status);
CTX_INIT(dump_debug_state);
dd_init_draw_functions(dctx);
dctx->sample_mask = ~0;
return &dctx->base;
}

View file

@ -0,0 +1,807 @@
/**************************************************************************
*
* Copyright 2015 Advanced Micro Devices, Inc.
* Copyright 2008 VMware, Inc.
* All Rights Reserved.
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, 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 (including the next
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "dd_pipe.h"
#include "util/u_dump.h"
#include "util/u_format.h"
#include "tgsi/tgsi_scan.h"
#include "os/os_process.h"
#include <errno.h>
#include <sys/stat.h>
enum call_type
{
CALL_DRAW_VBO,
CALL_RESOURCE_COPY_REGION,
CALL_BLIT,
CALL_FLUSH_RESOURCE,
CALL_CLEAR,
CALL_CLEAR_BUFFER,
CALL_CLEAR_RENDER_TARGET,
CALL_CLEAR_DEPTH_STENCIL,
};
struct call_resource_copy_region
{
struct pipe_resource *dst;
unsigned dst_level;
unsigned dstx, dsty, dstz;
struct pipe_resource *src;
unsigned src_level;
const struct pipe_box *src_box;
};
struct call_clear
{
unsigned buffers;
const union pipe_color_union *color;
double depth;
unsigned stencil;
};
struct call_clear_buffer
{
struct pipe_resource *res;
unsigned offset;
unsigned size;
const void *clear_value;
int clear_value_size;
};
struct dd_call
{
enum call_type type;
union {
struct pipe_draw_info draw_vbo;
struct call_resource_copy_region resource_copy_region;
struct pipe_blit_info blit;
struct pipe_resource *flush_resource;
struct call_clear clear;
struct call_clear_buffer clear_buffer;
} info;
};
static FILE *
dd_get_file_stream(struct dd_context *dctx)
{
struct pipe_screen *screen = dctx->pipe->screen;
static unsigned index;
char proc_name[128], dir[256], name[512];
FILE *f;
if (!os_get_process_name(proc_name, sizeof(proc_name))) {
fprintf(stderr, "dd: can't get the process name\n");
return NULL;
}
snprintf(dir, sizeof(dir), "%s/"DD_DIR, debug_get_option("HOME", "."));
if (mkdir(dir, 0774) && errno != EEXIST) {
fprintf(stderr, "dd: can't create a directory (%i)\n", errno);
return NULL;
}
snprintf(name, sizeof(name), "%s/%s_%u_%08u", dir, proc_name, getpid(), index++);
f = fopen(name, "w");
if (!f) {
fprintf(stderr, "dd: can't open file %s\n", name);
return NULL;
}
fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen));
fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen));
fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
return f;
}
static void
dd_close_file_stream(FILE *f)
{
fclose(f);
}
static unsigned
dd_num_active_viewports(struct dd_context *dctx)
{
struct tgsi_shader_info info;
const struct tgsi_token *tokens;
if (dctx->shaders[PIPE_SHADER_GEOMETRY])
tokens = dctx->shaders[PIPE_SHADER_GEOMETRY]->state.shader.tokens;
else if (dctx->shaders[PIPE_SHADER_TESS_EVAL])
tokens = dctx->shaders[PIPE_SHADER_TESS_EVAL]->state.shader.tokens;
else if (dctx->shaders[PIPE_SHADER_VERTEX])
tokens = dctx->shaders[PIPE_SHADER_VERTEX]->state.shader.tokens;
else
return 1;
tgsi_scan_shader(tokens, &info);
return info.writes_viewport_index ? PIPE_MAX_VIEWPORTS : 1;
}
#define COLOR_RESET "\033[0m"
#define COLOR_SHADER "\033[1;32m"
#define COLOR_STATE "\033[1;33m"
#define DUMP(name, var) do { \
fprintf(f, COLOR_STATE #name ": " COLOR_RESET); \
util_dump_##name(f, var); \
fprintf(f, "\n"); \
} while(0)
#define DUMP_I(name, var, i) do { \
fprintf(f, COLOR_STATE #name " %i: " COLOR_RESET, i); \
util_dump_##name(f, var); \
fprintf(f, "\n"); \
} while(0)
#define DUMP_M(name, var, member) do { \
fprintf(f, " " #member ": "); \
util_dump_##name(f, (var)->member); \
fprintf(f, "\n"); \
} while(0)
#define DUMP_M_ADDR(name, var, member) do { \
fprintf(f, " " #member ": "); \
util_dump_##name(f, &(var)->member); \
fprintf(f, "\n"); \
} while(0)
static void
print_named_value(FILE *f, const char *name, int value)
{
fprintf(f, COLOR_STATE "%s" COLOR_RESET " = %i\n", name, value);
}
static void
print_named_xvalue(FILE *f, const char *name, int value)
{
fprintf(f, COLOR_STATE "%s" COLOR_RESET " = 0x%08x\n", name, value);
}
static void
util_dump_uint(FILE *f, unsigned i)
{
fprintf(f, "%u", i);
}
static void
util_dump_hex(FILE *f, unsigned i)
{
fprintf(f, "0x%x", i);
}
static void
util_dump_double(FILE *f, double d)
{
fprintf(f, "%f", d);
}
static void
util_dump_format(FILE *f, enum pipe_format format)
{
fprintf(f, "%s", util_format_name(format));
}
static void
util_dump_color_union(FILE *f, const union pipe_color_union *color)
{
fprintf(f, "{f = {%f, %f, %f, %f}, ui = {%u, %u, %u, %u}",
color->f[0], color->f[1], color->f[2], color->f[3],
color->ui[0], color->ui[1], color->ui[2], color->ui[3]);
}
static void
util_dump_query(FILE *f, struct dd_query *query)
{
if (query->type >= PIPE_QUERY_DRIVER_SPECIFIC)
fprintf(f, "PIPE_QUERY_DRIVER_SPECIFIC + %i",
query->type - PIPE_QUERY_DRIVER_SPECIFIC);
else
fprintf(f, "%s", util_dump_query_type(query->type, false));
}
static void
dd_dump_render_condition(struct dd_context *dctx, FILE *f)
{
if (dctx->render_cond.query) {
fprintf(f, "render condition:\n");
DUMP_M(query, &dctx->render_cond, query);
DUMP_M(uint, &dctx->render_cond, condition);
DUMP_M(uint, &dctx->render_cond, mode);
fprintf(f, "\n");
}
}
static void
dd_dump_draw_vbo(struct dd_context *dctx, struct pipe_draw_info *info, FILE *f)
{
int sh, i;
const char *shader_str[PIPE_SHADER_TYPES];
shader_str[PIPE_SHADER_VERTEX] = "VERTEX";
shader_str[PIPE_SHADER_TESS_CTRL] = "TESS_CTRL";
shader_str[PIPE_SHADER_TESS_EVAL] = "TESS_EVAL";
shader_str[PIPE_SHADER_GEOMETRY] = "GEOMETRY";
shader_str[PIPE_SHADER_FRAGMENT] = "FRAGMENT";
shader_str[PIPE_SHADER_COMPUTE] = "COMPUTE";
DUMP(draw_info, info);
if (info->indexed) {
DUMP(index_buffer, &dctx->index_buffer);
if (dctx->index_buffer.buffer)
DUMP_M(resource, &dctx->index_buffer, buffer);
}
if (info->count_from_stream_output)
DUMP_M(stream_output_target, info,
count_from_stream_output);
if (info->indirect)
DUMP_M(resource, info, indirect);
fprintf(f, "\n");
/* TODO: dump active queries */
dd_dump_render_condition(dctx, f);
for (i = 0; i < PIPE_MAX_ATTRIBS; i++)
if (dctx->vertex_buffers[i].buffer ||
dctx->vertex_buffers[i].user_buffer) {
DUMP_I(vertex_buffer, &dctx->vertex_buffers[i], i);
if (dctx->vertex_buffers[i].buffer)
DUMP_M(resource, &dctx->vertex_buffers[i], buffer);
}
if (dctx->velems) {
print_named_value(f, "num vertex elements",
dctx->velems->state.velems.count);
for (i = 0; i < dctx->velems->state.velems.count; i++) {
fprintf(f, " ");
DUMP_I(vertex_element, &dctx->velems->state.velems.velems[i], i);
}
}
print_named_value(f, "num stream output targets", dctx->num_so_targets);
for (i = 0; i < dctx->num_so_targets; i++)
if (dctx->so_targets[i]) {
DUMP_I(stream_output_target, dctx->so_targets[i], i);
DUMP_M(resource, dctx->so_targets[i], buffer);
fprintf(f, " offset = %i\n", dctx->so_offsets[i]);
}
fprintf(f, "\n");
for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
if (sh == PIPE_SHADER_COMPUTE)
continue;
if (sh == PIPE_SHADER_TESS_CTRL &&
!dctx->shaders[PIPE_SHADER_TESS_CTRL] &&
dctx->shaders[PIPE_SHADER_TESS_EVAL])
fprintf(f, "tess_state: {default_outer_level = {%f, %f, %f, %f}, "
"default_inner_level = {%f, %f}}\n",
dctx->tess_default_levels[0],
dctx->tess_default_levels[1],
dctx->tess_default_levels[2],
dctx->tess_default_levels[3],
dctx->tess_default_levels[4],
dctx->tess_default_levels[5]);
if (sh == PIPE_SHADER_FRAGMENT)
if (dctx->rs) {
unsigned num_viewports = dd_num_active_viewports(dctx);
if (dctx->rs->state.rs.clip_plane_enable)
DUMP(clip_state, &dctx->clip_state);
for (i = 0; i < num_viewports; i++)
DUMP_I(viewport_state, &dctx->viewports[i], i);
if (dctx->rs->state.rs.scissor)
for (i = 0; i < num_viewports; i++)
DUMP_I(scissor_state, &dctx->scissors[i], i);
DUMP(rasterizer_state, &dctx->rs->state.rs);
if (dctx->rs->state.rs.poly_stipple_enable)
DUMP(poly_stipple, &dctx->polygon_stipple);
fprintf(f, "\n");
}
if (!dctx->shaders[sh])
continue;
fprintf(f, COLOR_SHADER "begin shader: %s" COLOR_RESET "\n", shader_str[sh]);
DUMP(shader_state, &dctx->shaders[sh]->state.shader);
for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++)
if (dctx->constant_buffers[sh][i].buffer ||
dctx->constant_buffers[sh][i].user_buffer) {
DUMP_I(constant_buffer, &dctx->constant_buffers[sh][i], i);
if (dctx->constant_buffers[sh][i].buffer)
DUMP_M(resource, &dctx->constant_buffers[sh][i], buffer);
}
for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
if (dctx->sampler_states[sh][i])
DUMP_I(sampler_state, &dctx->sampler_states[sh][i]->state.sampler, i);
for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
if (dctx->sampler_views[sh][i]) {
DUMP_I(sampler_view, dctx->sampler_views[sh][i], i);
DUMP_M(resource, dctx->sampler_views[sh][i], texture);
}
/* TODO: print shader images */
/* TODO: print shader buffers */
fprintf(f, COLOR_SHADER "end shader: %s" COLOR_RESET "\n\n", shader_str[sh]);
}
if (dctx->dsa)
DUMP(depth_stencil_alpha_state, &dctx->dsa->state.dsa);
DUMP(stencil_ref, &dctx->stencil_ref);
if (dctx->blend)
DUMP(blend_state, &dctx->blend->state.blend);
DUMP(blend_color, &dctx->blend_color);
print_named_value(f, "min_samples", dctx->min_samples);
print_named_xvalue(f, "sample_mask", dctx->sample_mask);
fprintf(f, "\n");
DUMP(framebuffer_state, &dctx->framebuffer_state);
for (i = 0; i < dctx->framebuffer_state.nr_cbufs; i++)
if (dctx->framebuffer_state.cbufs[i]) {
fprintf(f, " " COLOR_STATE "cbufs[%i]:" COLOR_RESET "\n ", i);
DUMP(surface, dctx->framebuffer_state.cbufs[i]);
fprintf(f, " ");
DUMP(resource, dctx->framebuffer_state.cbufs[i]->texture);
}
if (dctx->framebuffer_state.zsbuf) {
fprintf(f, " " COLOR_STATE "zsbuf:" COLOR_RESET "\n ");
DUMP(surface, dctx->framebuffer_state.zsbuf);
fprintf(f, " ");
DUMP(resource, dctx->framebuffer_state.zsbuf->texture);
}
fprintf(f, "\n");
}
static void
dd_dump_resource_copy_region(struct dd_context *dctx,
struct call_resource_copy_region *info,
FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP_M(resource, info, dst);
DUMP_M(uint, info, dst_level);
DUMP_M(uint, info, dstx);
DUMP_M(uint, info, dsty);
DUMP_M(uint, info, dstz);
DUMP_M(resource, info, src);
DUMP_M(uint, info, src_level);
DUMP_M(box, info, src_box);
}
static void
dd_dump_blit(struct dd_context *dctx, struct pipe_blit_info *info, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP_M(resource, info, dst.resource);
DUMP_M(uint, info, dst.level);
DUMP_M_ADDR(box, info, dst.box);
DUMP_M(format, info, dst.format);
DUMP_M(resource, info, src.resource);
DUMP_M(uint, info, src.level);
DUMP_M_ADDR(box, info, src.box);
DUMP_M(format, info, src.format);
DUMP_M(hex, info, mask);
DUMP_M(uint, info, filter);
DUMP_M(uint, info, scissor_enable);
DUMP_M_ADDR(scissor_state, info, scissor);
DUMP_M(uint, info, render_condition_enable);
if (info->render_condition_enable)
dd_dump_render_condition(dctx, f);
}
static void
dd_dump_flush_resource(struct dd_context *dctx, struct pipe_resource *res,
FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP(resource, res);
}
static void
dd_dump_clear(struct dd_context *dctx, struct call_clear *info, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
DUMP_M(uint, info, buffers);
DUMP_M(color_union, info, color);
DUMP_M(double, info, depth);
DUMP_M(hex, info, stencil);
}
static void
dd_dump_clear_buffer(struct dd_context *dctx, struct call_clear_buffer *info,
FILE *f)
{
int i;
const char *value = (const char*)info->clear_value;
fprintf(f, "%s:\n", __func__+8);
DUMP_M(resource, info, res);
DUMP_M(uint, info, offset);
DUMP_M(uint, info, size);
DUMP_M(uint, info, clear_value_size);
fprintf(f, " clear_value:");
for (i = 0; i < info->clear_value_size; i++)
fprintf(f, " %02x", value[i]);
fprintf(f, "\n");
}
static void
dd_dump_clear_render_target(struct dd_context *dctx, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
/* TODO */
}
static void
dd_dump_clear_depth_stencil(struct dd_context *dctx, FILE *f)
{
fprintf(f, "%s:\n", __func__+8);
/* TODO */
}
static void
dd_dump_driver_state(struct dd_context *dctx, FILE *f, unsigned flags)
{
if (dctx->pipe->dump_debug_state) {
fprintf(f,"\n\n**************************************************"
"***************************\n");
fprintf(f, "Driver-specific state:\n\n");
dctx->pipe->dump_debug_state(dctx->pipe, f, flags);
}
}
static void
dd_dump_call(struct dd_context *dctx, struct dd_call *call, unsigned flags)
{
FILE *f = dd_get_file_stream(dctx);
if (!f)
return;
switch (call->type) {
case CALL_DRAW_VBO:
dd_dump_draw_vbo(dctx, &call->info.draw_vbo, f);
break;
case CALL_RESOURCE_COPY_REGION:
dd_dump_resource_copy_region(dctx, &call->info.resource_copy_region, f);
break;
case CALL_BLIT:
dd_dump_blit(dctx, &call->info.blit, f);
break;
case CALL_FLUSH_RESOURCE:
dd_dump_flush_resource(dctx, call->info.flush_resource, f);
break;
case CALL_CLEAR:
dd_dump_clear(dctx, &call->info.clear, f);
break;
case CALL_CLEAR_BUFFER:
dd_dump_clear_buffer(dctx, &call->info.clear_buffer, f);
break;
case CALL_CLEAR_RENDER_TARGET:
dd_dump_clear_render_target(dctx, f);
break;
case CALL_CLEAR_DEPTH_STENCIL:
dd_dump_clear_depth_stencil(dctx, f);
}
dd_dump_driver_state(dctx, f, flags);
dd_close_file_stream(f);
}
static void
dd_kill_process(void)
{
sync();
fprintf(stderr, "dd: Aborting the process...\n");
fflush(stdout);
fflush(stderr);
abort();
}
static bool
dd_flush_and_check_hang(struct dd_context *dctx,
struct pipe_fence_handle **flush_fence,
unsigned flush_flags)
{
struct pipe_fence_handle *fence = NULL;
struct pipe_context *pipe = dctx->pipe;
struct pipe_screen *screen = pipe->screen;
uint64_t timeout_ms = dd_screen(dctx->base.screen)->timeout_ms;
bool idle;
assert(timeout_ms > 0);
pipe->flush(pipe, &fence, flush_flags);
if (flush_fence)
screen->fence_reference(screen, flush_fence, fence);
if (!fence)
return false;
idle = screen->fence_finish(screen, fence, timeout_ms * 1000000);
screen->fence_reference(screen, &fence, NULL);
if (!idle)
fprintf(stderr, "dd: GPU hang detected!\n");
return !idle;
}
static void
dd_flush_and_handle_hang(struct dd_context *dctx,
struct pipe_fence_handle **fence, unsigned flags,
const char *cause)
{
if (dd_flush_and_check_hang(dctx, fence, flags)) {
FILE *f = dd_get_file_stream(dctx);
if (f) {
fprintf(f, "dd: %s.\n", cause);
dd_dump_driver_state(dctx, f, PIPE_DEBUG_DEVICE_IS_HUNG);
dd_close_file_stream(f);
}
/* Terminate the process to prevent future hangs. */
dd_kill_process();
}
}
static void
dd_context_flush(struct pipe_context *_pipe,
struct pipe_fence_handle **fence, unsigned flags)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
switch (dd_screen(dctx->base.screen)->mode) {
case DD_DETECT_HANGS:
dd_flush_and_handle_hang(dctx, fence, flags,
"GPU hang detected in pipe->flush()");
break;
case DD_DUMP_ALL_CALLS:
pipe->flush(pipe, fence, flags);
break;
default:
assert(0);
}
}
static void
dd_before_draw(struct dd_context *dctx)
{
if (dd_screen(dctx->base.screen)->mode == DD_DETECT_HANGS &&
!dd_screen(dctx->base.screen)->no_flush)
dd_flush_and_handle_hang(dctx, NULL, 0,
"GPU hang most likely caused by internal "
"driver commands");
}
static void
dd_after_draw(struct dd_context *dctx, struct dd_call *call)
{
switch (dd_screen(dctx->base.screen)->mode) {
case DD_DETECT_HANGS:
if (!dd_screen(dctx->base.screen)->no_flush &&
dd_flush_and_check_hang(dctx, NULL, 0)) {
dd_dump_call(dctx, call, PIPE_DEBUG_DEVICE_IS_HUNG);
/* Terminate the process to prevent future hangs. */
dd_kill_process();
}
break;
case DD_DUMP_ALL_CALLS:
dd_dump_call(dctx, call, 0);
break;
default:
assert(0);
}
}
static void
dd_context_draw_vbo(struct pipe_context *_pipe,
const struct pipe_draw_info *info)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_call call;
call.type = CALL_DRAW_VBO;
call.info.draw_vbo = *info;
dd_before_draw(dctx);
pipe->draw_vbo(pipe, info);
dd_after_draw(dctx, &call);
}
static void
dd_context_resource_copy_region(struct pipe_context *_pipe,
struct pipe_resource *dst, unsigned dst_level,
unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *src, unsigned src_level,
const struct pipe_box *src_box)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_call call;
call.type = CALL_RESOURCE_COPY_REGION;
call.info.resource_copy_region.dst = dst;
call.info.resource_copy_region.dst_level = dst_level;
call.info.resource_copy_region.dstx = dstx;
call.info.resource_copy_region.dsty = dsty;
call.info.resource_copy_region.dstz = dstz;
call.info.resource_copy_region.src = src;
call.info.resource_copy_region.src_level = src_level;
call.info.resource_copy_region.src_box = src_box;
dd_before_draw(dctx);
pipe->resource_copy_region(pipe,
dst, dst_level, dstx, dsty, dstz,
src, src_level, src_box);
dd_after_draw(dctx, &call);
}
static void
dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_call call;
call.type = CALL_BLIT;
call.info.blit = *info;
dd_before_draw(dctx);
pipe->blit(pipe, info);
dd_after_draw(dctx, &call);
}
static void
dd_context_flush_resource(struct pipe_context *_pipe,
struct pipe_resource *resource)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_call call;
call.type = CALL_FLUSH_RESOURCE;
call.info.flush_resource = resource;
dd_before_draw(dctx);
pipe->flush_resource(pipe, resource);
dd_after_draw(dctx, &call);
}
static void
dd_context_clear(struct pipe_context *_pipe, unsigned buffers,
const union pipe_color_union *color, double depth,
unsigned stencil)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_call call;
call.type = CALL_CLEAR;
call.info.clear.buffers = buffers;
call.info.clear.color = color;
call.info.clear.depth = depth;
call.info.clear.stencil = stencil;
dd_before_draw(dctx);
pipe->clear(pipe, buffers, color, depth, stencil);
dd_after_draw(dctx, &call);
}
static void
dd_context_clear_render_target(struct pipe_context *_pipe,
struct pipe_surface *dst,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_call call;
call.type = CALL_CLEAR_RENDER_TARGET;
dd_before_draw(dctx);
pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height);
dd_after_draw(dctx, &call);
}
static void
dd_context_clear_depth_stencil(struct pipe_context *_pipe,
struct pipe_surface *dst, unsigned clear_flags,
double depth, unsigned stencil, unsigned dstx,
unsigned dsty, unsigned width, unsigned height)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_call call;
call.type = CALL_CLEAR_DEPTH_STENCIL;
dd_before_draw(dctx);
pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil,
dstx, dsty, width, height);
dd_after_draw(dctx, &call);
}
static void
dd_context_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res,
unsigned offset, unsigned size,
const void *clear_value, int clear_value_size)
{
struct dd_context *dctx = dd_context(_pipe);
struct pipe_context *pipe = dctx->pipe;
struct dd_call call;
call.type = CALL_CLEAR_BUFFER;
call.info.clear_buffer.res = res;
call.info.clear_buffer.offset = offset;
call.info.clear_buffer.size = size;
call.info.clear_buffer.clear_value = clear_value;
call.info.clear_buffer.clear_value_size = clear_value_size;
dd_before_draw(dctx);
pipe->clear_buffer(pipe, res, offset, size, clear_value, clear_value_size);
dd_after_draw(dctx, &call);
}
void
dd_init_draw_functions(struct dd_context *dctx)
{
CTX_INIT(flush);
CTX_INIT(draw_vbo);
CTX_INIT(resource_copy_region);
CTX_INIT(blit);
CTX_INIT(clear);
CTX_INIT(clear_render_target);
CTX_INIT(clear_depth_stencil);
CTX_INIT(clear_buffer);
CTX_INIT(flush_resource);
/* launch_grid */
}

View file

@ -0,0 +1,141 @@
/**************************************************************************
*
* Copyright 2015 Advanced Micro Devices, Inc.
* Copyright 2008 VMware, Inc.
* All Rights Reserved.
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, 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 (including the next
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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.
*
**************************************************************************/
#ifndef DD_H_
#define DD_H_
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "pipe/p_screen.h"
/* name of the directory in home */
#define DD_DIR "ddebug_dumps"
enum dd_mode {
DD_DETECT_HANGS,
DD_DUMP_ALL_CALLS
};
struct dd_screen
{
struct pipe_screen base;
struct pipe_screen *screen;
unsigned timeout_ms;
enum dd_mode mode;
bool no_flush;
};
struct dd_query
{
unsigned type;
struct pipe_query *query;
};
struct dd_state
{
void *cso;
union {
struct pipe_blend_state blend;
struct pipe_depth_stencil_alpha_state dsa;
struct pipe_rasterizer_state rs;
struct pipe_sampler_state sampler;
struct {
struct pipe_vertex_element velems[PIPE_MAX_ATTRIBS];
unsigned count;
} velems;
struct pipe_shader_state shader;
} state;
};
struct dd_context
{
struct pipe_context base;
struct pipe_context *pipe;
struct {
struct dd_query *query;
bool condition;
unsigned mode;
} render_cond;
struct pipe_index_buffer index_buffer;
struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
unsigned num_so_targets;
struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS];
unsigned so_offsets[PIPE_MAX_SO_BUFFERS];
struct dd_state *shaders[PIPE_SHADER_TYPES];
struct pipe_constant_buffer constant_buffers[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
struct dd_state *sampler_states[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
struct pipe_image_view *shader_images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
struct pipe_shader_buffer shader_buffers[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
struct dd_state *velems;
struct dd_state *rs;
struct dd_state *dsa;
struct dd_state *blend;
struct pipe_blend_color blend_color;
struct pipe_stencil_ref stencil_ref;
unsigned sample_mask;
unsigned min_samples;
struct pipe_clip_state clip_state;
struct pipe_framebuffer_state framebuffer_state;
struct pipe_poly_stipple polygon_stipple;
struct pipe_scissor_state scissors[PIPE_MAX_VIEWPORTS];
struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
float tess_default_levels[6];
};
struct pipe_context *
dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe);
void
dd_init_draw_functions(struct dd_context *dctx);
static inline struct dd_context *
dd_context(struct pipe_context *pipe)
{
return (struct dd_context *)pipe;
}
static inline struct dd_screen *
dd_screen(struct pipe_screen *screen)
{
return (struct dd_screen*)screen;
}
#define CTX_INIT(_member) \
dctx->base._member = dctx->pipe->_member ? dd_context_##_member : NULL
#endif /* DD_H_ */

View file

@ -0,0 +1,36 @@
/**************************************************************************
*
* Copyright 2015 Advanced Micro Devices, Inc.
* Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, 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 (including the next
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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.
*
**************************************************************************/
#ifndef DD_PUBLIC_H_
#define DD_PUBLIC_H_
struct pipe_screen;
struct pipe_screen *
ddebug_screen_create(struct pipe_screen *screen);
#endif /* DD_PUBLIC_H_ */

View file

@ -0,0 +1,353 @@
/**************************************************************************
*
* Copyright 2015 Advanced Micro Devices, Inc.
* Copyright 2008 VMware, Inc.
* All Rights Reserved.
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, 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 (including the next
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "dd_pipe.h"
#include "dd_public.h"
#include "util/u_memory.h"
#include <stdio.h>
static const char *
dd_screen_get_name(struct pipe_screen *_screen)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_name(screen);
}
static const char *
dd_screen_get_vendor(struct pipe_screen *_screen)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_vendor(screen);
}
static const char *
dd_screen_get_device_vendor(struct pipe_screen *_screen)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_device_vendor(screen);
}
static int
dd_screen_get_param(struct pipe_screen *_screen,
enum pipe_cap param)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_param(screen, param);
}
static float
dd_screen_get_paramf(struct pipe_screen *_screen,
enum pipe_capf param)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_paramf(screen, param);
}
static int
dd_screen_get_shader_param(struct pipe_screen *_screen, unsigned shader,
enum pipe_shader_cap param)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_shader_param(screen, shader, param);
}
static uint64_t
dd_screen_get_timestamp(struct pipe_screen *_screen)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_timestamp(screen);
}
static struct pipe_context *
dd_screen_context_create(struct pipe_screen *_screen, void *priv,
unsigned flags)
{
struct dd_screen *dscreen = dd_screen(_screen);
struct pipe_screen *screen = dscreen->screen;
flags |= PIPE_CONTEXT_DEBUG;
return dd_context_create(dscreen,
screen->context_create(screen, priv, flags));
}
static boolean
dd_screen_is_format_supported(struct pipe_screen *_screen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned tex_usage)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->is_format_supported(screen, format, target, sample_count,
tex_usage);
}
static boolean
dd_screen_can_create_resource(struct pipe_screen *_screen,
const struct pipe_resource *templat)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->can_create_resource(screen, templat);
}
static void
dd_screen_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private,
struct pipe_box *sub_box)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
screen->flush_frontbuffer(screen, resource, level, layer, context_private,
sub_box);
}
static int
dd_screen_get_driver_query_info(struct pipe_screen *_screen,
unsigned index,
struct pipe_driver_query_info *info)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_driver_query_info(screen, index, info);
}
static int
dd_screen_get_driver_query_group_info(struct pipe_screen *_screen,
unsigned index,
struct pipe_driver_query_group_info *info)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->get_driver_query_group_info(screen, index, info);
}
/********************************************************************
* resource
*/
static struct pipe_resource *
dd_screen_resource_create(struct pipe_screen *_screen,
const struct pipe_resource *templat)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
struct pipe_resource *res = screen->resource_create(screen, templat);
if (!res)
return NULL;
res->screen = _screen;
return res;
}
static struct pipe_resource *
dd_screen_resource_from_handle(struct pipe_screen *_screen,
const struct pipe_resource *templ,
struct winsys_handle *handle)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
struct pipe_resource *res =
screen->resource_from_handle(screen, templ, handle);
if (!res)
return NULL;
res->screen = _screen;
return res;
}
static struct pipe_resource *
dd_screen_resource_from_user_memory(struct pipe_screen *_screen,
const struct pipe_resource *templ,
void *user_memory)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
struct pipe_resource *res =
screen->resource_from_user_memory(screen, templ, user_memory);
if (!res)
return NULL;
res->screen = _screen;
return res;
}
static void
dd_screen_resource_destroy(struct pipe_screen *_screen,
struct pipe_resource *res)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
screen->resource_destroy(screen, res);
}
static boolean
dd_screen_resource_get_handle(struct pipe_screen *_screen,
struct pipe_resource *resource,
struct winsys_handle *handle)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->resource_get_handle(screen, resource, handle);
}
/********************************************************************
* fence
*/
static void
dd_screen_fence_reference(struct pipe_screen *_screen,
struct pipe_fence_handle **pdst,
struct pipe_fence_handle *src)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
screen->fence_reference(screen, pdst, src);
}
static boolean
dd_screen_fence_finish(struct pipe_screen *_screen,
struct pipe_fence_handle *fence,
uint64_t timeout)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
return screen->fence_finish(screen, fence, timeout);
}
/********************************************************************
* screen
*/
static void
dd_screen_destroy(struct pipe_screen *_screen)
{
struct dd_screen *dscreen = dd_screen(_screen);
struct pipe_screen *screen = dscreen->screen;
screen->destroy(screen);
FREE(dscreen);
}
struct pipe_screen *
ddebug_screen_create(struct pipe_screen *screen)
{
struct dd_screen *dscreen;
const char *option = debug_get_option("GALLIUM_DDEBUG", NULL);
bool dump_always = option && !strcmp(option, "always");
bool no_flush = option && strstr(option, "noflush");
bool help = option && !strcmp(option, "help");
unsigned timeout = 0;
if (help) {
puts("Gallium driver debugger");
puts("");
puts("Usage:");
puts("");
puts(" GALLIUM_DDEBUG=always");
puts(" Dump context and driver information after every draw call into");
puts(" $HOME/"DD_DIR"/.");
puts("");
puts(" GALLIUM_DDEBUG=[timeout in ms] noflush");
puts(" Flush and detect a device hang after every draw call based on the given");
puts(" fence timeout and dump context and driver information into");
puts(" $HOME/"DD_DIR"/ when a hang is detected.");
puts(" If 'noflush' is specified, only detect hangs in pipe->flush.");
puts("");
exit(0);
}
if (!option)
return screen;
if (!dump_always && sscanf(option, "%u", &timeout) != 1)
return screen;
dscreen = CALLOC_STRUCT(dd_screen);
if (!dscreen)
return NULL;
#define SCR_INIT(_member) \
dscreen->base._member = screen->_member ? dd_screen_##_member : NULL
dscreen->base.destroy = dd_screen_destroy;
dscreen->base.get_name = dd_screen_get_name;
dscreen->base.get_vendor = dd_screen_get_vendor;
dscreen->base.get_device_vendor = dd_screen_get_device_vendor;
dscreen->base.get_param = dd_screen_get_param;
dscreen->base.get_paramf = dd_screen_get_paramf;
dscreen->base.get_shader_param = dd_screen_get_shader_param;
/* get_video_param */
/* get_compute_param */
SCR_INIT(get_timestamp);
dscreen->base.context_create = dd_screen_context_create;
dscreen->base.is_format_supported = dd_screen_is_format_supported;
/* is_video_format_supported */
SCR_INIT(can_create_resource);
dscreen->base.resource_create = dd_screen_resource_create;
dscreen->base.resource_from_handle = dd_screen_resource_from_handle;
SCR_INIT(resource_from_user_memory);
dscreen->base.resource_get_handle = dd_screen_resource_get_handle;
dscreen->base.resource_destroy = dd_screen_resource_destroy;
SCR_INIT(flush_frontbuffer);
SCR_INIT(fence_reference);
SCR_INIT(fence_finish);
SCR_INIT(get_driver_query_info);
SCR_INIT(get_driver_query_group_info);
#undef SCR_INIT
dscreen->screen = screen;
dscreen->timeout_ms = timeout;
dscreen->mode = dump_always ? DD_DUMP_ALL_CALLS : DD_DETECT_HANGS;
dscreen->no_flush = no_flush;
switch (dscreen->mode) {
case DD_DUMP_ALL_CALLS:
fprintf(stderr, "Gallium debugger active. Logging all calls.\n");
break;
case DD_DETECT_HANGS:
fprintf(stderr, "Gallium debugger active. "
"The hang detection timout is %i ms.\n", timeout);
break;
default:
assert(0);
}
return &dscreen->base;
}

View file

@ -86,7 +86,7 @@ static const uint8_t a20x_primtypes[PIPE_PRIM_MAX] = {
};
struct pipe_context *
fd2_context_create(struct pipe_screen *pscreen, void *priv)
fd2_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
{
struct fd_screen *screen = fd_screen(pscreen);
struct fd2_context *fd2_ctx = CALLOC_STRUCT(fd2_context);

View file

@ -47,6 +47,6 @@ fd2_context(struct fd_context *ctx)
}
struct pipe_context *
fd2_context_create(struct pipe_screen *pscreen, void *priv);
fd2_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags);
#endif /* FD2_CONTEXT_H_ */

View file

@ -98,7 +98,7 @@ static const uint8_t primtypes[PIPE_PRIM_MAX] = {
};
struct pipe_context *
fd3_context_create(struct pipe_screen *pscreen, void *priv)
fd3_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
{
struct fd_screen *screen = fd_screen(pscreen);
struct fd3_context *fd3_ctx = CALLOC_STRUCT(fd3_context);

View file

@ -119,6 +119,6 @@ fd3_context(struct fd_context *ctx)
}
struct pipe_context *
fd3_context_create(struct pipe_screen *pscreen, void *priv);
fd3_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags);
#endif /* FD3_CONTEXT_H_ */

View file

@ -96,7 +96,7 @@ static const uint8_t primtypes[PIPE_PRIM_MAX] = {
};
struct pipe_context *
fd4_context_create(struct pipe_screen *pscreen, void *priv)
fd4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
{
struct fd_screen *screen = fd_screen(pscreen);
struct fd4_context *fd4_ctx = CALLOC_STRUCT(fd4_context);

View file

@ -97,6 +97,6 @@ fd4_context(struct fd_context *ctx)
}
struct pipe_context *
fd4_context_create(struct pipe_screen *pscreen, void *priv);
fd4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags);
#endif /* FD4_CONTEXT_H_ */

View file

@ -155,7 +155,7 @@ static void i915_destroy(struct pipe_context *pipe)
}
struct pipe_context *
i915_create_context(struct pipe_screen *screen, void *priv)
i915_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
{
struct i915_context *i915;

View file

@ -401,7 +401,7 @@ void i915_init_string_functions( struct i915_context *i915 );
* i915_context.c
*/
struct pipe_context *i915_create_context(struct pipe_screen *screen,
void *priv);
void *priv, unsigned flags);
/***********************************************************************

View file

@ -135,7 +135,7 @@ ilo_context_destroy(struct pipe_context *pipe)
}
static struct pipe_context *
ilo_context_create(struct pipe_screen *screen, void *priv)
ilo_context_create(struct pipe_screen *screen, void *priv, unsigned flags)
{
struct ilo_screen *is = ilo_screen(screen);
struct ilo_context *ilo;

View file

@ -128,7 +128,8 @@ llvmpipe_render_condition ( struct pipe_context *pipe,
}
struct pipe_context *
llvmpipe_create_context( struct pipe_screen *screen, void *priv )
llvmpipe_create_context(struct pipe_screen *screen, void *priv,
unsigned flags)
{
struct llvmpipe_context *llvmpipe;

View file

@ -160,7 +160,8 @@ struct llvmpipe_context {
struct pipe_context *
llvmpipe_create_context( struct pipe_screen *screen, void *priv );
llvmpipe_create_context(struct pipe_screen *screen, void *priv,
unsigned flags);
struct pipe_resource *
llvmpipe_user_buffer_create(struct pipe_screen *screen,

View file

@ -260,7 +260,8 @@ static void noop_destroy_context(struct pipe_context *ctx)
FREE(ctx);
}
static struct pipe_context *noop_create_context(struct pipe_screen *screen, void *priv)
static struct pipe_context *noop_create_context(struct pipe_screen *screen,
void *priv, unsigned flags)
{
struct pipe_context *ctx = CALLOC_STRUCT(pipe_context);

View file

@ -190,7 +190,7 @@ nv30_context_destroy(struct pipe_context *pipe)
} while(0)
struct pipe_context *
nv30_context_create(struct pipe_screen *pscreen, void *priv)
nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
{
struct nv30_screen *screen = nv30_screen(pscreen);
struct nv30_context *nv30 = CALLOC_STRUCT(nv30_context);

View file

@ -132,7 +132,7 @@ nv30_context(struct pipe_context *pipe)
}
struct pipe_context *
nv30_context_create(struct pipe_screen *pscreen, void *priv);
nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags);
void
nv30_vbo_init(struct pipe_context *pipe);

View file

@ -240,7 +240,7 @@ nv50_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
float *);
struct pipe_context *
nv50_create(struct pipe_screen *pscreen, void *priv)
nv50_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
{
struct nv50_screen *screen = nv50_screen(pscreen);
struct nv50_context *nv50;

View file

@ -186,7 +186,7 @@ nv50_context_shader_stage(unsigned pipe)
}
/* nv50_context.c */
struct pipe_context *nv50_create(struct pipe_screen *, void *);
struct pipe_context *nv50_create(struct pipe_screen *, void *, unsigned flags);
void nv50_bufctx_fence(struct nouveau_bufctx *, bool on_flush);

View file

@ -262,7 +262,7 @@ nvc0_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
float *);
struct pipe_context *
nvc0_create(struct pipe_screen *pscreen, void *priv)
nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
{
struct nvc0_screen *screen = nvc0_screen(pscreen);
struct nvc0_context *nvc0;

View file

@ -214,7 +214,7 @@ nvc0_shader_stage(unsigned pipe)
/* nvc0_context.c */
struct pipe_context *nvc0_create(struct pipe_screen *, void *);
struct pipe_context *nvc0_create(struct pipe_screen *, void *, unsigned flags);
void nvc0_bufctx_fence(struct nvc0_context *, struct nouveau_bufctx *,
bool on_flush);
void nvc0_default_kick_notify(struct nouveau_pushbuf *);

View file

@ -363,7 +363,7 @@ static void r300_init_states(struct pipe_context *pipe)
}
struct pipe_context* r300_create_context(struct pipe_screen* screen,
void *priv)
void *priv, unsigned flags)
{
struct r300_context* r300 = CALLOC_STRUCT(r300_context);
struct r300_screen* r300screen = r300_screen(screen);

View file

@ -705,7 +705,7 @@ r300_get_nonnull_cb(struct pipe_framebuffer_state *fb, unsigned i)
}
struct pipe_context* r300_create_context(struct pipe_screen* screen,
void *priv);
void *priv, unsigned flags);
/* Context initialization. */
struct draw_stage* r300_draw_stage(struct r300_context* r300);

View file

@ -108,7 +108,8 @@ static void r600_destroy_context(struct pipe_context *context)
FREE(rctx);
}
static struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv)
static struct pipe_context *r600_create_context(struct pipe_screen *screen,
void *priv, unsigned flags)
{
struct r600_context *rctx = CALLOC_STRUCT(r600_context);
struct r600_screen* rscreen = (struct r600_screen *)screen;
@ -624,7 +625,7 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
rscreen->global_pool = compute_memory_pool_new(rscreen);
/* Create the auxiliary context. This must be done last. */
rscreen->b.aux_context = rscreen->b.b.context_create(&rscreen->b.b, NULL);
rscreen->b.aux_context = rscreen->b.b.context_create(&rscreen->b.b, NULL, 0);
#if 0 /* This is for testing whether aux_context and buffer clearing work correctly. */
struct pipe_resource templ = {};

View file

@ -3428,7 +3428,6 @@
#define S_0085F0_SO3_DEST_BASE_ENA(x) (((x) & 0x1) << 5)
#define G_0085F0_SO3_DEST_BASE_ENA(x) (((x) >> 5) & 0x1)
#define C_0085F0_SO3_DEST_BASE_ENA 0xFFFFFFDF
#define S_0085F0_CB0_DEST_BASE_ENA_SHIFT 6
#define S_0085F0_CB0_DEST_BASE_ENA(x) (((x) & 0x1) << 6)
#define G_0085F0_CB0_DEST_BASE_ENA(x) (((x) >> 6) & 0x1)
#define C_0085F0_CB0_DEST_BASE_ENA 0xFFFFFFBF

View file

@ -680,7 +680,7 @@ struct radeon_winsys {
uint64_t (*query_value)(struct radeon_winsys *ws,
enum radeon_value_id value);
void (*read_registers)(struct radeon_winsys *ws, unsigned reg_offset,
bool (*read_registers)(struct radeon_winsys *ws, unsigned reg_offset,
unsigned num_registers, uint32_t *out);
};

View file

@ -0,0 +1 @@
sid_tables.h

View file

@ -31,3 +31,12 @@ AM_CFLAGS = \
noinst_LTLIBRARIES = libradeonsi.la
libradeonsi_la_SOURCES = $(C_SOURCES)
sid_tables.h: $(srcdir)/sid_tables.py $(srcdir)/sid.h
$(AM_V_GEN) $(PYTHON2) $(srcdir)/sid_tables.py $(srcdir)/sid.h > $@
EXTRA_DIST = \
sid_tables.py
BUILT_SOURCES =\
sid_tables.h

View file

@ -4,8 +4,10 @@ C_SOURCES := \
si_commands.c \
si_compute.c \
si_cp_dma.c \
si_debug.c \
si_descriptors.c \
sid.h \
sid_tables.h \
si_dma.c \
si_hw_context.c \
si_pipe.c \

View file

@ -47,10 +47,11 @@ static void si_emit_cp_dma_copy_buffer(struct si_context *sctx,
unsigned size, unsigned flags)
{
struct radeon_winsys_cs *cs = sctx->b.rings.gfx.cs;
uint32_t sync_flag = flags & R600_CP_DMA_SYNC ? PKT3_CP_DMA_CP_SYNC : 0;
uint32_t raw_wait = flags & SI_CP_DMA_RAW_WAIT ? PKT3_CP_DMA_CMD_RAW_WAIT : 0;
uint32_t sync_flag = flags & R600_CP_DMA_SYNC ? S_411_CP_SYNC(1) : 0;
uint32_t raw_wait = flags & SI_CP_DMA_RAW_WAIT ? S_414_RAW_WAIT(1) : 0;
uint32_t sel = flags & CIK_CP_DMA_USE_L2 ?
PKT3_CP_DMA_SRC_SEL(3) | PKT3_CP_DMA_DST_SEL(3) : 0;
S_411_SRC_SEL(V_411_SRC_ADDR_TC_L2) |
S_411_DSL_SEL(V_411_DST_ADDR_TC_L2) : 0;
assert(size);
assert((size & ((1<<21)-1)) == size);
@ -79,16 +80,16 @@ static void si_emit_cp_dma_clear_buffer(struct si_context *sctx,
uint32_t clear_value, unsigned flags)
{
struct radeon_winsys_cs *cs = sctx->b.rings.gfx.cs;
uint32_t sync_flag = flags & R600_CP_DMA_SYNC ? PKT3_CP_DMA_CP_SYNC : 0;
uint32_t raw_wait = flags & SI_CP_DMA_RAW_WAIT ? PKT3_CP_DMA_CMD_RAW_WAIT : 0;
uint32_t dst_sel = flags & CIK_CP_DMA_USE_L2 ? PKT3_CP_DMA_DST_SEL(3) : 0;
uint32_t sync_flag = flags & R600_CP_DMA_SYNC ? S_411_CP_SYNC(1) : 0;
uint32_t raw_wait = flags & SI_CP_DMA_RAW_WAIT ? S_414_RAW_WAIT(1) : 0;
uint32_t dst_sel = flags & CIK_CP_DMA_USE_L2 ? S_411_DSL_SEL(V_411_DST_ADDR_TC_L2) : 0;
assert(size);
assert((size & ((1<<21)-1)) == size);
if (sctx->b.chip_class >= CIK) {
radeon_emit(cs, PKT3(PKT3_DMA_DATA, 5, 0));
radeon_emit(cs, sync_flag | dst_sel | PKT3_CP_DMA_SRC_SEL(2)); /* CP_SYNC [31] | SRC_SEL[30:29] */
radeon_emit(cs, sync_flag | dst_sel | S_411_SRC_SEL(V_411_DATA)); /* CP_SYNC [31] | SRC_SEL[30:29] */
radeon_emit(cs, clear_value); /* DATA [31:0] */
radeon_emit(cs, 0);
radeon_emit(cs, dst_va); /* DST_ADDR_LO [31:0] */
@ -97,7 +98,7 @@ static void si_emit_cp_dma_clear_buffer(struct si_context *sctx,
} else {
radeon_emit(cs, PKT3(PKT3_CP_DMA, 4, 0));
radeon_emit(cs, clear_value); /* DATA [31:0] */
radeon_emit(cs, sync_flag | PKT3_CP_DMA_SRC_SEL(2)); /* CP_SYNC [31] | SRC_SEL[30:29] */
radeon_emit(cs, sync_flag | S_411_SRC_SEL(V_411_DATA)); /* CP_SYNC [31] | SRC_SEL[30:29] */
radeon_emit(cs, dst_va); /* DST_ADDR_LO [31:0] */
radeon_emit(cs, (dst_va >> 32) & 0xffff); /* DST_ADDR_HI [15:0] */
radeon_emit(cs, size | raw_wait); /* COMMAND [29:22] | BYTE_COUNT [20:0] */

View file

@ -0,0 +1,439 @@
/*
* Copyright 2015 Advanced Micro Devices, Inc.
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, 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 (including the next
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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.
*
* Authors:
* Marek Olšák <maraeo@gmail.com>
*/
#include "si_pipe.h"
#include "si_shader.h"
#include "sid.h"
#include "sid_tables.h"
static void si_dump_shader(struct si_shader_selector *sel, const char *name,
FILE *f)
{
if (!sel || !sel->current)
return;
fprintf(f, "%s shader disassembly:\n", name);
si_dump_shader_key(sel->type, &sel->current->key, f);
fprintf(f, "%s\n\n", sel->current->binary.disasm_string);
}
/* Parsed IBs are difficult to read without colors. Use "less -R file" to
* read them, or use "aha -b -f file" to convert them to html.
*/
#define COLOR_RESET "\033[0m"
#define COLOR_RED "\033[31m"
#define COLOR_GREEN "\033[1;32m"
#define COLOR_YELLOW "\033[1;33m"
#define COLOR_CYAN "\033[1;36m"
#define INDENT_PKT 8
static void print_spaces(FILE *f, unsigned num)
{
fprintf(f, "%*s", num, "");
}
static void print_value(FILE *file, uint32_t value, int bits)
{
/* Guess if it's int or float */
if (value <= (1 << 15))
fprintf(file, "%u\n", value);
else {
float f = uif(value);
if (fabs(f) < 100000 && f*10 == floor(f*10))
fprintf(file, "%.1ff\n", f);
else
/* Don't print more leading zeros than there are bits. */
fprintf(file, "0x%0*x\n", bits / 4, value);
}
}
static void print_named_value(FILE *file, const char *name, uint32_t value,
int bits)
{
print_spaces(file, INDENT_PKT);
fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", name);
print_value(file, value, bits);
}
static void si_dump_reg(FILE *file, unsigned offset, uint32_t value,
uint32_t field_mask)
{
int r, f;
for (r = 0; r < ARRAY_SIZE(reg_table); r++) {
const struct si_reg *reg = &reg_table[r];
if (reg->offset == offset) {
bool first_field = true;
print_spaces(file, INDENT_PKT);
fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ",
reg->name);
if (!reg->num_fields) {
print_value(file, value, 32);
return;
}
for (f = 0; f < reg->num_fields; f++) {
const struct si_field *field = &reg->fields[f];
uint32_t val = (value & field->mask) >>
(ffs(field->mask) - 1);
if (!(field->mask & field_mask))
continue;
/* Indent the field. */
if (!first_field)
print_spaces(file,
INDENT_PKT + strlen(reg->name) + 4);
/* Print the field. */
fprintf(file, "%s = ", field->name);
if (val < field->num_values && field->values[val])
fprintf(file, "%s\n", field->values[val]);
else
print_value(file, val,
util_bitcount(field->mask));
first_field = false;
}
return;
}
}
fprintf(file, COLOR_YELLOW "0x%05x" COLOR_RESET " = 0x%08x", offset, value);
}
static void si_parse_set_reg_packet(FILE *f, uint32_t *ib, unsigned count,
unsigned reg_offset)
{
unsigned reg = (ib[1] << 2) + reg_offset;
int i;
for (i = 0; i < count; i++)
si_dump_reg(f, reg + i*4, ib[2+i], ~0);
}
static uint32_t *si_parse_packet3(FILE *f, uint32_t *ib, int *num_dw,
int trace_id)
{
unsigned count = PKT_COUNT_G(ib[0]);
unsigned op = PKT3_IT_OPCODE_G(ib[0]);
const char *predicate = PKT3_PREDICATE(ib[0]) ? "(predicate)" : "";
int i;
/* Print the name first. */
for (i = 0; i < ARRAY_SIZE(packet3_table); i++)
if (packet3_table[i].op == op)
break;
if (i < ARRAY_SIZE(packet3_table))
if (op == PKT3_SET_CONTEXT_REG ||
op == PKT3_SET_CONFIG_REG ||
op == PKT3_SET_UCONFIG_REG ||
op == PKT3_SET_SH_REG)
fprintf(f, COLOR_CYAN "%s%s" COLOR_CYAN ":\n",
packet3_table[i].name, predicate);
else
fprintf(f, COLOR_GREEN "%s%s" COLOR_RESET ":\n",
packet3_table[i].name, predicate);
else
fprintf(f, COLOR_RED "PKT3_UNKNOWN 0x%x%s" COLOR_RESET ":\n",
op, predicate);
/* Print the contents. */
switch (op) {
case PKT3_SET_CONTEXT_REG:
si_parse_set_reg_packet(f, ib, count, SI_CONTEXT_REG_OFFSET);
break;
case PKT3_SET_CONFIG_REG:
si_parse_set_reg_packet(f, ib, count, SI_CONFIG_REG_OFFSET);
break;
case PKT3_SET_UCONFIG_REG:
si_parse_set_reg_packet(f, ib, count, CIK_UCONFIG_REG_OFFSET);
break;
case PKT3_SET_SH_REG:
si_parse_set_reg_packet(f, ib, count, SI_SH_REG_OFFSET);
break;
case PKT3_DRAW_PREAMBLE:
si_dump_reg(f, R_030908_VGT_PRIMITIVE_TYPE, ib[1], ~0);
si_dump_reg(f, R_028AA8_IA_MULTI_VGT_PARAM, ib[2], ~0);
si_dump_reg(f, R_028B58_VGT_LS_HS_CONFIG, ib[3], ~0);
break;
case PKT3_ACQUIRE_MEM:
si_dump_reg(f, R_0301F0_CP_COHER_CNTL, ib[1], ~0);
si_dump_reg(f, R_0301F4_CP_COHER_SIZE, ib[2], ~0);
si_dump_reg(f, R_030230_CP_COHER_SIZE_HI, ib[3], ~0);
si_dump_reg(f, R_0301F8_CP_COHER_BASE, ib[4], ~0);
si_dump_reg(f, R_0301E4_CP_COHER_BASE_HI, ib[5], ~0);
print_named_value(f, "POLL_INTERVAL", ib[6], 16);
break;
case PKT3_SURFACE_SYNC:
si_dump_reg(f, R_0085F0_CP_COHER_CNTL, ib[1], ~0);
si_dump_reg(f, R_0085F4_CP_COHER_SIZE, ib[2], ~0);
si_dump_reg(f, R_0085F8_CP_COHER_BASE, ib[3], ~0);
print_named_value(f, "POLL_INTERVAL", ib[4], 16);
break;
case PKT3_EVENT_WRITE:
si_dump_reg(f, R_028A90_VGT_EVENT_INITIATOR, ib[1],
S_028A90_EVENT_TYPE(~0));
print_named_value(f, "EVENT_INDEX", (ib[1] >> 8) & 0xf, 4);
print_named_value(f, "INV_L2", (ib[1] >> 20) & 0x1, 1);
if (count > 0) {
print_named_value(f, "ADDRESS_LO", ib[2], 32);
print_named_value(f, "ADDRESS_HI", ib[3], 16);
}
break;
case PKT3_DRAW_INDEX_AUTO:
si_dump_reg(f, R_030930_VGT_NUM_INDICES, ib[1], ~0);
si_dump_reg(f, R_0287F0_VGT_DRAW_INITIATOR, ib[2], ~0);
break;
case PKT3_DRAW_INDEX_2:
si_dump_reg(f, R_028A78_VGT_DMA_MAX_SIZE, ib[1], ~0);
si_dump_reg(f, R_0287E8_VGT_DMA_BASE, ib[2], ~0);
si_dump_reg(f, R_0287E4_VGT_DMA_BASE_HI, ib[3], ~0);
si_dump_reg(f, R_030930_VGT_NUM_INDICES, ib[4], ~0);
si_dump_reg(f, R_0287F0_VGT_DRAW_INITIATOR, ib[5], ~0);
break;
case PKT3_INDEX_TYPE:
si_dump_reg(f, R_028A7C_VGT_DMA_INDEX_TYPE, ib[1], ~0);
break;
case PKT3_NUM_INSTANCES:
si_dump_reg(f, R_030934_VGT_NUM_INSTANCES, ib[1], ~0);
break;
case PKT3_WRITE_DATA:
si_dump_reg(f, R_370_CONTROL, ib[1], ~0);
si_dump_reg(f, R_371_DST_ADDR_LO, ib[2], ~0);
si_dump_reg(f, R_372_DST_ADDR_HI, ib[3], ~0);
for (i = 2; i < count; i++) {
print_spaces(f, INDENT_PKT);
fprintf(f, "0x%08x\n", ib[2+i]);
}
break;
case PKT3_CP_DMA:
si_dump_reg(f, R_410_CP_DMA_WORD0, ib[1], ~0);
si_dump_reg(f, R_411_CP_DMA_WORD1, ib[2], ~0);
si_dump_reg(f, R_412_CP_DMA_WORD2, ib[3], ~0);
si_dump_reg(f, R_413_CP_DMA_WORD3, ib[4], ~0);
si_dump_reg(f, R_414_COMMAND, ib[5], ~0);
break;
case PKT3_DMA_DATA:
si_dump_reg(f, R_500_DMA_DATA_WORD0, ib[1], ~0);
si_dump_reg(f, R_501_SRC_ADDR_LO, ib[2], ~0);
si_dump_reg(f, R_502_SRC_ADDR_HI, ib[3], ~0);
si_dump_reg(f, R_503_DST_ADDR_LO, ib[4], ~0);
si_dump_reg(f, R_504_DST_ADDR_HI, ib[5], ~0);
si_dump_reg(f, R_414_COMMAND, ib[6], ~0);
break;
case PKT3_NOP:
if (ib[0] == 0xffff1000) {
count = -1; /* One dword NOP. */
break;
} else if (count == 0 && SI_IS_TRACE_POINT(ib[1])) {
unsigned packet_id = SI_GET_TRACE_POINT_ID(ib[1]);
print_spaces(f, INDENT_PKT);
fprintf(f, COLOR_RED "Trace point ID: %u\n", packet_id);
if (trace_id == -1)
break; /* tracing was disabled */
print_spaces(f, INDENT_PKT);
if (packet_id < trace_id)
fprintf(f, COLOR_RED
"This trace point was reached by the CP."
COLOR_RESET "\n");
else if (packet_id == trace_id)
fprintf(f, COLOR_RED
"!!!!! This is the last trace point that "
"was reached by the CP !!!!!"
COLOR_RESET "\n");
else if (packet_id+1 == trace_id)
fprintf(f, COLOR_RED
"!!!!! This is the first trace point that "
"was NOT been reached by the CP !!!!!"
COLOR_RESET "\n");
else
fprintf(f, COLOR_RED
"!!!!! This trace point was NOT reached "
"by the CP !!!!!"
COLOR_RESET "\n");
break;
}
/* fall through, print all dwords */
default:
for (i = 0; i < count+1; i++) {
print_spaces(f, INDENT_PKT);
fprintf(f, "0x%08x\n", ib[1+i]);
}
}
ib += count + 2;
*num_dw -= count + 2;
return ib;
}
/**
* Parse and print an IB into a file.
*
* \param f file
* \param ib IB
* \param num_dw size of the IB
* \param chip_class chip class
* \param trace_id the last trace ID that is known to have been reached
* and executed by the CP, typically read from a buffer
*/
static void si_parse_ib(FILE *f, uint32_t *ib, int num_dw, int trace_id)
{
fprintf(f, "------------------ IB begin ------------------\n");
while (num_dw > 0) {
unsigned type = PKT_TYPE_G(ib[0]);
switch (type) {
case 3:
ib = si_parse_packet3(f, ib, &num_dw, trace_id);
break;
case 2:
/* type-2 nop */
if (ib[0] == 0x80000000) {
fprintf(f, COLOR_GREEN "NOP (type 2)" COLOR_RESET "\n");
ib++;
break;
}
/* fall through */
default:
fprintf(f, "Unknown packet type %i\n", type);
return;
}
}
fprintf(f, "------------------- IB end -------------------\n");
if (num_dw < 0) {
printf("Packet ends after the end of IB.\n");
exit(0);
}
}
static void si_dump_mmapped_reg(struct si_context *sctx, FILE *f,
unsigned offset)
{
struct radeon_winsys *ws = sctx->b.ws;
uint32_t value;
if (ws->read_registers(ws, offset, 1, &value))
si_dump_reg(f, offset, value, ~0);
}
static void si_dump_debug_registers(struct si_context *sctx, FILE *f)
{
if (sctx->screen->b.info.drm_major == 2 &&
sctx->screen->b.info.drm_minor < 42)
return; /* no radeon support */
fprintf(f, "Memory-mapped registers:\n");
si_dump_mmapped_reg(sctx, f, R_008010_GRBM_STATUS);
/* No other registers can be read on DRM < 3.1.0. */
if (sctx->screen->b.info.drm_major < 3 ||
sctx->screen->b.info.drm_minor < 1) {
fprintf(f, "\n");
return;
}
si_dump_mmapped_reg(sctx, f, R_008008_GRBM_STATUS2);
si_dump_mmapped_reg(sctx, f, R_008014_GRBM_STATUS_SE0);
si_dump_mmapped_reg(sctx, f, R_008018_GRBM_STATUS_SE1);
si_dump_mmapped_reg(sctx, f, R_008038_GRBM_STATUS_SE2);
si_dump_mmapped_reg(sctx, f, R_00803C_GRBM_STATUS_SE3);
si_dump_mmapped_reg(sctx, f, R_00D034_SDMA0_STATUS_REG);
si_dump_mmapped_reg(sctx, f, R_00D834_SDMA1_STATUS_REG);
si_dump_mmapped_reg(sctx, f, R_000E50_SRBM_STATUS);
si_dump_mmapped_reg(sctx, f, R_000E4C_SRBM_STATUS2);
si_dump_mmapped_reg(sctx, f, R_000E54_SRBM_STATUS3);
si_dump_mmapped_reg(sctx, f, R_008680_CP_STAT);
si_dump_mmapped_reg(sctx, f, R_008674_CP_STALLED_STAT1);
si_dump_mmapped_reg(sctx, f, R_008678_CP_STALLED_STAT2);
si_dump_mmapped_reg(sctx, f, R_008670_CP_STALLED_STAT3);
si_dump_mmapped_reg(sctx, f, R_008210_CP_CPC_STATUS);
si_dump_mmapped_reg(sctx, f, R_008214_CP_CPC_BUSY_STAT);
si_dump_mmapped_reg(sctx, f, R_008218_CP_CPC_STALLED_STAT1);
si_dump_mmapped_reg(sctx, f, R_00821C_CP_CPF_STATUS);
si_dump_mmapped_reg(sctx, f, R_008220_CP_CPF_BUSY_STAT);
si_dump_mmapped_reg(sctx, f, R_008224_CP_CPF_STALLED_STAT1);
fprintf(f, "\n");
}
static void si_dump_debug_state(struct pipe_context *ctx, FILE *f,
unsigned flags)
{
struct si_context *sctx = (struct si_context*)ctx;
if (flags & PIPE_DEBUG_DEVICE_IS_HUNG)
si_dump_debug_registers(sctx, f);
si_dump_shader(sctx->vs_shader, "Vertex", f);
si_dump_shader(sctx->tcs_shader, "Tessellation control", f);
si_dump_shader(sctx->tes_shader, "Tessellation evaluation", f);
si_dump_shader(sctx->gs_shader, "Geometry", f);
si_dump_shader(sctx->ps_shader, "Fragment", f);
if (sctx->last_ib) {
int last_trace_id = -1;
if (sctx->last_trace_buf) {
/* We are expecting that the ddebug pipe has already
* waited for the context, so this buffer should be idle.
* If the GPU is hung, there is no point in waiting for it.
*/
uint32_t *map =
sctx->b.ws->buffer_map(sctx->last_trace_buf->cs_buf,
NULL,
PIPE_TRANSFER_UNSYNCHRONIZED |
PIPE_TRANSFER_READ);
if (map)
last_trace_id = *map;
}
si_parse_ib(f, sctx->last_ib, sctx->last_ib_dw_size,
last_trace_id);
free(sctx->last_ib); /* dump only once */
sctx->last_ib = NULL;
r600_resource_reference(&sctx->last_trace_buf, NULL);
}
fprintf(f, "Done.\n");
}
void si_init_debug_functions(struct si_context *sctx)
{
sctx->b.b.dump_debug_state = si_dump_debug_state;
}

View file

@ -88,11 +88,8 @@ void si_need_cs_space(struct si_context *ctx, unsigned num_dw,
/* Count in framebuffer cache flushes at the end of CS. */
num_dw += ctx->atoms.s.cache_flush->num_dw;
#if SI_TRACE_CS
if (ctx->screen->b.trace_bo) {
num_dw += SI_TRACE_CS_DWORDS;
}
#endif
if (ctx->screen->b.trace_bo)
num_dw += SI_TRACE_CS_DWORDS * 2;
/* Flush if there's not enough space. */
if (num_dw > cs->max_dw) {
@ -130,6 +127,19 @@ void si_context_gfx_flush(void *context, unsigned flags,
/* force to keep tiling flags */
flags |= RADEON_FLUSH_KEEP_TILING_FLAGS;
if (ctx->trace_buf)
si_trace_emit(ctx);
/* Save the IB for debug contexts. */
if (ctx->is_debug) {
free(ctx->last_ib);
ctx->last_ib_dw_size = cs->cdw;
ctx->last_ib = malloc(cs->cdw * 4);
memcpy(ctx->last_ib, cs->buf, cs->cdw * 4);
r600_resource_reference(&ctx->last_trace_buf, ctx->trace_buf);
r600_resource_reference(&ctx->trace_buf, NULL);
}
/* Flush the CS. */
ws->cs_flush(cs, flags, &ctx->last_gfx_fence,
ctx->screen->b.cs_count++);
@ -138,31 +148,28 @@ void si_context_gfx_flush(void *context, unsigned flags,
if (fence)
ws->fence_reference(fence, ctx->last_gfx_fence);
#if SI_TRACE_CS
if (ctx->screen->b.trace_bo) {
struct si_screen *sscreen = ctx->screen;
unsigned i;
for (i = 0; i < 10; i++) {
usleep(5);
if (!ws->buffer_is_busy(sscreen->b.trace_bo->buf, RADEON_USAGE_READWRITE)) {
break;
}
}
if (i == 10) {
fprintf(stderr, "timeout on cs lockup likely happen at cs %d dw %d\n",
sscreen->b.trace_ptr[1], sscreen->b.trace_ptr[0]);
} else {
fprintf(stderr, "cs %d executed in %dms\n", sscreen->b.trace_ptr[1], i * 5);
}
}
#endif
si_begin_new_cs(ctx);
}
void si_begin_new_cs(struct si_context *ctx)
{
if (ctx->is_debug) {
uint32_t zero = 0;
/* Create a buffer used for writing trace IDs and initialize it to 0. */
assert(!ctx->trace_buf);
ctx->trace_buf = (struct r600_resource*)
pipe_buffer_create(ctx->b.b.screen, PIPE_BIND_CUSTOM,
PIPE_USAGE_STAGING, 4);
if (ctx->trace_buf)
pipe_buffer_write_nooverlap(&ctx->b.b, &ctx->trace_buf->b.b,
0, sizeof(zero), &zero);
ctx->trace_id = 0;
}
if (ctx->trace_buf)
si_trace_emit(ctx);
/* Flush read caches at the beginning of CS. */
ctx->b.flags |= SI_CONTEXT_FLUSH_AND_INV_FRAMEBUFFER |
SI_CONTEXT_INV_TC_L1 |

View file

@ -81,6 +81,9 @@ static void si_destroy_context(struct pipe_context *context)
LLVMDisposeTargetMachine(sctx->tm);
#endif
r600_resource_reference(&sctx->trace_buf, NULL);
r600_resource_reference(&sctx->last_trace_buf, NULL);
free(sctx->last_ib);
FREE(sctx);
}
@ -92,7 +95,8 @@ si_amdgpu_get_reset_status(struct pipe_context *ctx)
return sctx->b.ws->ctx_query_reset_status(sctx->b.ctx);
}
static struct pipe_context *si_create_context(struct pipe_screen *screen, void *priv)
static struct pipe_context *si_create_context(struct pipe_screen *screen,
void *priv, unsigned flags)
{
struct si_context *sctx = CALLOC_STRUCT(si_context);
struct si_screen* sscreen = (struct si_screen *)screen;
@ -111,6 +115,7 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, void *
sctx->b.b.destroy = si_destroy_context;
sctx->b.set_atom_dirty = (void *)si_set_atom_dirty;
sctx->screen = sscreen; /* Easy accessing of screen/winsys. */
sctx->is_debug = (flags & PIPE_CONTEXT_DEBUG) != 0;
if (!r600_common_context_init(&sctx->b, &sscreen->b))
goto fail;
@ -121,6 +126,7 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, void *
si_init_blit_functions(sctx);
si_init_compute_functions(sctx);
si_init_cp_dma_functions(sctx);
si_init_debug_functions(sctx);
if (sscreen->b.info.has_uvd) {
sctx->b.b.create_video_codec = si_uvd_create_decoder;
@ -586,7 +592,7 @@ struct pipe_screen *radeonsi_screen_create(struct radeon_winsys *ws)
sscreen->b.debug_flags |= DBG_FS | DBG_VS | DBG_GS | DBG_PS | DBG_CS;
/* Create the auxiliary context. This must be done last. */
sscreen->b.aux_context = sscreen->b.b.context_create(&sscreen->b.b, NULL);
sscreen->b.aux_context = sscreen->b.b.context_create(&sscreen->b.b, NULL, 0);
return &sscreen->b.b;
}

View file

@ -43,8 +43,7 @@
#define SI_RESTART_INDEX_UNKNOWN INT_MIN
#define SI_NUM_SMOOTH_AA_SAMPLES 8
#define SI_TRACE_CS 0
#define SI_TRACE_CS_DWORDS 6
#define SI_TRACE_CS_DWORDS 7
#define SI_MAX_DRAW_CS_DWORDS \
(/*scratch:*/ 3 + /*derived prim state:*/ 3 + \
@ -82,6 +81,10 @@
SI_CONTEXT_FLUSH_AND_INV_DB | \
SI_CONTEXT_FLUSH_AND_INV_DB_META)
#define SI_ENCODE_TRACE_POINT(id) (0xcafe0000 | ((id) & 0xffff))
#define SI_IS_TRACE_POINT(x) (((x) & 0xcafe0000) == 0xcafe0000)
#define SI_GET_TRACE_POINT_ID(x) ((x) & 0xffff)
struct si_compute;
struct si_screen {
@ -243,6 +246,14 @@ struct si_context {
struct si_shader_selector *last_tcs;
int last_num_tcs_input_cp;
int last_tes_sh_base;
/* Debug state. */
bool is_debug;
uint32_t *last_ib;
unsigned last_ib_dw_size;
struct r600_resource *last_trace_buf;
struct r600_resource *trace_buf;
unsigned trace_id;
};
/* cik_sdma.c */
@ -275,6 +286,9 @@ void si_copy_buffer(struct si_context *sctx,
bool is_framebuffer);
void si_init_cp_dma_functions(struct si_context *sctx);
/* si_debug.c */
void si_init_debug_functions(struct si_context *sctx);
/* si_dma.c */
void si_dma_copy(struct pipe_context *ctx,
struct pipe_resource *dst,
@ -290,10 +304,6 @@ void si_context_gfx_flush(void *context, unsigned flags,
void si_begin_new_cs(struct si_context *ctx);
void si_need_cs_space(struct si_context *ctx, unsigned num_dw, boolean count_draw_in);
#if SI_TRACE_CS
void si_trace_emit(struct si_context *sctx);
#endif
/* si_compute.c */
void si_init_compute_functions(struct si_context *sctx);

View file

@ -135,12 +135,6 @@ unsigned si_pm4_dirty_dw(struct si_context *sctx)
continue;
count += state->ndw;
#if SI_TRACE_CS
/* for tracing each states */
if (sctx->screen->b.trace_bo) {
count += SI_TRACE_CS_DWORDS;
}
#endif
}
return count;
@ -161,12 +155,6 @@ void si_pm4_emit(struct si_context *sctx, struct si_pm4_state *state)
}
cs->cdw += state->ndw;
#if SI_TRACE_CS
if (sctx->screen->b.trace_bo) {
si_trace_emit(sctx);
}
#endif
}
void si_pm4_emit_dirty(struct si_context *sctx)

View file

@ -2418,7 +2418,7 @@ static void tex_fetch_args(
num_deriv_channels = 1;
break;
default:
assert(0); /* no other targets are valid here */
unreachable("invalid target");
}
for (param = 0; param < 2; param++)
@ -3964,48 +3964,48 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen,
return r;
}
static void si_dump_key(unsigned shader, union si_shader_key *key)
void si_dump_shader_key(unsigned shader, union si_shader_key *key, FILE *f)
{
int i;
fprintf(stderr, "SHADER KEY\n");
fprintf(f, "SHADER KEY\n");
switch (shader) {
case PIPE_SHADER_VERTEX:
fprintf(stderr, " instance_divisors = {");
fprintf(f, " instance_divisors = {");
for (i = 0; i < Elements(key->vs.instance_divisors); i++)
fprintf(stderr, !i ? "%u" : ", %u",
fprintf(f, !i ? "%u" : ", %u",
key->vs.instance_divisors[i]);
fprintf(stderr, "}\n");
fprintf(f, "}\n");
if (key->vs.as_es)
fprintf(stderr, " es_enabled_outputs = 0x%"PRIx64"\n",
fprintf(f, " es_enabled_outputs = 0x%"PRIx64"\n",
key->vs.es_enabled_outputs);
fprintf(stderr, " as_es = %u\n", key->vs.as_es);
fprintf(stderr, " as_ls = %u\n", key->vs.as_ls);
fprintf(f, " as_es = %u\n", key->vs.as_es);
fprintf(f, " as_ls = %u\n", key->vs.as_ls);
break;
case PIPE_SHADER_TESS_CTRL:
fprintf(stderr, " prim_mode = %u\n", key->tcs.prim_mode);
fprintf(f, " prim_mode = %u\n", key->tcs.prim_mode);
break;
case PIPE_SHADER_TESS_EVAL:
if (key->tes.as_es)
fprintf(stderr, " es_enabled_outputs = 0x%"PRIx64"\n",
fprintf(f, " es_enabled_outputs = 0x%"PRIx64"\n",
key->tes.es_enabled_outputs);
fprintf(stderr, " as_es = %u\n", key->tes.as_es);
fprintf(f, " as_es = %u\n", key->tes.as_es);
break;
case PIPE_SHADER_GEOMETRY:
break;
case PIPE_SHADER_FRAGMENT:
fprintf(stderr, " export_16bpc = 0x%X\n", key->ps.export_16bpc);
fprintf(stderr, " last_cbuf = %u\n", key->ps.last_cbuf);
fprintf(stderr, " color_two_side = %u\n", key->ps.color_two_side);
fprintf(stderr, " alpha_func = %u\n", key->ps.alpha_func);
fprintf(stderr, " alpha_to_one = %u\n", key->ps.alpha_to_one);
fprintf(stderr, " poly_stipple = %u\n", key->ps.poly_stipple);
fprintf(f, " export_16bpc = 0x%X\n", key->ps.export_16bpc);
fprintf(f, " last_cbuf = %u\n", key->ps.last_cbuf);
fprintf(f, " color_two_side = %u\n", key->ps.color_two_side);
fprintf(f, " alpha_func = %u\n", key->ps.alpha_func);
fprintf(f, " alpha_to_one = %u\n", key->ps.alpha_to_one);
fprintf(f, " poly_stipple = %u\n", key->ps.poly_stipple);
break;
default:
@ -4036,7 +4036,7 @@ int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
/* Dump TGSI code before doing TGSI->LLVM conversion in case the
* conversion fails. */
if (dump && !(sscreen->b.debug_flags & DBG_NO_TGSI)) {
si_dump_key(sel->type, &shader->key);
si_dump_shader_key(sel->type, &shader->key, stderr);
tgsi_dump(tokens, 0);
si_dump_streamout(&sel->so);
}

View file

@ -304,6 +304,7 @@ static inline bool si_vs_exports_prim_id(struct si_shader *shader)
/* radeonsi_shader.c */
int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
struct si_shader *shader);
void si_dump_shader_key(unsigned shader, union si_shader_key *key, FILE *f);
int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader,
LLVMTargetMachineRef tm, LLVMModuleRef mod);
void si_shader_destroy(struct pipe_context *ctx, struct si_shader *shader);

View file

@ -281,6 +281,7 @@ extern const struct r600_atom si_atom_msaa_sample_locs;
extern const struct r600_atom si_atom_msaa_config;
void si_emit_cache_flush(struct r600_common_context *sctx, struct r600_atom *atom);
void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo);
void si_trace_emit(struct si_context *sctx);
/* si_commands.c */
void si_cmd_context_control(struct si_pm4_state *pm4);

View file

@ -835,11 +835,8 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
si_emit_draw_registers(sctx, info);
si_emit_draw_packets(sctx, info, &ib);
#if SI_TRACE_CS
if (sctx->screen->b.trace_bo) {
if (sctx->trace_buf)
si_trace_emit(sctx);
}
#endif
/* Workaround for a VGT hang when streamout is enabled.
* It must be done after drawing. */
@ -874,23 +871,20 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
sctx->b.num_draw_calls++;
}
#if SI_TRACE_CS
void si_trace_emit(struct si_context *sctx)
{
struct si_screen *sscreen = sctx->screen;
struct radeon_winsys_cs *cs = sctx->b.rings.gfx.cs;
uint64_t va;
va = sscreen->b.trace_bo->gpu_address;
r600_context_bo_reloc(&sctx->b, &sctx->b.rings.gfx, sscreen->b.trace_bo,
sctx->trace_id++;
r600_context_bo_reloc(&sctx->b, &sctx->b.rings.gfx, sctx->trace_buf,
RADEON_USAGE_READWRITE, RADEON_PRIO_MIN);
radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 4, 0));
radeon_emit(cs, PKT3_WRITE_DATA_DST_SEL(PKT3_WRITE_DATA_DST_SEL_MEM_SYNC) |
PKT3_WRITE_DATA_WR_CONFIRM |
PKT3_WRITE_DATA_ENGINE_SEL(PKT3_WRITE_DATA_ENGINE_SEL_ME));
radeon_emit(cs, va & 0xFFFFFFFFUL);
radeon_emit(cs, (va >> 32UL) & 0xFFFFFFFFUL);
radeon_emit(cs, cs->cdw);
radeon_emit(cs, sscreen->b.cs_count);
radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 3, 0));
radeon_emit(cs, S_370_DST_SEL(V_370_MEMORY_SYNC) |
S_370_WR_CONFIRM(1) |
S_370_ENGINE_SEL(V_370_ME));
radeon_emit(cs, sctx->trace_buf->gpu_address);
radeon_emit(cs, sctx->trace_buf->gpu_address >> 32);
radeon_emit(cs, sctx->trace_id);
radeon_emit(cs, PKT3(PKT3_NOP, 0, 0));
radeon_emit(cs, SI_ENCODE_TRACE_POINT(sctx->trace_id));
}
#endif

View file

@ -181,7 +181,7 @@ static void si_shader_es(struct si_shader *shader)
vgpr_comp_cnt = 3; /* all components are needed for TES */
num_user_sgprs = SI_TES_NUM_USER_SGPR;
} else
assert(0);
unreachable("invalid shader selector type");
num_sgprs = shader->num_sgprs;
/* One SGPR after user SGPRs is pre-loaded with es2gs_offset */
@ -338,7 +338,7 @@ static void si_shader_vs(struct si_shader *shader)
vgpr_comp_cnt = 3; /* all components are needed for TES */
num_user_sgprs = SI_TES_NUM_USER_SGPR;
} else
assert(0);
unreachable("invalid shader selector type");
num_sgprs = shader->num_sgprs;
if (num_user_sgprs > num_sgprs) {

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,179 @@
#!/usr/bin/env python
CopyRight = '''
/*
* Copyright 2015 Advanced Micro Devices, Inc.
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, 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 (including the next
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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.
*
*/
'''
import sys
import re
class Field:
def __init__(self, reg, s_name):
self.s_name = s_name
self.name = strip_prefix(s_name)
self.values = []
self.varname_values = '%s__%s__values' % (reg.r_name.lower(), self.name.lower())
class Reg:
def __init__(self, r_name):
self.r_name = r_name
self.name = strip_prefix(r_name)
self.fields = []
self.varname_fields = '%s__fields' % self.r_name.lower()
self.own_fields = True
def strip_prefix(s):
'''Strip prefix in the form ._.*_, e.g. R_001234_'''
return s[s[2:].find('_')+3:]
def parse(filename):
stream = open(filename)
regs = []
packets = []
for line in stream:
if not line.startswith('#define '):
continue
line = line[8:].strip()
if line.startswith('R_'):
reg = Reg(line.split()[0])
regs.append(reg)
elif line.startswith('S_'):
field = Field(reg, line[:line.find('(')])
reg.fields.append(field)
elif line.startswith('V_'):
field.values.append(line.split()[0])
elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1:
packets.append(line.split()[0])
# Copy fields to indexed registers which have their fields only defined
# at register index 0.
# For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 0.
match_number = re.compile('[0-9]+')
reg_dict = dict()
# Create a dict of registers with fields and '0' in their name
for reg in regs:
if len(reg.fields) and reg.name.find('0') != -1:
reg_dict[reg.name] = reg
# Assign fields
for reg in regs:
if not len(reg.fields):
reg0 = reg_dict.get(match_number.sub('0', reg.name))
if reg0 != None:
reg.fields = reg0.fields
reg.varname_fields = reg0.varname_fields
reg.own_fields = False
return (regs, packets)
def write_tables(tables):
regs = tables[0]
packets = tables[1]
print '/* This file is autogenerated by sid_tables.py from sid.h. Do not edit directly. */'
print
print CopyRight.strip()
print '''
#ifndef SID_TABLES_H
#define SID_TABLES_H
struct si_field {
const char *name;
unsigned mask;
unsigned num_values;
const char **values;
};
struct si_reg {
const char *name;
unsigned offset;
unsigned num_fields;
const struct si_field *fields;
};
struct si_packet3 {
const char *name;
unsigned op;
};
'''
print 'static const struct si_packet3 packet3_table[] = {'
for pkt in packets:
print '\t{"%s", %s},' % (pkt[5:], pkt)
print '};'
print
for reg in regs:
if len(reg.fields) and reg.own_fields:
for field in reg.fields:
if len(field.values):
print 'static const char *%s[] = {' % (field.varname_values)
for value in field.values:
print '\t[%s] = "%s",' % (value, strip_prefix(value))
print '};'
print
print 'static const struct si_field %s[] = {' % (reg.varname_fields)
for field in reg.fields:
if len(field.values):
print '\t{"%s", %s(~0u), ARRAY_SIZE(%s), %s},' % (field.name,
field.s_name, field.varname_values, field.varname_values)
else:
print '\t{"%s", %s(~0u)},' % (field.name, field.s_name)
print '};'
print
print 'static const struct si_reg reg_table[] = {'
for reg in regs:
if len(reg.fields):
print '\t{"%s", %s, ARRAY_SIZE(%s), %s},' % (reg.name, reg.r_name,
reg.varname_fields, reg.varname_fields)
else:
print '\t{"%s", %s},' % (reg.name, reg.r_name)
print '};'
print
print '#endif'
def main():
tables = []
for arg in sys.argv[1:]:
tables.extend(parse(arg))
write_tables(tables)
if __name__ == '__main__':
main()

View file

@ -129,13 +129,13 @@ rbug_screen_is_format_supported(struct pipe_screen *_screen,
static struct pipe_context *
rbug_screen_context_create(struct pipe_screen *_screen,
void *priv)
void *priv, unsigned flags)
{
struct rbug_screen *rb_screen = rbug_screen(_screen);
struct pipe_screen *screen = rb_screen->screen;
struct pipe_context *result;
result = screen->context_create(screen, priv);
result = screen->context_create(screen, priv, flags);
if (result)
return rbug_context_create(_screen, result);
return NULL;
@ -281,7 +281,7 @@ rbug_screen_create(struct pipe_screen *screen)
rb_screen->screen = screen;
rb_screen->private_context = screen->context_create(screen, NULL);
rb_screen->private_context = screen->context_create(screen, NULL, 0);
if (!rb_screen->private_context)
goto err_free;

View file

@ -186,8 +186,8 @@ softpipe_render_condition( struct pipe_context *pipe,
struct pipe_context *
softpipe_create_context( struct pipe_screen *screen,
void *priv )
softpipe_create_context(struct pipe_screen *screen,
void *priv, unsigned flags)
{
struct softpipe_screen *sp_screen = softpipe_screen(screen);
struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context);

View file

@ -211,7 +211,7 @@ softpipe_context( struct pipe_context *pipe )
struct pipe_context *
softpipe_create_context( struct pipe_screen *, void *priv );
softpipe_create_context(struct pipe_screen *, void *priv, unsigned flags);
struct pipe_resource *
softpipe_user_buffer_create(struct pipe_screen *screen,

View file

@ -81,8 +81,8 @@ static void svga_destroy( struct pipe_context *pipe )
struct pipe_context *svga_context_create( struct pipe_screen *screen,
void *priv )
struct pipe_context *svga_context_create(struct pipe_screen *screen,
void *priv, unsigned flags)
{
struct svga_screen *svgascreen = svga_screen(screen);
struct svga_context *svga = NULL;

View file

@ -478,7 +478,7 @@ void svga_surfaces_flush(struct svga_context *svga);
struct pipe_context *
svga_context_create(struct pipe_screen *screen,
void *priv);
void *priv, unsigned flags);
/***********************************************************************

View file

@ -204,7 +204,8 @@ trace_screen_is_format_supported(struct pipe_screen *_screen,
static struct pipe_context *
trace_screen_context_create(struct pipe_screen *_screen, void *priv)
trace_screen_context_create(struct pipe_screen *_screen, void *priv,
unsigned flags)
{
struct trace_screen *tr_scr = trace_screen(_screen);
struct pipe_screen *screen = tr_scr->screen;
@ -213,8 +214,10 @@ trace_screen_context_create(struct pipe_screen *_screen, void *priv)
trace_dump_call_begin("pipe_screen", "context_create");
trace_dump_arg(ptr, screen);
trace_dump_arg(ptr, priv);
trace_dump_arg(uint, flags);
result = screen->context_create(screen, priv);
result = screen->context_create(screen, priv, flags);
trace_dump_ret(ptr, result);

View file

@ -194,7 +194,7 @@ vc4_context_destroy(struct pipe_context *pctx)
}
struct pipe_context *
vc4_context_create(struct pipe_screen *pscreen, void *priv)
vc4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
{
struct vc4_screen *screen = vc4_screen(pscreen);
struct vc4_context *vc4;

View file

@ -365,7 +365,7 @@ vc4_sampler_state(struct pipe_sampler_state *psampler)
}
struct pipe_context *vc4_context_create(struct pipe_screen *pscreen,
void *priv);
void *priv, unsigned flags);
void vc4_draw_init(struct pipe_context *pctx);
void vc4_state_init(struct pipe_context *pctx);
void vc4_program_init(struct pipe_context *pctx);

View file

@ -32,6 +32,7 @@
#include "p_format.h"
#include "p_video_enums.h"
#include "p_defines.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
@ -617,6 +618,17 @@ struct pipe_context {
* Return information about unexpected device resets.
*/
enum pipe_reset_status (*get_device_reset_status)(struct pipe_context *ctx);
/**
* Dump driver-specific debug information into a stream. This is
* used by debugging tools.
*
* \param ctx pipe context
* \param stream where the output should be written to
* \param flags a mask of PIPE_DEBUG_* flags
*/
void (*dump_debug_state)(struct pipe_context *ctx, FILE *stream,
unsigned flags);
};

View file

@ -328,6 +328,26 @@ enum pipe_flush_flags
PIPE_FLUSH_END_OF_FRAME = (1 << 0)
};
/**
* Flags for pipe_context::dump_debug_state.
*/
#define PIPE_DEBUG_DEVICE_IS_HUNG (1 << 0)
/**
* Create a compute-only context. Use in pipe_screen::context_create.
* This disables draw, blit, and clear*, render_condition, and other graphics
* functions. Interop with other graphics contexts is still allowed.
* This allows scheduling jobs on a compute-only hardware command queue that
* can run in parallel with graphics without stalling it.
*/
#define PIPE_CONTEXT_COMPUTE_ONLY (1 << 0)
/**
* Gather debug information and expect that pipe_context::dump_debug_state
* will be called. Use in pipe_screen::context_create.
*/
#define PIPE_CONTEXT_DEBUG (1 << 1)
/**
* Flags for pipe_context::memory_barrier.
*/

View file

@ -125,8 +125,15 @@ struct pipe_screen {
*/
uint64_t (*get_timestamp)(struct pipe_screen *);
struct pipe_context * (*context_create)( struct pipe_screen *,
void *priv );
/**
* Create a context.
*
* \param screen pipe screen
* \param priv a pointer to set in pipe_context::priv
* \param flags a mask of PIPE_CONTEXT_* flags
*/
struct pipe_context * (*context_create)(struct pipe_screen *screen,
void *priv, unsigned flags);
/**
* Check if the given pipe_format is supported as a texture or

View file

@ -30,7 +30,7 @@ using namespace clover;
command_queue::command_queue(clover::context &ctx, clover::device &dev,
cl_command_queue_properties props) :
context(ctx), device(dev), props(props) {
pipe = dev.pipe->context_create(dev.pipe, NULL);
pipe = dev.pipe->context_create(dev.pipe, NULL, PIPE_CONTEXT_COMPUTE_ONLY);
if (!pipe)
throw error(CL_INVALID_DEVICE);
}

View file

@ -398,7 +398,7 @@ xmesa_get_context(struct st_framebuffer_iface *stfbi)
pipe = xstfb->display->pipe;
if (!pipe) {
pipe = xstfb->screen->context_create(xstfb->screen, NULL);
pipe = xstfb->screen->context_create(xstfb->screen, NULL, 0);
if (!pipe)
return NULL;
xstfb->display->pipe = pipe;

View file

@ -163,7 +163,7 @@ NineDevice9_ctor( struct NineDevice9 *This,
if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING)
DBG("Application asked mixed Software Vertex Processing. Ignoring.\n");
This->pipe = This->screen->context_create(This->screen, NULL);
This->pipe = This->screen->context_create(This->screen, NULL, 0);
if (!This->pipe) { return E_OUTOFMEMORY; } /* guess */
This->cso = cso_create_context(This->pipe);

View file

@ -162,7 +162,7 @@ static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING nam
return OMX_ErrorInsufficientResources;
screen = priv->screen->pscreen;
priv->pipe = screen->context_create(screen, priv->screen);
priv->pipe = screen->context_create(screen, priv->screen, 0);
if (!priv->pipe)
return OMX_ErrorInsufficientResources;

View file

@ -185,7 +185,7 @@ static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING nam
PIPE_VIDEO_ENTRYPOINT_ENCODE,
PIPE_VIDEO_CAP_STACKED_FRAMES);
priv->s_pipe = screen->context_create(screen, priv->screen);
priv->s_pipe = screen->context_create(screen, priv->screen, 0);
if (!priv->s_pipe)
return OMX_ErrorInsufficientResources;
@ -202,7 +202,7 @@ static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING nam
return OMX_ErrorInsufficientResources;
}
priv->t_pipe = screen->context_create(screen, priv->screen);
priv->t_pipe = screen->context_create(screen, priv->screen, 0);
if (!priv->t_pipe)
return OMX_ErrorInsufficientResources;

View file

@ -100,7 +100,8 @@ VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
if (!drv->vscreen)
goto error_screen;
drv->pipe = drv->vscreen->pscreen->context_create(drv->vscreen->pscreen, drv->vscreen);
drv->pipe = drv->vscreen->pscreen->context_create(drv->vscreen->pscreen,
drv->vscreen, 0);
if (!drv->pipe)
goto error_pipe;

View file

@ -70,7 +70,7 @@ vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device,
}
pscreen = dev->vscreen->pscreen;
dev->context = pscreen->context_create(pscreen, dev->vscreen);
dev->context = pscreen->context_create(pscreen, dev->vscreen, 0);
if (!dev->context) {
ret = VDP_STATUS_RESOURCES;
goto no_context;

View file

@ -56,7 +56,7 @@ xa_context_create(struct xa_tracker *xa)
struct xa_context *ctx = calloc(1, sizeof(*ctx));
ctx->xa = xa;
ctx->pipe = xa->screen->context_create(xa->screen, NULL);
ctx->pipe = xa->screen->context_create(xa->screen, NULL, 0);
ctx->cso = cso_create_context(ctx->pipe);
ctx->shaders = xa_shaders_create(ctx);
renderer_init_state(ctx);

View file

@ -237,7 +237,7 @@ Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,
return BadAlloc;
}
pipe = vscreen->pscreen->context_create(vscreen->pscreen, vscreen);
pipe = vscreen->pscreen->context_create(vscreen->pscreen, vscreen, 0);
if (!pipe) {
XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n");
vl_screen_destroy(vscreen);

View file

@ -11,6 +11,7 @@ AM_CFLAGS = \
AM_CPPFLAGS = \
$(DEFINES) \
-DDRI_TARGET \
-DGALLIUM_DDEBUG \
-DGALLIUM_NOOP \
-DGALLIUM_RBUG \
-DGALLIUM_TRACE
@ -45,6 +46,7 @@ gallium_dri_la_LIBADD = \
$(top_builddir)/src/gallium/state_trackers/dri/libdri.la \
$(top_builddir)/src/gallium/auxiliary/libgalliumvl.la \
$(top_builddir)/src/gallium/auxiliary/libgallium.la \
$(top_builddir)/src/gallium/drivers/ddebug/libddebug.la \
$(top_builddir)/src/gallium/drivers/noop/libnoop.la \
$(top_builddir)/src/gallium/drivers/rbug/librbug.la \
$(top_builddir)/src/gallium/drivers/trace/libtrace.la \

View file

@ -61,7 +61,7 @@ static void init( void )
exit(1);
}
ctx = screen->context_create(screen, NULL);
ctx = screen->context_create(screen, NULL, 0);
if (ctx == NULL)
exit(3);

View file

@ -398,7 +398,7 @@ static void init( void )
exit(1);
}
ctx = screen->context_create(screen, NULL);
ctx = screen->context_create(screen, NULL, 0);
if (ctx == NULL)
exit(3);

View file

@ -60,7 +60,7 @@ graw_util_create_window(struct graw_info *info,
return FALSE;
}
info->ctx = info->screen->context_create(info->screen, NULL);
info->ctx = info->screen->context_create(info->screen, NULL, 0);
if (info->ctx == NULL) {
debug_printf("graw: Failed to create context\n");
return FALSE;

View file

@ -505,7 +505,7 @@ static void init( void )
exit(1);
}
ctx = screen->context_create(screen, NULL);
ctx = screen->context_create(screen, NULL, 0);
if (ctx == NULL)
exit(3);

View file

@ -313,7 +313,7 @@ static void init( void )
exit(1);
}
ctx = screen->context_create(screen, NULL);
ctx = screen->context_create(screen, NULL, 0);
if (ctx == NULL)
exit(3);

View file

@ -188,7 +188,7 @@ static void init( void )
exit(1);
}
ctx = screen->context_create(screen, NULL);
ctx = screen->context_create(screen, NULL, 0);
if (ctx == NULL)
exit(3);

View file

@ -195,7 +195,7 @@ static void init( void )
exit(1);
}
ctx = screen->context_create(screen, NULL);
ctx = screen->context_create(screen, NULL, 0);
if (ctx == NULL)
exit(3);

View file

@ -246,7 +246,7 @@ static void init( void )
exit(1);
}
ctx = screen->context_create(screen, NULL);
ctx = screen->context_create(screen, NULL, 0);
if (ctx == NULL)
exit(3);

View file

@ -392,7 +392,7 @@ static void init( void )
exit(1);
}
ctx = screen->context_create(screen, NULL);
ctx = screen->context_create(screen, NULL, 0);
if (ctx == NULL)
exit(3);

View file

@ -77,7 +77,7 @@ static void init_ctx(struct context *ctx)
ctx->screen = pipe_loader_create_screen(ctx->dev, PIPE_SEARCH_DIR);
assert(ctx->screen);
ctx->pipe = ctx->screen->context_create(ctx->screen, NULL);
ctx->pipe = ctx->screen->context_create(ctx->screen, NULL, 0);
assert(ctx->pipe);
DUMP_COMPUTE_PARAM(p, PIPE_COMPUTE_CAP_GRID_DIMENSION);

View file

@ -100,7 +100,7 @@ static void init_prog(struct program *p)
assert(p->screen);
/* create the pipe driver context and cso context */
p->pipe = p->screen->context_create(p->screen, NULL);
p->pipe = p->screen->context_create(p->screen, NULL, 0);
p->cso = cso_create_context(p->pipe);
/* set clear color */

View file

@ -95,7 +95,7 @@ static void init_prog(struct program *p)
assert(p->screen);
/* create the pipe driver context and cso context */
p->pipe = p->screen->context_create(p->screen, NULL);
p->pipe = p->screen->context_create(p->screen, NULL, 0);
p->cso = cso_create_context(p->pipe);
/* set clear color */

View file

@ -350,14 +350,14 @@ static uint64_t amdgpu_query_value(struct radeon_winsys *rws,
return 0;
}
static void amdgpu_read_registers(struct radeon_winsys *rws,
static bool amdgpu_read_registers(struct radeon_winsys *rws,
unsigned reg_offset,
unsigned num_registers, uint32_t *out)
{
struct amdgpu_winsys *ws = (struct amdgpu_winsys*)rws;
amdgpu_read_mm_registers(ws->dev, reg_offset / 4, num_registers,
0xffffffff, 0, out);
return amdgpu_read_mm_registers(ws->dev, reg_offset / 4, num_registers,
0xffffffff, 0, out) == 0;
}
static unsigned hash_dev(void *key)

View file

@ -583,7 +583,7 @@ static uint64_t radeon_query_value(struct radeon_winsys *rws,
return 0;
}
static void radeon_read_registers(struct radeon_winsys *rws,
static bool radeon_read_registers(struct radeon_winsys *rws,
unsigned reg_offset,
unsigned num_registers, uint32_t *out)
{
@ -593,9 +593,11 @@ static void radeon_read_registers(struct radeon_winsys *rws,
for (i = 0; i < num_registers; i++) {
uint32_t reg = reg_offset + i*4;
radeon_get_drm_value(ws->fd, RADEON_INFO_READ_REG, "read-reg", &reg);
if (!radeon_get_drm_value(ws->fd, RADEON_INFO_READ_REG, NULL, &reg))
return false;
out[i] = reg;
}
return true;
}
static unsigned hash_fd(void *key)

View file

@ -299,7 +299,7 @@ wrapper_sw_winsys_wrap_pipe_screen(struct pipe_screen *screen)
wsw->base.destroy = wsw_destroy;
wsw->screen = screen;
wsw->pipe = screen->context_create(screen, NULL);
wsw->pipe = screen->context_create(screen, NULL, 0);
if (!wsw->pipe)
goto err_free;

View file

@ -1979,7 +1979,7 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format,
case MESA_FORMAT_X8R8G8B8_SRGB:
return GL_FALSE;
default:
assert(_mesa_is_format_compressed(format));
assert(_mesa_is_format_compressed(mesa_format));
if (error)
*error = GL_INVALID_ENUM;
}

View file

@ -361,48 +361,13 @@ static const int extra_ARB_shader_image_load_store_and_tessellation[] = {
EXTRA_END
};
static const int extra_ARB_draw_indirect_es31[] = {
EXT(ARB_draw_indirect),
EXTRA_API_ES31,
EXTRA_END
};
static const int extra_ARB_shader_image_load_store_es31[] = {
EXT(ARB_shader_image_load_store),
EXTRA_API_ES31,
EXTRA_END
};
static const int extra_ARB_shader_atomic_counters_es31[] = {
EXT(ARB_shader_atomic_counters),
EXTRA_API_ES31,
EXTRA_END
};
static const int extra_ARB_texture_multisample_es31[] = {
EXT(ARB_texture_multisample),
EXTRA_API_ES31,
EXTRA_END
};
static const int extra_ARB_texture_gather_es31[] = {
EXT(ARB_texture_gather),
EXTRA_API_ES31,
EXTRA_END
};
/* HACK: remove when ARB_compute_shader is actually supported */
static const int extra_ARB_compute_shader_es31[] = {
EXT(ARB_compute_shader),
EXTRA_API_ES31,
EXTRA_END
};
static const int extra_ARB_explicit_uniform_location_es31[] = {
EXT(ARB_explicit_uniform_location),
EXTRA_API_ES31,
EXTRA_END
};
EXTRA_EXT(ARB_texture_cube_map);
EXTRA_EXT(EXT_texture_array);
EXTRA_EXT(NV_fog_distance);
@ -2049,7 +2014,7 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
return TYPE_INT;
case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_compute_shader)
if (!_mesa_has_compute_shaders(ctx))
goto invalid_enum;
if (index >= 3)
goto invalid_value;
@ -2057,7 +2022,7 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
return TYPE_INT;
case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_compute_shader)
if (!_mesa_has_compute_shaders(ctx))
goto invalid_enum;
if (index >= 3)
goto invalid_value;

View file

@ -410,33 +410,33 @@ descriptor=[
# Enums in OpenGL and ES 3.1
{ "apis": ["GL", "GL_CORE", "GLES31"], "params": [
# GL_ARB_shader_image_load_store / GLES 3.1
[ "MAX_IMAGE_UNITS", "CONTEXT_INT(Const.MaxImageUnits), extra_ARB_shader_image_load_store_es31" ],
[ "MAX_VERTEX_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms), extra_ARB_shader_image_load_store_es31" ],
[ "MAX_FRAGMENT_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxImageUniforms), extra_ARB_shader_image_load_store_es31" ],
[ "MAX_COMBINED_IMAGE_UNIFORMS", "CONTEXT_INT(Const.MaxCombinedImageUniforms), extra_ARB_shader_image_load_store_es31" ],
[ "MAX_IMAGE_UNITS", "CONTEXT_INT(Const.MaxImageUnits), extra_ARB_shader_image_load_store" ],
[ "MAX_VERTEX_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms), extra_ARB_shader_image_load_store" ],
[ "MAX_FRAGMENT_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxImageUniforms), extra_ARB_shader_image_load_store" ],
[ "MAX_COMBINED_IMAGE_UNIFORMS", "CONTEXT_INT(Const.MaxCombinedImageUniforms), extra_ARB_shader_image_load_store" ],
# GL_ARB_shader_atomic_counters / GLES 3.1
[ "ATOMIC_COUNTER_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_atomic_counters_es31" ],
[ "MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", "CONTEXT_INT(Const.MaxAtomicBufferBindings), extra_ARB_shader_atomic_counters_es31" ],
[ "MAX_ATOMIC_COUNTER_BUFFER_SIZE", "CONTEXT_INT(Const.MaxAtomicBufferSize), extra_ARB_shader_atomic_counters_es31" ],
[ "MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxAtomicBuffers), extra_ARB_shader_atomic_counters_es31" ],
[ "MAX_VERTEX_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxAtomicCounters), extra_ARB_shader_atomic_counters_es31" ],
[ "MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers), extra_ARB_shader_atomic_counters_es31" ],
[ "MAX_FRAGMENT_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicCounters), extra_ARB_shader_atomic_counters_es31" ],
[ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters_es31" ],
[ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters_es31" ],
[ "ATOMIC_COUNTER_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_atomic_counters" ],
[ "MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", "CONTEXT_INT(Const.MaxAtomicBufferBindings), extra_ARB_shader_atomic_counters" ],
[ "MAX_ATOMIC_COUNTER_BUFFER_SIZE", "CONTEXT_INT(Const.MaxAtomicBufferSize), extra_ARB_shader_atomic_counters" ],
[ "MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ],
[ "MAX_VERTEX_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxAtomicCounters), extra_ARB_shader_atomic_counters" ],
[ "MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ],
[ "MAX_FRAGMENT_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicCounters), extra_ARB_shader_atomic_counters" ],
[ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ],
[ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ],
# GL_ARB_texture_multisample / GLES 3.1
[ "TEXTURE_BINDING_2D_MULTISAMPLE", "LOC_CUSTOM, TYPE_INT, TEXTURE_2D_MULTISAMPLE_INDEX, extra_ARB_texture_multisample_es31" ],
[ "MAX_COLOR_TEXTURE_SAMPLES", "CONTEXT_INT(Const.MaxColorTextureSamples), extra_ARB_texture_multisample_es31" ],
[ "MAX_DEPTH_TEXTURE_SAMPLES", "CONTEXT_INT(Const.MaxDepthTextureSamples), extra_ARB_texture_multisample_es31" ],
[ "MAX_INTEGER_SAMPLES", "CONTEXT_INT(Const.MaxIntegerSamples), extra_ARB_texture_multisample_es31" ],
[ "SAMPLE_MASK", "CONTEXT_BOOL(Multisample.SampleMask), extra_ARB_texture_multisample_es31" ],
[ "MAX_SAMPLE_MASK_WORDS", "CONST(1), extra_ARB_texture_multisample_es31" ],
[ "TEXTURE_BINDING_2D_MULTISAMPLE", "LOC_CUSTOM, TYPE_INT, TEXTURE_2D_MULTISAMPLE_INDEX, extra_ARB_texture_multisample" ],
[ "MAX_COLOR_TEXTURE_SAMPLES", "CONTEXT_INT(Const.MaxColorTextureSamples), extra_ARB_texture_multisample" ],
[ "MAX_DEPTH_TEXTURE_SAMPLES", "CONTEXT_INT(Const.MaxDepthTextureSamples), extra_ARB_texture_multisample" ],
[ "MAX_INTEGER_SAMPLES", "CONTEXT_INT(Const.MaxIntegerSamples), extra_ARB_texture_multisample" ],
[ "SAMPLE_MASK", "CONTEXT_BOOL(Multisample.SampleMask), extra_ARB_texture_multisample" ],
[ "MAX_SAMPLE_MASK_WORDS", "CONST(1), extra_ARB_texture_multisample" ],
# GL_ARB_texture_gather / GLES 3.1
[ "MIN_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MinProgramTextureGatherOffset), extra_ARB_texture_gather_es31"],
[ "MAX_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MaxProgramTextureGatherOffset), extra_ARB_texture_gather_es31"],
[ "MIN_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MinProgramTextureGatherOffset), extra_ARB_texture_gather"],
[ "MAX_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MaxProgramTextureGatherOffset), extra_ARB_texture_gather"],
# GL_ARB_compute_shader / GLES 3.1
[ "MAX_COMPUTE_WORK_GROUP_INVOCATIONS", "CONTEXT_INT(Const.MaxComputeWorkGroupInvocations), extra_ARB_compute_shader_es31" ],
@ -449,13 +449,13 @@ descriptor=[
[ "MAX_COMPUTE_IMAGE_UNIFORMS", "CONST(MAX_COMPUTE_IMAGE_UNIFORMS), extra_ARB_compute_shader_es31" ],
# GL_ARB_explicit_uniform_location / GLES 3.1
[ "MAX_UNIFORM_LOCATIONS", "CONTEXT_INT(Const.MaxUserAssignableUniformLocations), extra_ARB_explicit_uniform_location_es31" ],
[ "MAX_UNIFORM_LOCATIONS", "CONTEXT_INT(Const.MaxUserAssignableUniformLocations), extra_ARB_explicit_uniform_location" ],
]},
# Enums in OpenGL Core profile and ES 3.1
{ "apis": ["GL_CORE", "GLES3"], "params": [
{ "apis": ["GL_CORE", "GLES31"], "params": [
# GL_ARB_draw_indirect / GLES 3.1
[ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_draw_indirect_es31" ],
[ "DRAW_INDIRECT_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_draw_indirect" ],
]},
# Remaining enums are only in OpenGL

View file

@ -756,7 +756,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
return;
case GL_COMPUTE_WORK_GROUP_SIZE: {
int i;
if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_compute_shader)
if (!_mesa_has_compute_shaders(ctx))
break;
if (!shProg->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(program not "

View file

@ -1213,6 +1213,13 @@ getteximage_error_check(struct gl_context *ctx,
"%s(format=GL_STENCIL_INDEX)", caller);
return true;
}
else if (_mesa_is_stencil_format(format)
&& !_mesa_is_depthstencil_format(baseFormat)
&& !_mesa_is_stencil_format(baseFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(format mismatch)", caller);
return true;
}
else if (_mesa_is_ycbcr_format(format)
&& !_mesa_is_ycbcr_format(baseFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION,

View file

@ -1208,20 +1208,34 @@ static GLboolean
legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target,
bool dsa)
{
/* Common targets for desktop GL and GLES 3.1. */
switch (target) {
case GL_TEXTURE_1D:
case GL_PROXY_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
case GL_TEXTURE_3D:
case GL_PROXY_TEXTURE_3D:
return GL_TRUE;
case GL_TEXTURE_2D_ARRAY_EXT:
return ctx->Extensions.EXT_texture_array;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
return ctx->Extensions.ARB_texture_cube_map;
case GL_TEXTURE_2D_MULTISAMPLE:
return ctx->Extensions.ARB_texture_multisample;
}
if (!_mesa_is_desktop_gl(ctx))
return GL_FALSE;
/* Rest of the desktop GL targets. */
switch (target) {
case GL_TEXTURE_1D:
case GL_PROXY_TEXTURE_1D:
case GL_PROXY_TEXTURE_2D:
case GL_PROXY_TEXTURE_3D:
return GL_TRUE;
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
return ctx->Extensions.ARB_texture_cube_map;
case GL_TEXTURE_CUBE_MAP_ARRAY_ARB:
@ -1232,7 +1246,6 @@ legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target,
return ctx->Extensions.NV_texture_rectangle;
case GL_TEXTURE_1D_ARRAY_EXT:
case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
case GL_TEXTURE_2D_ARRAY_EXT:
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
return ctx->Extensions.EXT_texture_array;
case GL_TEXTURE_BUFFER:
@ -1254,7 +1267,6 @@ legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target,
* "target may also be TEXTURE_BUFFER, indicating the texture buffer."
*/
return ctx->API == API_OPENGL_CORE && ctx->Version >= 31;
case GL_TEXTURE_2D_MULTISAMPLE:
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:

View file

@ -1004,6 +1004,7 @@ store_texsubimage(struct gl_context *ctx,
/* compute slice info (and do some sanity checks) */
switch (target) {
case GL_TEXTURE_2D:
case GL_TEXTURE_2D_MULTISAMPLE:
case GL_TEXTURE_RECTANGLE:
case GL_TEXTURE_CUBE_MAP:
case GL_TEXTURE_EXTERNAL_OES:
@ -1025,6 +1026,7 @@ store_texsubimage(struct gl_context *ctx,
srcImageStride = _mesa_image_row_stride(packing, width, format, type);
break;
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
numSlices = depth;
sliceOffset = zoffset;
depth = 1;

View file

@ -450,13 +450,15 @@ compute_version_es2(const struct gl_extensions *extensions)
extensions->ARB_arrays_of_arrays &&
extensions->ARB_compute_shader &&
extensions->ARB_draw_indirect &&
extensions->ARB_explicit_uniform_location &&
false /*extensions->ARB_framebuffer_no_attachments*/ &&
extensions->ARB_shader_atomic_counters &&
extensions->ARB_shader_image_load_store &&
false /*extensions->ARB_shader_image_size*/ &&
false /*extensions->ARB_shader_storage_buffer_object*/ &&
extensions->ARB_shader_image_size &&
extensions->ARB_shader_storage_buffer_object &&
extensions->ARB_shading_language_packing &&
extensions->ARB_stencil_texturing &&
extensions->ARB_texture_multisample &&
extensions->ARB_gpu_shader5 &&
extensions->EXT_shader_integer_mix);

View file

@ -657,7 +657,7 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
break;
}
pipe = smapi->screen->context_create(smapi->screen, NULL);
pipe = smapi->screen->context_create(smapi->screen, NULL, 0);
if (!pipe) {
*error = ST_CONTEXT_ERROR_NO_MEMORY;
return NULL;