summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/state_tracker/st_atom_array.c172
-rw-r--r--src/mesa/state_tracker/st_extensions.c4
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp27
-rw-r--r--src/mesa/state_tracker/st_program.c5
-rw-r--r--src/mesa/state_tracker/st_program.h1
5 files changed, 164 insertions, 45 deletions
diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c
index d4fb8b862f6..56b8019a36f 100644
--- a/src/mesa/state_tracker/st_atom_array.c
+++ b/src/mesa/state_tracker/st_atom_array.c
@@ -44,7 +44,6 @@
#include "cso_cache/cso_context.h"
#include "util/u_math.h"
-
#include "main/bufferobj.h"
#include "main/glformats.h"
@@ -311,6 +310,18 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
return PIPE_FORMAT_NONE; /* silence compiler warning */
}
+static const struct gl_client_array *
+get_client_array(const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ int attr)
+{
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ /* st_program uses 0xffffffff to denote a double placeholder attribute */
+ if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER)
+ return NULL;
+ return arrays[mesaAttr];
+}
+
/**
* Examine the active arrays to determine if we have interleaved
* vertex arrays all living in one VBO, or all living in user space.
@@ -327,11 +338,16 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
GLboolean userSpaceBuffer = GL_FALSE;
for (attr = 0; attr < vpv->num_inputs; attr++) {
- const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- const struct gl_buffer_object *bufObj = array->BufferObj;
- const GLsizei stride = array->StrideB; /* in bytes */
+ const struct gl_client_array *array;
+ const struct gl_buffer_object *bufObj;
+ GLsizei stride;
+
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ stride = array->StrideB; /* in bytes */
+ bufObj = array->BufferObj;
if (attr == 0) {
/* save info about the first array */
firstStride = stride;
@@ -358,6 +374,55 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
return GL_TRUE;
}
+static void init_velement(struct pipe_vertex_element *velement,
+ int src_offset, int format,
+ int instance_divisor, int vbo_index)
+{
+ velement->src_offset = src_offset;
+ velement->src_format = format;
+ velement->instance_divisor = instance_divisor;
+ velement->vertex_buffer_index = vbo_index;
+ assert(velement->src_format);
+}
+
+static void init_velement_lowered(struct st_context *st,
+ struct pipe_vertex_element *velements,
+ int src_offset, int format,
+ int instance_divisor, int vbo_index,
+ int nr_components, GLboolean doubles,
+ GLuint *attr_idx)
+{
+ int idx = *attr_idx;
+ if (doubles) {
+ int lower_format;
+
+ if (nr_components == 1)
+ lower_format = PIPE_FORMAT_R32G32_UINT;
+ else if (nr_components >= 2)
+ lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+
+ init_velement(&velements[idx], src_offset,
+ lower_format, instance_divisor, vbo_index);
+ idx++;
+
+ if (nr_components > 2) {
+ if (nr_components == 3)
+ lower_format = PIPE_FORMAT_R32G32_UINT;
+ else if (nr_components >= 4)
+ lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+
+ init_velement(&velements[idx], src_offset + 4 * sizeof(float),
+ lower_format, instance_divisor, vbo_index);
+ idx++;
+ }
+ } else {
+ init_velement(&velements[idx], src_offset,
+ format, instance_divisor, vbo_index);
+ idx++;
+ }
+ *attr_idx = idx;
+}
+
/**
* Set up for drawing interleaved arrays that all live in one VBO
* or all live in user space.
@@ -365,13 +430,15 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
* \param velements returns vertex element info
*/
static boolean
-setup_interleaved_attribs(const struct st_vertex_program *vp,
+setup_interleaved_attribs(struct st_context *st,
+ const struct st_vertex_program *vp,
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer *vbuffer,
- struct pipe_vertex_element velements[])
+ struct pipe_vertex_element velements[],
+ unsigned *num_velements)
{
- GLuint attr;
+ GLuint attr, attr_idx;
const GLubyte *low_addr = NULL;
GLboolean usingVBO; /* all arrays in a VBO? */
struct gl_buffer_object *bufobj;
@@ -381,8 +448,10 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
* Init bufobj and stride.
*/
if (vpv->num_inputs) {
- const GLuint mesaAttr0 = vp->index_to_input[0];
- const struct gl_client_array *array = arrays[mesaAttr0];
+ const struct gl_client_array *array;
+
+ array = get_client_array(vp, arrays, 0);
+ assert(array);
/* Since we're doing interleaved arrays, we know there'll be at most
* one buffer object and the stride will be the same for all arrays.
@@ -394,7 +463,11 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
low_addr = arrays[vp->index_to_input[0]]->Ptr;
for (attr = 1; attr < vpv->num_inputs; attr++) {
- const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
+ const GLubyte *start;
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ start = array->Ptr;
low_addr = MIN2(low_addr, start);
}
}
@@ -408,25 +481,33 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
/* are the arrays in user space? */
usingVBO = _mesa_is_bufferobj(bufobj);
+ attr_idx = 0;
for (attr = 0; attr < vpv->num_inputs; attr++) {
- const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- unsigned src_offset = (unsigned) (array->Ptr - low_addr);
+ const struct gl_client_array *array;
+ unsigned src_offset;
+ unsigned src_format;
+
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ src_offset = (unsigned) (array->Ptr - low_addr);
assert(array->_ElementSize ==
_mesa_bytes_per_vertex_attrib(array->Size, array->Type));
- velements[attr].src_offset = src_offset;
- velements[attr].instance_divisor = array->InstanceDivisor;
- velements[attr].vertex_buffer_index = 0;
- velements[attr].src_format = st_pipe_vertex_format(array->Type,
- array->Size,
- array->Format,
- array->Normalized,
- array->Integer);
- assert(velements[attr].src_format);
+ src_format = st_pipe_vertex_format(array->Type,
+ array->Size,
+ array->Format,
+ array->Normalized,
+ array->Integer);
+
+ init_velement_lowered(st, velements, src_offset, src_format,
+ array->InstanceDivisor, 0,
+ array->Size, array->Doubles, &attr_idx);
}
+ *num_velements = attr_idx;
+
/*
* Return the vbuffer info and setup user-space attrib info, if needed.
*/
@@ -472,17 +553,25 @@ setup_non_interleaved_attribs(struct st_context *st,
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer vbuffer[],
- struct pipe_vertex_element velements[])
+ struct pipe_vertex_element velements[],
+ unsigned *num_velements)
{
struct gl_context *ctx = st->ctx;
- GLuint attr;
+ GLuint attr, attr_idx = 0;
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- struct gl_buffer_object *bufobj = array->BufferObj;
- GLsizei stride = array->StrideB;
+ const struct gl_client_array *array;
+ struct gl_buffer_object *bufobj;
+ GLsizei stride;
+ unsigned src_format;
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+
+ stride = array->StrideB;
+ bufobj = array->BufferObj;
assert(array->_ElementSize ==
_mesa_bytes_per_vertex_attrib(array->Size, array->Type));
@@ -524,16 +613,19 @@ setup_non_interleaved_attribs(struct st_context *st,
/* common-case setup */
vbuffer[attr].stride = stride; /* in bytes */
- velements[attr].src_offset = 0;
- velements[attr].instance_divisor = array->InstanceDivisor;
- velements[attr].vertex_buffer_index = attr;
- velements[attr].src_format = st_pipe_vertex_format(array->Type,
- array->Size,
- array->Format,
- array->Normalized,
- array->Integer);
- assert(velements[attr].src_format);
+ src_format = st_pipe_vertex_format(array->Type,
+ array->Size,
+ array->Format,
+ array->Normalized,
+ array->Integer);
+
+ init_velement_lowered(st, velements, 0, src_format,
+ array->InstanceDivisor, attr,
+ array->Size, array->Doubles, &attr_idx);
+
}
+
+ *num_velements = attr_idx;
return TRUE;
}
@@ -563,25 +655,23 @@ static void update_array(struct st_context *st)
* Setup the vbuffer[] and velements[] arrays.
*/
if (is_interleaved_arrays(vp, vpv, arrays)) {
- if (!setup_interleaved_attribs(vp, vpv, arrays, vbuffer, velements)) {
+ if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements, &num_velements)) {
st->vertex_array_out_of_memory = TRUE;
return;
}
num_vbuffers = 1;
- num_velements = vpv->num_inputs;
if (num_velements == 0)
num_vbuffers = 0;
}
else {
if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer,
- velements)) {
+ velements, &num_velements)) {
st->vertex_array_out_of_memory = TRUE;
return;
}
num_vbuffers = vpv->num_inputs;
- num_velements = vpv->num_inputs;
}
cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer);
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 82e4a30093f..b1057f3eadd 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -909,6 +909,8 @@ void st_init_extensions(struct pipe_screen *screen,
if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
PIPE_SHADER_CAP_DOUBLES) &&
screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
- PIPE_SHADER_CAP_DOUBLES))
+ PIPE_SHADER_CAP_DOUBLES)) {
extensions->ARB_gpu_shader_fp64 = GL_TRUE;
+ extensions->ARB_vertex_attrib_64bit = GL_TRUE;
+ }
}
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 08957dc2e1d..1fea8600a75 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -88,6 +88,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg(gl_register_file file, int index, int type)
@@ -101,6 +102,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg(gl_register_file file, int index, int type, int index2D)
@@ -114,6 +116,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg()
@@ -127,6 +130,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
explicit st_src_reg(st_dst_reg reg);
@@ -141,6 +145,11 @@ public:
st_src_reg *reladdr;
st_src_reg *reladdr2;
bool has_index2;
+ /*
+ * Is this the second half of a double register pair?
+ * currently used for input mapping only.
+ */
+ bool double_reg2;
};
class st_dst_reg {
@@ -197,6 +206,7 @@ st_src_reg::st_src_reg(st_dst_reg reg)
this->index2D = 0;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_dst_reg::st_dst_reg(st_src_reg reg)
@@ -677,8 +687,10 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
if (dinst->src[j].type == GLSL_TYPE_DOUBLE) {
dinst->src[j].index = initial_src_idx[j];
- if (swz > 1)
+ if (swz > 1) {
+ dinst->src[j].double_reg2 = true;
dinst->src[j].index++;
+ }
if (swz & 1)
dinst->src[j].swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W);
@@ -3705,6 +3717,7 @@ glsl_to_tgsi_visitor::copy_propagate(void)
} else {
if (first->src[0].file != copy_chan->src[0].file ||
first->src[0].index != copy_chan->src[0].index ||
+ first->src[0].double_reg2 != copy_chan->src[0].double_reg2 ||
first->src[0].index2D != copy_chan->src[0].index2D) {
good = false;
break;
@@ -3720,6 +3733,7 @@ glsl_to_tgsi_visitor::copy_propagate(void)
inst->src[r].index = first->src[0].index;
inst->src[r].index2D = first->src[0].index2D;
inst->src[r].has_index2 = first->src[0].has_index2;
+ inst->src[r].double_reg2 = first->src[0].double_reg2;
int swizzle = 0;
for (int i = 0; i < 4; i++) {
@@ -4552,6 +4566,9 @@ dst_register(struct st_translate *t,
static struct ureg_src
src_register(struct st_translate *t, const st_src_reg *reg)
{
+ int index = reg->index;
+ int double_reg2 = reg->double_reg2 ? 1 : 0;
+
switch(reg->file) {
case PROGRAM_UNDEFINED:
return ureg_imm4f(t->ureg, 0, 0, 0, 0);
@@ -4577,8 +4594,12 @@ src_register(struct st_translate *t, const st_src_reg *reg)
return t->immediates[reg->index];
case PROGRAM_INPUT:
- assert(t->inputMapping[reg->index] < ARRAY_SIZE(t->inputs));
- return t->inputs[t->inputMapping[reg->index]];
+ /* GLSL inputs are 64-bit containers, so we have to
+ * map back to the original index and add the offset after
+ * mapping. */
+ index -= double_reg2;
+ assert(t->inputMapping[index] < ARRAY_SIZE(t->inputs));
+ return t->inputs[t->inputMapping[index] + double_reg2];
case PROGRAM_OUTPUT:
assert(t->outputMapping[reg->index] < ARRAY_SIZE(t->outputs));
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index d93b3c7bcb8..a9110d3c674 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -194,6 +194,11 @@ st_prepare_vertex_program(struct gl_context *ctx,
stvp->input_to_index[attr] = stvp->num_inputs;
stvp->index_to_input[stvp->num_inputs] = attr;
stvp->num_inputs++;
+ if ((stvp->Base.Base.DoubleInputsRead & BITFIELD64_BIT(attr)) != 0) {
+ /* add placeholder for second part of a double attribute */
+ stvp->index_to_input[stvp->num_inputs] = ST_DOUBLE_ATTRIB_PLACEHOLDER;
+ stvp->num_inputs++;
+ }
}
}
/* bit of a hack, presetup potentially unused edgeflag input */
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index b2c86faecb7..a2c56062d6e 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -45,6 +45,7 @@
extern "C" {
#endif
+#define ST_DOUBLE_ATTRIB_PLACEHOLDER 0xffffffff
/** Fragment program variant key */
struct st_fp_variant_key