*/
+#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "util/u_math.h"
#include "util/u_memory.h"
uint num_texcoord_gen;
uint texcoord_gen_slot[PIPE_MAX_SHADER_OUTPUTS];
+ /* TGSI_SEMANTIC to which sprite_coord_enable applies */
+ unsigned sprite_coord_semantic;
+
int psize_slot;
};
wide->num_texcoord_gen = 0;
- /* Loop over fragment shader inputs looking for generic inputs
+ /* Loop over fragment shader inputs looking for the PCOORD input or inputs
* for which bit 'k' in sprite_coord_enable is set.
*/
for (i = 0; i < fs->info.num_inputs; i++) {
- if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
- const int generic_index = fs->info.input_semantic_index[i];
- /* Note that sprite_coord enable is a bitfield of
- * PIPE_MAX_SHADER_OUTPUTS bits.
- */
- if (generic_index < PIPE_MAX_SHADER_OUTPUTS &&
- (rast->sprite_coord_enable & (1 << generic_index))) {
- /* OK, this generic attribute needs to be replaced with a
- * texcoord (see above).
- */
- int slot = draw_alloc_extra_vertex_attrib(draw,
- TGSI_SEMANTIC_GENERIC,
- generic_index);
-
- /* add this slot to the texcoord-gen list */
- wide->texcoord_gen_slot[wide->num_texcoord_gen++] = slot;
- }
+ int slot;
+ const unsigned sn = fs->info.input_semantic_name[i];
+ const unsigned si = fs->info.input_semantic_index[i];
+
+ if (sn == wide->sprite_coord_semantic) {
+ /* Note that sprite_coord_enable is a bitfield of 32 bits. */
+ if (si >= 32 || !(rast->sprite_coord_enable & (1 << si)))
+ continue;
+ } else if (sn != TGSI_SEMANTIC_PCOORD) {
+ continue;
}
+
+ /* OK, this generic attribute needs to be replaced with a
+ * sprite coord (see above).
+ */
+ slot = draw_alloc_extra_vertex_attrib(draw, sn, si);
+
+ /* add this slot to the texcoord-gen list */
+ wide->texcoord_gen_slot[wide->num_texcoord_gen++] = slot;
}
}
if (!draw_alloc_temp_verts( &wide->stage, 4 ))
goto fail;
+ wide->sprite_coord_semantic =
+ draw->pipe->screen->get_param(draw->pipe->screen, PIPE_CAP_TGSI_TEXCOORD)
+ ?
+ TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
+
return &wide->stage;
fail:
TXT( ", " );
ENM( decl->Semantic.Name, tgsi_semantic_names );
if (decl->Semantic.Index != 0 ||
+ decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD ||
decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
CHR( '[' );
UID( decl->Semantic.Index );
"GRID_SIZE",
"BLOCK_ID",
"BLOCK_SIZE",
- "THREAD_ID"
+ "THREAD_ID",
+ "TEXCOORD",
+ "PCOORD"
};
const char *tgsi_texture_names[TGSI_TEXTURE_COUNT] =
sprite_coord_enable
^^^^^^^^^^^^^^^^^^^
+The effect of this state depends on PIPE_CAP_TGSI_TEXCOORD !
Controls automatic texture coordinate generation for rendering sprite points.
+If PIPE_CAP_TGSI_TEXCOORD is false:
When bit k in the sprite_coord_enable bitfield is set, then generic
input k to the fragment shader will get an automatically computed
texture coordinate.
+If PIPE_CAP_TGSI_TEXCOORD is true:
+The bitfield refers to inputs with TEXCOORD semantic instead of generic inputs.
+
The texture coordinate will be of the form (s, t, 0, 1) where s varies
from 0 to 1 from left to right while t varies from 0 to 1 according to
the state of 'sprite_coord_mode' (see below).
* ``PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT``: Describes the required
alignment for pipe_sampler_view::u.buf.first_element, in bytes.
If a driver does not support first/last_element, it should return 0.
+* ``PIPE_CAP_TGSI_TEXCOORD``: This CAP describes a hw limitation.
+ If true, the hardware cannot replace arbitrary shader inputs with sprite
+ coordinates and hence the inputs that are desired to be replaceable must
+ be declared with TGSI_SEMANTIC_TEXCOORD instead of TGSI_SEMANTIC_GENERIC.
+ The rasterizer's sprite_coord_enable state therefore also applies to the
+ TEXCOORD semantic.
+ Also, TGSI_SEMANTIC_PCOORD becomes available, which labels a fragment shader
+ input that will always be replaced with sprite coordinates.
.. _pipe_capf:
:ref:`rasterizer` first.
+TGSI_SEMANTIC_TEXCOORD
+""""""""""""""""""""""
+
+Only available if PIPE_CAP_TGSI_TEXCOORD is exposed !
+
+Vertex shader outputs and fragment shader inputs may be labeled with
+this semantic to make them replaceable by sprite coordinates via the
+sprite_coord_enable state in the :ref:`rasterizer`.
+The semantic index permitted with this semantic is limited to <= 7.
+
+If the driver does not support TEXCOORD, sprite coordinate replacement
+applies to inputs with the GENERIC semantic instead.
+
+The intended use case for this semantic is gl_TexCoord.
+
+
+TGSI_SEMANTIC_PCOORD
+""""""""""""""""""""
+
+Only available if PIPE_CAP_TGSI_TEXCOORD is exposed !
+
+Fragment shader inputs may be labeled with TGSI_SEMANTIC_PCOORD to indicate
+that the register contains sprite coordinates in the form (x, y, 0, 1), if
+the current primitive is a point and point sprites are enabled. Otherwise,
+the contents of the register are undefined.
+
+The intended use case for this semantic is gl_PointCoord.
+
+
TGSI_SEMANTIC_GENERIC
"""""""""""""""""""""
case PIPE_CAP_TEXTURE_MULTISAMPLE:
case PIPE_CAP_USER_CONSTANT_BUFFERS:
return 1;
+ case PIPE_CAP_TGSI_TEXCOORD:
+ return 0;
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
return 256;
case PIPE_CAP_USER_INDEX_BUFFERS:
case PIPE_CAP_USER_CONSTANT_BUFFERS:
return 1;
+ case PIPE_CAP_TGSI_TEXCOORD:
+ return 0;
/* Unsupported features (boolean caps). */
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_TGSI_TEXCOORD:
return 0;
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
+ case PIPE_CAP_TGSI_TEXCOORD:
case PIPE_CAP_USER_CONSTANT_BUFFERS:
case PIPE_CAP_USER_INDEX_BUFFERS:
return 1;
case TGSI_SEMANTIC_FACE:
hw = NV40_FP_OP_INPUT_SRC_FACING;
break;
- case TGSI_SEMANTIC_GENERIC:
- if (fdec->Semantic.Index >= 8)
- return TRUE;
-
+ case TGSI_SEMANTIC_TEXCOORD:
+ assert(fdec->Semantic.Index < 8);
fpc->fp->texcoord[fdec->Semantic.Index] = fdec->Semantic.Index;
fpc->fp->texcoords |= (1 << fdec->Semantic.Index);
fpc->fp->vp_or |= (0x00004000 << fdec->Semantic.Index);
hw = NVFX_FP_OP_INPUT_SRC_TC(fdec->Semantic.Index);
break;
+ case TGSI_SEMANTIC_GENERIC:
+ case TGSI_SEMANTIC_PCOORD:
+ /* will be assigned to remaining TC slots later */
+ return TRUE;
default:
assert(0);
return FALSE;
switch (fdec->Semantic.Name) {
case TGSI_SEMANTIC_GENERIC:
- if (fdec->Semantic.Index >= 8) {
- for (hw = 0; hw < num_texcoords; hw++) {
- if (fpc->fp->texcoord[hw] == 0xffff) {
- fpc->fp->texcoord[hw] = fdec->Semantic.Index;
- if (hw <= 7) {
- fpc->fp->texcoords |= (0x1 << hw);
- fpc->fp->vp_or |= (0x00004000 << hw);
- } else {
- fpc->fp->vp_or |= (0x00001000 << (hw - 8));
- }
- if (fdec->Semantic.Index == 9)
- fpc->fp->point_sprite_control |= (0x00000100 << hw);
- hw = NVFX_FP_OP_INPUT_SRC_TC(hw);
- fpc->r_input[idx] = nvfx_reg(NVFXSR_INPUT, hw);
- return TRUE;
+ case TGSI_SEMANTIC_PCOORD:
+ for (hw = 0; hw < num_texcoords; hw++) {
+ if (fpc->fp->texcoord[hw] == 0xffff) {
+ if (hw <= 7) {
+ fpc->fp->texcoords |= (0x1 << hw);
+ fpc->fp->vp_or |= (0x00004000 << hw);
+ } else {
+ fpc->fp->vp_or |= (0x00001000 << (hw - 8));
+ }
+ if (fdec->Semantic.Name == TGSI_SEMANTIC_PCOORD) {
+ fpc->fp->texcoord[hw] = 0xfffe;
+ fpc->fp->point_sprite_control |= (0x00000100 << hw);
+ } else {
+ fpc->fp->texcoord[hw] = fdec->Semantic.Index + 8;
}
+ hw = NVFX_FP_OP_INPUT_SRC_TC(hw);
+ fpc->r_input[idx] = nvfx_reg(NVFXSR_INPUT, hw);
+ return TRUE;
}
return FALSE;
}
{
unsigned num_texcoords = nv30->is_nv4x ? 10 : 8;
unsigned idx = fdec->Range.First;
+ unsigned semantic_index = fdec->Semantic.Index;
int hw = 0, i;
switch (fdec->Semantic.Name) {
hw = NVFX_VP(INST_DEST_PSZ);
break;
case TGSI_SEMANTIC_GENERIC:
+ /* this is really an identifier for VP/FP linkage */
+ semantic_index += 8;
+ /* fall through */
+ case TGSI_SEMANTIC_TEXCOORD:
for (i = 0; i < num_texcoords; i++) {
- if (vpc->vp->texcoord[i] == fdec->Semantic.Index) {
+ if (vpc->vp->texcoord[i] == semantic_index) {
hw = NVFX_VP(INST_DEST_TC(i));
break;
}
#endif
#define NV50_SEMANTIC_CLIPDISTANCE (TGSI_SEMANTIC_COUNT + 0)
-#define NV50_SEMANTIC_TEXCOORD (TGSI_SEMANTIC_COUNT + 1)
-#define NV50_SEMANTIC_POINTCOORD (TGSI_SEMANTIC_COUNT + 2)
#define NV50_SEMANTIC_VIEWPORTINDEX (TGSI_SEMANTIC_COUNT + 4)
#define NV50_SEMANTIC_LAYER (TGSI_SEMANTIC_COUNT + 5)
#define NV50_SEMANTIC_INVOCATIONID (TGSI_SEMANTIC_COUNT + 6)
case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_TGSI_TEXCOORD:
case PIPE_CAP_TEXTURE_MULTISAMPLE:
return 0;
default:
blit->vp.out[1].hw = 2;
blit->vp.out[1].mask = 0x7;
blit->vp.out[1].sn = TGSI_SEMANTIC_GENERIC;
- blit->vp.out[1].si = 8;
+ blit->vp.out[1].si = 0;
blit->vp.vp.attrs[0] = 0x73;
blit->vp.vp.psiz = 0x40;
blit->vp.vp.edgeflag = 0x40;
return NULL;
out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
- /* NOTE: use GENERIC[8] so we don't use the TEXCOORD slots on nvc0 */
tc = ureg_DECL_fs_input(
- ureg, TGSI_SEMANTIC_GENERIC, 8, TGSI_INTERPOLATE_LINEAR);
+ ureg, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_LINEAR);
data = ureg_DECL_temporary(ureg);
#include "nv50/codegen/nv50_ir_driver.h"
#include "nve4_compute.h"
-/* If only they told use the actual semantic instead of just GENERIC ... */
-static void
-nvc0_mesa_varying_hack(struct nv50_ir_varying *var)
-{
- unsigned c;
-
- if (var->sn != TGSI_SEMANTIC_GENERIC)
- return;
-
- if (var->si <= 7) /* gl_TexCoord */
- for (c = 0; c < 4; ++c)
- var->slot[c] = (0x300 + var->si * 0x10 + c * 0x4) / 4;
- else
- if (var->si == 9) /* gl_PointCoord */
- for (c = 0; c < 4; ++c)
- var->slot[c] = (0x2e0 + c * 0x4) / 4;
- else
- if (var->si <= 39)
- for (c = 0; c < 4; ++c) /* move down user varyings (first has index 8) */
- var->slot[c] -= 0x80 / 4;
- else {
- NOUVEAU_ERR("too many varyings / invalid location: %u !\n", var->si);
- for (c = 0; c < 4; ++c)
- var->slot[c] = (0x270 + c * 0x4) / 4; /* catch invalid indices */
- }
-}
-
static uint32_t
nvc0_shader_input_address(unsigned sn, unsigned si, unsigned ubase)
{
case NV50_SEMANTIC_CLIPDISTANCE: return 0x2c0 + si * 0x4;
case TGSI_SEMANTIC_CLIPDIST: return 0x2c0 + si * 0x10;
case TGSI_SEMANTIC_CLIPVERTEX: return 0x260;
- case NV50_SEMANTIC_POINTCOORD: return 0x2e0;
+ case TGSI_SEMANTIC_PCOORD: return 0x2e0;
case NV50_SEMANTIC_TESSCOORD: return 0x2f0;
case TGSI_SEMANTIC_INSTANCEID: return 0x2f8;
case TGSI_SEMANTIC_VERTEXID: return 0x2fc;
- case NV50_SEMANTIC_TEXCOORD: return 0x300 + si * 0x10;
+ case TGSI_SEMANTIC_TEXCOORD: return 0x300 + si * 0x10;
case TGSI_SEMANTIC_FACE: return 0x3fc;
case NV50_SEMANTIC_INVOCATIONID: return ~0;
default:
case NV50_SEMANTIC_CLIPDISTANCE: return 0x2c0 + si * 0x4;
case TGSI_SEMANTIC_CLIPDIST: return 0x2c0 + si * 0x10;
case TGSI_SEMANTIC_CLIPVERTEX: return 0x260;
- case NV50_SEMANTIC_TEXCOORD: return 0x300 + si * 0x10;
+ case TGSI_SEMANTIC_TEXCOORD: return 0x300 + si * 0x10;
case TGSI_SEMANTIC_EDGEFLAG: return ~0;
default:
assert(!"invalid TGSI output semantic");
for (c = 0; c < 4; ++c)
info->in[i].slot[c] = (offset + c * 0x4) / 4;
-
- nvc0_mesa_varying_hack(&info->in[i]);
}
return 0;
for (c = 0; c < 4; ++c)
info->out[i].slot[c] = (offset + c * 0x4) / 4;
-
- nvc0_mesa_varying_hack(&info->out[i]);
}
return 0;
case PIPE_CAP_TWO_SIDED_STENCIL:
case PIPE_CAP_DEPTH_CLIP_DISABLE:
case PIPE_CAP_POINT_SPRITE:
+ case PIPE_CAP_TGSI_TEXCOORD:
return 1;
case PIPE_CAP_SM3:
return 1;
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
return r300screen->caps.has_tcl;
+ case PIPE_CAP_TGSI_TEXCOORD:
+ return 0;
/* Texturing. */
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
return 1;
+ case PIPE_CAP_TGSI_TEXCOORD:
+ return 0;
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
return R600_MAP_BUFFER_ALIGNMENT;
case PIPE_CAP_START_INSTANCE:
case PIPE_CAP_NPOT_TEXTURES:
return 1;
+ case PIPE_CAP_TGSI_TEXCOORD:
+ return 0;
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
return 64;
return 1;
case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
return 0;
+ case PIPE_CAP_TGSI_TEXCOORD:
+ return 0;
}
/* should only get here on unhandled cases */
debug_printf("Unexpected PIPE_CAP %d query\n", param);
return 1;
case PIPE_CAP_POINT_SPRITE:
return 1;
+ case PIPE_CAP_TGSI_TEXCOORD:
+ return 0;
case PIPE_CAP_MAX_RENDER_TARGETS:
if(!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_RENDER_TARGETS, &result))
return 1;
PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT = 75,
PIPE_CAP_CUBE_MAP_ARRAY = 76,
PIPE_CAP_TEXTURE_BUFFER_OBJECTS = 77,
- PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT = 78
+ PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT = 78,
+ PIPE_CAP_TGSI_TEXCOORD = 79
};
/**
#define TGSI_SEMANTIC_BLOCK_ID 16 /**< id of the current block */
#define TGSI_SEMANTIC_BLOCK_SIZE 17 /**< block size in threads */
#define TGSI_SEMANTIC_THREAD_ID 18 /**< block-relative id of the current thread */
-#define TGSI_SEMANTIC_COUNT 19 /**< number of semantic values */
+#define TGSI_SEMANTIC_TEXCOORD 19 /**< texture or sprite coordinates */
+#define TGSI_SEMANTIC_PCOORD 20 /**< point sprite coordinate */
+#define TGSI_SEMANTIC_COUNT 21 /**< number of semantic values */
struct tgsi_declaration_semantic
{
unsigned line_stipple_factor:8; /**< [1..256] actually */
unsigned line_stipple_pattern:16;
- unsigned sprite_coord_enable; /* bitfield referring to 32 GENERIC inputs */
+ uint32_t sprite_coord_enable; /* referring to 32 TEXCOORD/GENERIC inputs */
float line_width;
float point_size; /**< used when no per-vertex size */
screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3);
+ st->needs_texcoord_semantic =
+ screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD);
+
/* GL limits and extensions */
st_init_limits(st);
st_init_extensions(st);
boolean has_time_elapsed;
boolean has_shader_model3;
+ boolean needs_texcoord_semantic;
+
/* On old libGL's for linux we need to invalidate the drawables
* on glViewpport calls, this is set via a option.
*/
st_prepare_vertex_program(struct gl_context *ctx,
struct st_vertex_program *stvp)
{
+ struct st_context *st = st_context(ctx);
GLuint attr;
stvp->num_inputs = 0;
case VARYING_SLOT_TEX5:
case VARYING_SLOT_TEX6:
case VARYING_SLOT_TEX7:
- stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stvp->output_semantic_name[slot] = st->needs_texcoord_semantic ?
+ TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
stvp->output_semantic_index[slot] = attr - VARYING_SLOT_TEX0;
break;
default:
assert(attr < VARYING_SLOT_MAX);
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- stvp->output_semantic_index[slot] = (VARYING_SLOT_VAR0 -
- VARYING_SLOT_TEX0 +
- attr -
- VARYING_SLOT_VAR0);
+ stvp->output_semantic_index[slot] = st->needs_texcoord_semantic ?
+ (attr - VARYING_SLOT_VAR0) : (attr - VARYING_SLOT_TEX0);
break;
}
}
* fragment shader plus fixed-function hardware (such as
* BFC).
*
- * There is no requirement that semantic indexes start at
- * zero or be restricted to a particular range -- nobody
- * should be building tables based on semantic index.
+ * However, some drivers may need us to identify the PNTC and TEXi
+ * varyings if, for example, their capability to replace them with
+ * sprite coordinates is limited.
*/
case VARYING_SLOT_PNTC:
+ if (st->needs_texcoord_semantic) {
+ input_semantic_name[slot] = TGSI_SEMANTIC_PCOORD;
+ input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ }
+ /* fall through */
case VARYING_SLOT_TEX0:
case VARYING_SLOT_TEX1:
case VARYING_SLOT_TEX2:
case VARYING_SLOT_TEX5:
case VARYING_SLOT_TEX6:
case VARYING_SLOT_TEX7:
+ if (st->needs_texcoord_semantic) {
+ input_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD;
+ input_semantic_index[slot] = attr - VARYING_SLOT_TEX0;
+ interpMode[slot] =
+ st_translate_interp(stfp->Base.InterpQualifier[attr], FALSE);
+ break;
+ }
+ /* fall through */
case VARYING_SLOT_VAR0:
default:
- /* Actually, let's try and zero-base this just for
- * readability of the generated TGSI.
+ /* Semantic indices should be zero-based because drivers may choose
+ * to assign a fixed slot determined by that index.
+ * This is useful because ARB_separate_shader_objects uses location
+ * qualifiers for linkage, and if the semantic index corresponds to
+ * these locations, linkage passes in the driver become unecessary.
+ *
+ * If needs_texcoord_semantic is true, no semantic indices will be
+ * consumed for the TEXi varyings, and we can base the locations of
+ * the user varyings on VAR0. Otherwise, we use TEX0 as base index.
*/
assert(attr >= VARYING_SLOT_TEX0);
- input_semantic_index[slot] = (attr - VARYING_SLOT_TEX0);
+ input_semantic_index[slot] = st->needs_texcoord_semantic ?
+ (attr - VARYING_SLOT_VAR0) : (attr - VARYING_SLOT_TEX0);
input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
if (attr == VARYING_SLOT_PNTC)
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;