swr: implement clipPlanes/clipVertex/clipDistance/cullDistance
v2: only load the clip vertex once v3: fix clip enable logic, add cullDistance v4: remove duplicate fields in vs jit key, fix test of clip fixup needed v5: fix clipdistance linkage for slot!=0,4 v6: support clip+cull; passes most piglit clip (failures understood) Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
This commit is contained in:
@@ -211,7 +211,7 @@ GL 4.5, GLSL 4.50:
|
||||
GL_ARB_ES3_1_compatibility DONE (nvc0, radeonsi)
|
||||
GL_ARB_clip_control DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe, swr)
|
||||
GL_ARB_conditional_render_inverted DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe, swr)
|
||||
GL_ARB_cull_distance DONE (i965, nv50, nvc0, llvmpipe, softpipe)
|
||||
GL_ARB_cull_distance DONE (i965, nv50, nvc0, llvmpipe, softpipe, swr)
|
||||
GL_ARB_derivative_control DONE (i965, nv50, nvc0, r600, radeonsi)
|
||||
GL_ARB_direct_state_access DONE (all drivers)
|
||||
GL_ARB_get_texture_sub_image DONE (all drivers)
|
||||
|
@@ -89,6 +89,8 @@ struct swr_draw_context {
|
||||
swr_jit_texture texturesFS[PIPE_MAX_SHADER_SAMPLER_VIEWS];
|
||||
swr_jit_sampler samplersFS[PIPE_MAX_SAMPLERS];
|
||||
|
||||
float userClipPlanes[PIPE_MAX_CLIP_PLANES][4];
|
||||
|
||||
SWR_SURFACE_STATE renderTargets[SWR_NUM_ATTACHMENTS];
|
||||
};
|
||||
|
||||
|
@@ -333,6 +333,8 @@ swr_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
||||
case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
|
||||
case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
|
||||
return 1;
|
||||
case PIPE_CAP_CULL_DISTANCE:
|
||||
return 1;
|
||||
case PIPE_CAP_TGSI_TXQS:
|
||||
case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
|
||||
case PIPE_CAP_SHAREABLE_SHADERS:
|
||||
@@ -358,7 +360,6 @@ swr_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
||||
case PIPE_CAP_PCI_DEVICE:
|
||||
case PIPE_CAP_PCI_FUNCTION:
|
||||
case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
|
||||
case PIPE_CAP_CULL_DISTANCE:
|
||||
case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES:
|
||||
case PIPE_CAP_TGSI_VOTE:
|
||||
return 0;
|
||||
|
@@ -40,6 +40,9 @@
|
||||
#include "swr_state.h"
|
||||
#include "swr_screen.h"
|
||||
|
||||
static unsigned
|
||||
locate_linkage(ubyte name, ubyte index, struct tgsi_shader_info *info);
|
||||
|
||||
bool operator==(const swr_jit_fs_key &lhs, const swr_jit_fs_key &rhs)
|
||||
{
|
||||
return !memcmp(&lhs, &rhs, sizeof(lhs));
|
||||
@@ -119,6 +122,11 @@ swr_generate_vs_key(struct swr_jit_vs_key &key,
|
||||
{
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
key.clip_plane_mask =
|
||||
swr_vs->info.base.clipdist_writemask ?
|
||||
swr_vs->info.base.clipdist_writemask & ctx->rasterizer->clip_plane_enable :
|
||||
ctx->rasterizer->clip_plane_enable;
|
||||
|
||||
swr_generate_sampler_key(swr_vs->info, ctx, PIPE_SHADER_VERTEX, key);
|
||||
}
|
||||
|
||||
@@ -251,6 +259,63 @@ BuilderSWR::CompileVS(struct swr_context *ctx, swr_jit_vs_key &key)
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->rasterizer->clip_plane_enable ||
|
||||
swr_vs->info.base.culldist_writemask) {
|
||||
unsigned clip_mask = ctx->rasterizer->clip_plane_enable;
|
||||
|
||||
unsigned cv = 0;
|
||||
if (swr_vs->info.base.writes_clipvertex) {
|
||||
cv = 1 + locate_linkage(TGSI_SEMANTIC_CLIPVERTEX, 0,
|
||||
&swr_vs->info.base);
|
||||
} else {
|
||||
for (int i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
|
||||
if (swr_vs->info.base.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
|
||||
swr_vs->info.base.output_semantic_index[i] == 0) {
|
||||
cv = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LLVMValueRef cx = LLVMBuildLoad(gallivm->builder, outputs[cv][0], "");
|
||||
LLVMValueRef cy = LLVMBuildLoad(gallivm->builder, outputs[cv][1], "");
|
||||
LLVMValueRef cz = LLVMBuildLoad(gallivm->builder, outputs[cv][2], "");
|
||||
LLVMValueRef cw = LLVMBuildLoad(gallivm->builder, outputs[cv][3], "");
|
||||
|
||||
for (unsigned val = 0; val < PIPE_MAX_CLIP_PLANES; val++) {
|
||||
// clip distance overrides user clip planes
|
||||
if ((swr_vs->info.base.clipdist_writemask & clip_mask & (1 << val)) ||
|
||||
((swr_vs->info.base.culldist_writemask << swr_vs->info.base.num_written_clipdistance) & (1 << val))) {
|
||||
unsigned cv = 1 + locate_linkage(TGSI_SEMANTIC_CLIPDIST, val < 4 ? 0 : 1,
|
||||
&swr_vs->info.base);
|
||||
if (val < 4) {
|
||||
LLVMValueRef dist = LLVMBuildLoad(gallivm->builder, outputs[cv][val], "");
|
||||
STORE(unwrap(dist), vtxOutput, {0, 0, VERTEX_CLIPCULL_DIST_LO_SLOT, val});
|
||||
} else {
|
||||
LLVMValueRef dist = LLVMBuildLoad(gallivm->builder, outputs[cv][val - 4], "");
|
||||
STORE(unwrap(dist), vtxOutput, {0, 0, VERTEX_CLIPCULL_DIST_HI_SLOT, val - 4});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(clip_mask & (1 << val)))
|
||||
continue;
|
||||
|
||||
Value *px = LOAD(GEP(hPrivateData, {0, swr_draw_context_userClipPlanes, val, 0}));
|
||||
Value *py = LOAD(GEP(hPrivateData, {0, swr_draw_context_userClipPlanes, val, 1}));
|
||||
Value *pz = LOAD(GEP(hPrivateData, {0, swr_draw_context_userClipPlanes, val, 2}));
|
||||
Value *pw = LOAD(GEP(hPrivateData, {0, swr_draw_context_userClipPlanes, val, 3}));
|
||||
Value *dist = FADD(FMUL(unwrap(cx), VBROADCAST(px)),
|
||||
FADD(FMUL(unwrap(cy), VBROADCAST(py)),
|
||||
FADD(FMUL(unwrap(cz), VBROADCAST(pz)),
|
||||
FMUL(unwrap(cw), VBROADCAST(pw)))));
|
||||
|
||||
if (val < 4)
|
||||
STORE(dist, vtxOutput, {0, 0, VERTEX_CLIPCULL_DIST_LO_SLOT, val});
|
||||
else
|
||||
STORE(dist, vtxOutput, {0, 0, VERTEX_CLIPCULL_DIST_HI_SLOT, val - 4});
|
||||
}
|
||||
}
|
||||
|
||||
RET_VOID();
|
||||
|
||||
gallivm_verify_function(gallivm, wrap(pFunction));
|
||||
|
@@ -56,6 +56,7 @@ struct swr_jit_fs_key : swr_jit_sampler_key {
|
||||
};
|
||||
|
||||
struct swr_jit_vs_key : swr_jit_sampler_key {
|
||||
unsigned clip_plane_mask; // from rasterizer state & vs_info
|
||||
};
|
||||
|
||||
namespace std
|
||||
|
@@ -849,7 +849,9 @@ swr_update_derived(struct pipe_context *pipe,
|
||||
}
|
||||
|
||||
/* Raster state */
|
||||
if (ctx->dirty & (SWR_NEW_RASTERIZER | SWR_NEW_FRAMEBUFFER)) {
|
||||
if (ctx->dirty & (SWR_NEW_RASTERIZER |
|
||||
SWR_NEW_VS | // clipping
|
||||
SWR_NEW_FRAMEBUFFER)) {
|
||||
pipe_rasterizer_state *rasterizer = ctx->rasterizer;
|
||||
pipe_framebuffer_state *fb = &ctx->framebuffer;
|
||||
|
||||
@@ -906,6 +908,14 @@ swr_update_derived(struct pipe_context *pipe,
|
||||
|
||||
rastState->depthClipEnable = rasterizer->depth_clip;
|
||||
|
||||
rastState->clipDistanceMask =
|
||||
ctx->vs->info.base.num_written_clipdistance ?
|
||||
ctx->vs->info.base.clipdist_writemask & rasterizer->clip_plane_enable :
|
||||
rasterizer->clip_plane_enable;
|
||||
|
||||
rastState->cullDistanceMask =
|
||||
ctx->vs->info.base.culldist_writemask << ctx->vs->info.base.num_written_clipdistance;
|
||||
|
||||
SwrSetRastState(ctx->swrContext, rastState);
|
||||
}
|
||||
|
||||
@@ -1067,6 +1077,7 @@ swr_update_derived(struct pipe_context *pipe,
|
||||
|
||||
/* VertexShader */
|
||||
if (ctx->dirty & (SWR_NEW_VS |
|
||||
SWR_NEW_RASTERIZER | // for clip planes
|
||||
SWR_NEW_SAMPLER |
|
||||
SWR_NEW_SAMPLER_VIEW |
|
||||
SWR_NEW_FRAMEBUFFER)) {
|
||||
@@ -1341,6 +1352,18 @@ swr_update_derived(struct pipe_context *pipe,
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->dirty & SWR_NEW_CLIP) {
|
||||
// shader exporting clip distances overrides all user clip planes
|
||||
if (ctx->rasterizer->clip_plane_enable &&
|
||||
!ctx->vs->info.base.num_written_clipdistance)
|
||||
{
|
||||
swr_draw_context *pDC = &ctx->swrDC;
|
||||
memcpy(pDC->userClipPlanes,
|
||||
ctx->clip.ucp,
|
||||
sizeof(pDC->userClipPlanes));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t linkage = ctx->vs->linkageMask;
|
||||
if (ctx->rasterizer->sprite_coord_enable)
|
||||
linkage |= (1 << ctx->vs->info.base.num_outputs);
|
||||
|
Reference in New Issue
Block a user