[Mesa-dev] [PATCH] swr: Add polygon stipple support
Ilia Mirkin
imirkin at alum.mit.edu
Fri Apr 14 16:35:54 UTC 2017
On Fri, Apr 14, 2017 at 11:18 AM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> On Thu, Apr 13, 2017 at 4:30 PM, George Kyriazis
> <george.kyriazis at 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
More information about the mesa-dev
mailing list