Use rasterizer provoking vertex API.
Fix rasterizer provoking vertex for tristrips and quad list/strips.
v2: make provoking vertex tables static const
Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
uint32_t mapIdx = 0;
LONG constantInterpMask = pDC->pState->state.backendState.constantInterpolationMask;
const uint32_t provokingVertex = pDC->pState->state.frontendState.topologyProvokingVertex;
+ const PRIMITIVE_TOPOLOGY topo = pDC->pState->state.topology;
while (_BitScanForward(&slot, linkageMask))
{
uint32_t inputSlot = VERTEX_ATTRIB_START_SLOT + pLinkageMap[mapIdx];
__m128 attrib[3]; // triangle attribs (always 4 wide)
- pa.AssembleSingle(inputSlot, triIndex, attrib);
if (_bittest(&constantInterpMask, mapIdx))
{
+ uint32_t vid;
+ static const uint32_t tristripProvokingVertex[] = {0, 2, 1};
+ static const int32_t quadProvokingTri[2][4] = {{0, 0, 0, 1}, {0, -1, 0, 0}};
+ static const uint32_t quadProvokingVertex[2][4] = {{0, 1, 2, 2}, {0, 1, 1, 2}};
+ static const int32_t qstripProvokingTri[2][4] = {{0, 0, 0, 1}, {-1, 0, 0, 0}};
+ static const uint32_t qstripProvokingVertex[2][4] = {{0, 1, 2, 1}, {0, 0, 2, 1}};
+
+ switch (topo) {
+ case TOP_QUAD_LIST:
+ pa.AssembleSingle(inputSlot,
+ triIndex + quadProvokingTri[triIndex & 1][provokingVertex],
+ attrib);
+ vid = quadProvokingVertex[triIndex & 1][provokingVertex];
+ break;
+ case TOP_QUAD_STRIP:
+ pa.AssembleSingle(inputSlot,
+ triIndex + qstripProvokingTri[triIndex & 1][provokingVertex],
+ attrib);
+ vid = qstripProvokingVertex[triIndex & 1][provokingVertex];
+ break;
+ case TOP_TRIANGLE_STRIP:
+ pa.AssembleSingle(inputSlot, triIndex, attrib);
+ vid = (triIndex & 1)
+ ? tristripProvokingVertex[provokingVertex]
+ : provokingVertex;
+ break;
+ default:
+ pa.AssembleSingle(inputSlot, triIndex, attrib);
+ vid = provokingVertex;
+ break;
+ }
+
for (uint32_t i = 0; i < NumVerts; ++i)
{
- _mm_store_ps(pBuffer, attrib[provokingVertex]);
+ _mm_store_ps(pBuffer, attrib[vid]);
pBuffer += 4;
}
}
else
{
+ pa.AssembleSingle(inputSlot, triIndex, attrib);
+
for (uint32_t i = 0; i < NumVerts; ++i)
{
_mm_store_ps(pBuffer, attrib[i]);
/* Set up frontend state
* XXX setup provokingVertex & topologyProvokingVertex */
SWR_FRONTEND_STATE feState = {0};
+ if (ctx->rasterizer->flatshade_first) {
+ feState.provokingVertex = {1, 0, 0};
+ } else {
+ feState.provokingVertex = {2, 1, 2};
+ }
+
+ switch (info->mode) {
+ case PIPE_PRIM_TRIANGLE_FAN:
+ feState.topologyProvokingVertex = feState.provokingVertex.triFan;
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_TRIANGLES:
+ feState.topologyProvokingVertex = feState.provokingVertex.triStripList;
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ case PIPE_PRIM_QUADS:
+ if (ctx->rasterizer->flatshade_first)
+ feState.topologyProvokingVertex = 0;
+ else
+ feState.topologyProvokingVertex = 3;
+ break;
+ case PIPE_PRIM_LINES:
+ case PIPE_PRIM_LINE_LOOP:
+ case PIPE_PRIM_LINE_STRIP:
+ feState.topologyProvokingVertex = feState.provokingVertex.lineStripList;
+ break;
+ default:
+ feState.topologyProvokingVertex = 0;
+ }
+
feState.bEnableCutIndex = info->primitive_restart;
SwrSetFrontendState(ctx->swrContext, &feState);
case PIPE_CAP_GLSL_FEATURE_LEVEL:
return 330;
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
- return 0;
+ return 1;
case PIPE_CAP_COMPUTE:
return 0;
case PIPE_CAP_USER_VERTEX_BUFFERS:
key.nr_cbufs = ctx->framebuffer.nr_cbufs;
key.light_twoside = ctx->rasterizer->light_twoside;
- key.flatshade = ctx->rasterizer->flatshade;
memcpy(&key.vs_output_semantic_name,
&ctx->vs->info.base.output_semantic_name,
sizeof(key.vs_output_semantic_name));
GEP(hPrivateData, {0, swr_draw_context_num_constantsFS});
const_sizes_ptr->setName("num_fs_constants");
- // xxx should check for flat shading versus interpolation
-
-
// load *pAttribs, *pPerspAttribs
Value *pRawAttribs = LOAD(pPS, {0, SWR_PS_CONTEXT_pAttribs}, "pRawAttribs");
Value *pPerspAttribs =
LOAD(pPS, {0, SWR_PS_CONTEXT_pPerspAttribs}, "pPerspAttribs");
swr_fs->constantMask = 0;
+ swr_fs->flatConstantMask = 0;
swr_fs->pointSpriteMask = 0;
for (int attrib = 0; attrib < PIPE_MAX_SHADER_INPUTS; attrib++) {
if (interpMode == TGSI_INTERPOLATE_CONSTANT) {
swr_fs->constantMask |= 1 << linkedAttrib;
+ } else if (interpMode == TGSI_INTERPOLATE_COLOR) {
+ swr_fs->flatConstantMask |= 1 << linkedAttrib;
}
for (int channel = 0; channel < TGSI_NUM_CHANNELS; channel++) {
if (interpMode == TGSI_INTERPOLATE_CONSTANT) {
swr_fs->constantMask |= 1 << bcolorAttrib;
+ } else if (interpMode == TGSI_INTERPOLATE_COLOR) {
+ swr_fs->flatConstantMask |= 1 << bcolorAttrib;
}
}
if (interpMode == TGSI_INTERPOLATE_CONSTANT) {
inputs[attrib][channel] = wrap(va);
- } else if ((interpMode == TGSI_INTERPOLATE_COLOR) &&
- (key.flatshade == true)) {
- inputs[attrib][channel] = wrap(vc);
} else {
Value *vk = FSUB(FSUB(VIMMED1(1.0f), vi), vj);
struct swr_jit_fs_key : swr_jit_sampler_key {
unsigned nr_cbufs;
unsigned light_twoside;
- unsigned flatshade;
ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
ubyte vs_output_semantic_idx[PIPE_MAX_SHADER_OUTPUTS];
};
SWR_BACKEND_STATE backendState = {0};
backendState.numAttributes = 1;
backendState.numComponents[0] = 4;
- backendState.constantInterpolationMask = ctx->fs->constantMask;
+ backendState.constantInterpolationMask =
+ ctx->rasterizer->flatshade ?
+ ctx->fs->flatConstantMask :
+ ctx->fs->constantMask;
backendState.pointSpriteTexCoordMask = ctx->fs->pointSpriteMask;
SwrSetBackendState(ctx->swrContext, &backendState);
struct pipe_shader_state pipe;
struct lp_tgsi_info info;
uint32_t constantMask;
+ uint32_t flatConstantMask;
uint32_t pointSpriteMask;
std::unordered_map<swr_jit_fs_key, std::unique_ptr<VariantFS>> map;
};