On Fri, Apr 14, 2017 at 11:18 AM, Ilia Mirkin <imir...@alum.mit.edu> wrote: > On Thu, Apr 13, 2017 at 4:30 PM, George Kyriazis > <george.kyria...@intel.com> wrote: >> Add polygon stipple functionality to the fragment shader. >> >> Explicitly turn off polygon stipple for lines and points, since we >> do them using tris. >> --- >> src/gallium/drivers/swr/swr_context.h | 4 ++- >> src/gallium/drivers/swr/swr_shader.cpp | 56 >> ++++++++++++++++++++++++++++++---- >> src/gallium/drivers/swr/swr_shader.h | 1 + >> src/gallium/drivers/swr/swr_state.cpp | 27 ++++++++++++++-- >> src/gallium/drivers/swr/swr_state.h | 5 +++ >> 5 files changed, 84 insertions(+), 9 deletions(-) >> >> diff --git a/src/gallium/drivers/swr/swr_context.h >> b/src/gallium/drivers/swr/swr_context.h >> index be65a20..9d80c70 100644 >> --- a/src/gallium/drivers/swr/swr_context.h >> +++ b/src/gallium/drivers/swr/swr_context.h >> @@ -98,6 +98,8 @@ struct swr_draw_context { >> >> float userClipPlanes[PIPE_MAX_CLIP_PLANES][4]; >> >> + uint32_t polyStipple[32]; >> + >> SWR_SURFACE_STATE renderTargets[SWR_NUM_ATTACHMENTS]; >> void *pStats; >> }; >> @@ -127,7 +129,7 @@ struct swr_context { >> struct pipe_constant_buffer >> constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; >> struct pipe_framebuffer_state framebuffer; >> - struct pipe_poly_stipple poly_stipple; >> + struct swr_poly_stipple poly_stipple; >> struct pipe_scissor_state scissor; >> SWR_RECT swr_scissor; >> struct pipe_sampler_view * >> diff --git a/src/gallium/drivers/swr/swr_shader.cpp >> b/src/gallium/drivers/swr/swr_shader.cpp >> index 6fc0596..d8f5512 100644 >> --- a/src/gallium/drivers/swr/swr_shader.cpp >> +++ b/src/gallium/drivers/swr/swr_shader.cpp >> @@ -165,6 +165,9 @@ swr_generate_fs_key(struct swr_jit_fs_key &key, >> sizeof(key.vs_output_semantic_idx)); >> >> swr_generate_sampler_key(swr_fs->info, ctx, PIPE_SHADER_FRAGMENT, key); >> + >> + key.poly_stipple_enable = ctx->rasterizer->poly_stipple_enable && >> + ctx->poly_stipple.prim_is_poly; >> } >> >> void >> @@ -1099,17 +1102,58 @@ BuilderSWR::CompileFS(struct swr_context *ctx, >> swr_jit_fs_key &key) >> memset(&system_values, 0, sizeof(system_values)); >> >> struct lp_build_mask_context mask; >> + bool uses_mask = false; >> >> - if (swr_fs->info.base.uses_kill) { >> - Value *mask_val = LOAD(pPS, {0, SWR_PS_CONTEXT_activeMask}, >> "activeMask"); >> + if (swr_fs->info.base.uses_kill || >> + key.poly_stipple_enable) { >> + Value *vActiveMask = NULL; >> + if (swr_fs->info.base.uses_kill) { >> + vActiveMask = LOAD(pPS, {0, SWR_PS_CONTEXT_activeMask}, >> "activeMask"); >> + } >> + if (key.poly_stipple_enable) { >> + // first get fragment xy coords and clip to stipple bounds >> + Value *vXf = LOAD(pPS, {0, SWR_PS_CONTEXT_vX, PixelPositions_UL}); >> + Value *vYf = LOAD(pPS, {0, SWR_PS_CONTEXT_vY, PixelPositions_UL}); >> + Value *vXu = FP_TO_UI(vXf, mSimdInt32Ty); >> + Value *vYu = FP_TO_UI(vYf, mSimdInt32Ty); >> + >> + // stipple pattern is 32x32, which means that one line of stipple >> + // is stored in one word: >> + // vXstipple is bit offset inside 32-bit stipple word >> + // vYstipple is word index is stipple array >> + Value *vXstipple = AND(vXu, VIMMED1(0x1f)); // & (32-1) >> + Value *vYstipple = AND(vYu, VIMMED1(0x1f)); // & (32-1) >> + >> + // grab stipple pattern base address >> + Value *stipplePtr = GEP(hPrivateData, {0, >> swr_draw_context_polyStipple, 0}); >> + stipplePtr = BITCAST(stipplePtr, mInt8PtrTy); >> + >> + // peform a gather to grab stipple words for each lane >> + Value *vStipple = GATHERDD(VUNDEF_I(), stipplePtr, vYstipple, >> + VIMMED1(0xffffffff), C((char)4)); >> + >> + // create a mask with one bit corresponding to the x stipple >> + // and AND it with the pattern, to see if we have a bit >> + Value *vBitMask = LSHR(VIMMED1(0x80000000), vXstipple); >> + Value *vStippleMask = AND(vStipple, vBitMask); >> + vStippleMask = ICMP_NE(vStippleMask, VIMMED1(0)); >> + vStippleMask = VMASK(vStippleMask); >> + >> + if (swr_fs->info.base.uses_kill) { >> + vActiveMask = AND(vActiveMask, vStippleMask); >> + } else { >> + vActiveMask = vStippleMask; >> + } >> + } >> lp_build_mask_begin( >> - &mask, gallivm, lp_type_float_vec(32, 32 * 8), wrap(mask_val)); >> + &mask, gallivm, lp_type_float_vec(32, 32 * 8), wrap(vActiveMask)); >> + uses_mask = true; >> } >> >> lp_build_tgsi_soa(gallivm, >> swr_fs->pipe.tokens, >> lp_type_float_vec(32, 32 * 8), >> - swr_fs->info.base.uses_kill ? &mask : NULL, // mask >> + uses_mask ? &mask : NULL, // mask >> wrap(consts_ptr), >> wrap(const_sizes_ptr), >> &system_values, >> @@ -1172,13 +1216,13 @@ BuilderSWR::CompileFS(struct swr_context *ctx, >> swr_jit_fs_key &key) >> } >> >> LLVMValueRef mask_result = 0; >> - if (swr_fs->info.base.uses_kill) { >> + if (uses_mask) { >> mask_result = lp_build_mask_end(&mask); >> } >> >> IRB()->SetInsertPoint(unwrap(LLVMGetInsertBlock(gallivm->builder))); >> >> - if (swr_fs->info.base.uses_kill) { >> + if (uses_mask) { >> STORE(unwrap(mask_result), pPS, {0, SWR_PS_CONTEXT_activeMask}); >> } >> >> diff --git a/src/gallium/drivers/swr/swr_shader.h >> b/src/gallium/drivers/swr/swr_shader.h >> index c9df5b0..1ab6846 100644 >> --- a/src/gallium/drivers/swr/swr_shader.h >> +++ b/src/gallium/drivers/swr/swr_shader.h >> @@ -66,6 +66,7 @@ struct swr_jit_fs_key : swr_jit_sampler_key { >> unsigned sprite_coord_enable; >> ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; >> ubyte vs_output_semantic_idx[PIPE_MAX_SHADER_OUTPUTS]; >> + bool poly_stipple_enable; >> }; >> >> struct swr_jit_vs_key : swr_jit_sampler_key { >> diff --git a/src/gallium/drivers/swr/swr_state.cpp >> b/src/gallium/drivers/swr/swr_state.cpp >> index 5cc01dd..4f7ef66 100644 >> --- a/src/gallium/drivers/swr/swr_state.cpp >> +++ b/src/gallium/drivers/swr/swr_state.cpp >> @@ -39,6 +39,7 @@ >> #include "util/u_helpers.h" >> #include "util/u_framebuffer.h" >> #include "util/u_viewport.h" >> +#include "util/u_prim.h" >> >> #include "swr_state.h" >> #include "swr_context.h" >> @@ -608,7 +609,7 @@ swr_set_polygon_stipple(struct pipe_context *pipe, >> { >> struct swr_context *ctx = swr_context(pipe); >> >> - ctx->poly_stipple = *stipple; /* struct copy */ >> + ctx->poly_stipple.pipe = *stipple; /* struct copy */ >> ctx->dirty |= SWR_NEW_STIPPLE; >> } >> >> @@ -952,6 +953,17 @@ swr_user_vbuf_range(const struct pipe_draw_info *info, >> } >> } >> >> +static void >> +swr_update_poly_stipple(struct swr_context *ctx) >> +{ >> + struct swr_draw_context *pDC = &ctx->swrDC; >> + >> + assert(sizeof(ctx->poly_stipple.pipe.stipple) == >> sizeof(pDC->polyStipple)); >> + memcpy(pDC->polyStipple, >> + ctx->poly_stipple.pipe.stipple, >> + sizeof(ctx->poly_stipple.pipe.stipple)); >> +} >> + >> void >> swr_update_derived(struct pipe_context *pipe, >> const struct pipe_draw_info *p_draw_info) >> @@ -1352,6 +1364,17 @@ swr_update_derived(struct pipe_context *pipe, >> } >> } >> >> + /* work around the fact that poly stipple also affects lines */ >> + /* and points, since we rasterize them as triangles, too */ >> + /* Has to be before fragment shader, since it sets SWR_NEW_FS */ >> + if (p_draw_info) { >> + bool new_prim_is_poly = (u_reduced_prim(p_draw_info->mode) == >> PIPE_PRIM_TRIANGLES); > > What about glPolygonMode and what about geometry shaders that take in > e.g. points and put out triangles? Perhaps you need to pass in a "is > this *really* a triangle" parameter to the shader generated by the > rasterizer.
Actually the GS thing won't happen since polygon stippling is a compat-only feature and we don't support GS in compat profiles. You do need to check that the polymode == FILL here though. > Also it might be easy to just do all this masking directly in core > instead of as a frag shader variant implemented in swr_shader... I still think this would be a better place. Note that line stippling is also a thing. > > Cheers, > > -ilia _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev