From: Christoph Bumiller Date: Fri, 15 Mar 2013 21:11:31 +0000 (+0100) Subject: gallium: add TGSI_SEMANTIC_TEXCOORD,PCOORD v3 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8acaf862dfeac62550514b0e46f5aa6212b08992;p=mesa.git gallium: add TGSI_SEMANTIC_TEXCOORD,PCOORD v3 This makes it possible to identify gl_TexCoord and gl_PointCoord for drivers where sprite coordinate replacement is restricted. The new PIPE_CAP_TGSI_TEXCOORD decides whether these varyings should be hidden behind the GENERIC semantic or not. With this patch only nvc0 and nv30 will request that they be used. v2: introduce a CAP so other drivers don't have to bother with the new semantic v3: adapt to introduction gl_varying_slot enum --- diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c index 8e0a117843e..0d3fee4bb0d 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c @@ -52,6 +52,7 @@ */ +#include "pipe/p_screen.h" #include "pipe/p_context.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -74,6 +75,9 @@ struct widepoint_stage { 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; }; @@ -233,28 +237,29 @@ widepoint_first_point(struct draw_stage *stage, 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; } } @@ -326,6 +331,11 @@ struct draw_stage *draw_wide_point_stage( struct draw_context *draw ) 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: diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index d98f6c49366..365665fa6f7 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -305,6 +305,7 @@ iter_declaration( 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 ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_strings.c b/src/gallium/auxiliary/tgsi/tgsi_strings.c index 5c92e9a1001..95a5aded819 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_strings.c +++ b/src/gallium/auxiliary/tgsi/tgsi_strings.c @@ -76,7 +76,9 @@ const char *tgsi_semantic_names[TGSI_SEMANTIC_COUNT] = "GRID_SIZE", "BLOCK_ID", "BLOCK_SIZE", - "THREAD_ID" + "THREAD_ID", + "TEXCOORD", + "PCOORD" }; const char *tgsi_texture_names[TGSI_TEXTURE_COUNT] = diff --git a/src/gallium/docs/source/cso/rasterizer.rst b/src/gallium/docs/source/cso/rasterizer.rst index f4e24f0b438..8338243be9f 100644 --- a/src/gallium/docs/source/cso/rasterizer.rst +++ b/src/gallium/docs/source/cso/rasterizer.rst @@ -159,13 +159,18 @@ Points 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). diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst index 68d1a35cc73..0550a30714a 100644 --- a/src/gallium/docs/source/screen.rst +++ b/src/gallium/docs/source/screen.rst @@ -137,6 +137,14 @@ The integer capabilities: * ``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: diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst index 4c55e60cff0..28308cb9483 100644 --- a/src/gallium/docs/source/tgsi.rst +++ b/src/gallium/docs/source/tgsi.rst @@ -1949,6 +1949,35 @@ When using this semantic, be sure to set the appropriate state in the :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 """"""""""""""""""""" diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 5310fc7fdf8..5ff132dac72 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -165,6 +165,8 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) 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; diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index eb96e9e13b0..13aa91c29bd 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -184,6 +184,8 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) 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: diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 93e125da38d..5ec1df659b8 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -208,6 +208,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) 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: diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 90c367280d4..e17ee76fbd1 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -79,6 +79,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) 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; diff --git a/src/gallium/drivers/nv30/nvfx_fragprog.c b/src/gallium/drivers/nv30/nvfx_fragprog.c index 935804e8e14..4be7dec2c03 100644 --- a/src/gallium/drivers/nv30/nvfx_fragprog.c +++ b/src/gallium/drivers/nv30/nvfx_fragprog.c @@ -927,15 +927,17 @@ nvfx_fragprog_parse_decl_input(struct nv30_context *nvfx, struct nvfx_fpc *fpc, 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; @@ -955,22 +957,24 @@ nvfx_fragprog_assign_generic(struct nv30_context *nvfx, struct nvfx_fpc *fpc, 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; } diff --git a/src/gallium/drivers/nv30/nvfx_vertprog.c b/src/gallium/drivers/nv30/nvfx_vertprog.c index 74dba38001c..b73d4184045 100644 --- a/src/gallium/drivers/nv30/nvfx_vertprog.c +++ b/src/gallium/drivers/nv30/nvfx_vertprog.c @@ -819,6 +819,7 @@ nvfx_vertprog_parse_decl_output(struct nv30_context *nv30, struct nvfx_vpc *vpc, { 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) { @@ -860,8 +861,12 @@ nvfx_vertprog_parse_decl_output(struct nv30_context *nv30, struct nvfx_vpc *vpc, 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; } diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_driver.h b/src/gallium/drivers/nv50/codegen/nv50_ir_driver.h index c5a5b23c320..51ed9c1e1ae 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_driver.h +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_driver.h @@ -70,8 +70,6 @@ struct nv50_ir_varying #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) diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index aed1dd56eb5..fb29b2290c2 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -184,6 +184,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) 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: diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index 7a0470c4294..117d3d1894b 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -494,7 +494,7 @@ nv50_blitter_make_vp(struct nv50_blitter *blit) 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; @@ -536,9 +536,8 @@ nv50_blitter_make_fp(struct pipe_context *pipe, 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); diff --git a/src/gallium/drivers/nvc0/nvc0_program.c b/src/gallium/drivers/nvc0/nvc0_program.c index 2f4eae8f052..2f1b41704a5 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nvc0/nvc0_program.c @@ -27,33 +27,6 @@ #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) { @@ -69,11 +42,11 @@ 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: @@ -99,7 +72,7 @@ nvc0_shader_output_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_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"); @@ -149,8 +122,6 @@ nvc0_sp_assign_input_slots(struct nv50_ir_prog_info *info) for (c = 0; c < 4; ++c) info->in[i].slot[c] = (offset + c * 0x4) / 4; - - nvc0_mesa_varying_hack(&info->in[i]); } return 0; @@ -194,8 +165,6 @@ nvc0_sp_assign_output_slots(struct nv50_ir_prog_info *info) for (c = 0; c < 4; ++c) info->out[i].slot[c] = (offset + c * 0x4) / 4; - - nvc0_mesa_varying_hack(&info->out[i]); } return 0; diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index 7d034797eef..e77b819b651 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -114,6 +114,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) 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; diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 06ed1cb5b5b..46fb869cb72 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -172,6 +172,8 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) 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: diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 60a0247d5dd..9ed88148c49 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -565,6 +565,8 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) 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; diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c index 2abfce476a2..859843867ce 100644 --- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c +++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c @@ -330,6 +330,8 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) 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; diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 16aba5a630d..937035e5511 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -173,6 +173,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) 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); diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index 3e71ac3c6bf..f0831b9f2fe 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -150,6 +150,8 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap 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; diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index fdf6e7fb17b..7f20b992a13 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -498,7 +498,8 @@ enum pipe_cap { 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 }; /** diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index 1ca46fd0206..478ce25f57c 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -162,7 +162,9 @@ struct tgsi_declaration_interp #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 { diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index ab49cabb800..dfafd0bb99f 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -145,7 +145,7 @@ struct pipe_rasterizer_state 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 */ diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index f9a584ba0ac..e2d074d14a4 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -183,6 +183,9 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, 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); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index b9a98cd051d..c6c68adcfb2 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -85,6 +85,8 @@ struct st_context 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. */ diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 6af8df31641..7a38da84ffa 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -177,6 +177,7 @@ void 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; @@ -267,7 +268,8 @@ st_prepare_vertex_program(struct gl_context *ctx, 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; @@ -275,10 +277,8 @@ st_prepare_vertex_program(struct gl_context *ctx, 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; } } @@ -585,11 +585,18 @@ st_translate_fragment_program(struct st_context *st, * 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: @@ -598,13 +605,29 @@ st_translate_fragment_program(struct st_context *st, 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;