Commit 2210f804 by Ben Clayton Committed by Nicolas Capens

Implement non-solid polygon rasterization

Implements Vulkan's 'fillModeNonSolid' feature. Mostly a copy-and-paste of src/Renderer logic. It sets the batch size for non-solid triangles to 1 so their edges or vertices can get individually rasterized as lines or points. Bug: b/139872671 Tests: dEQP-VK.rasterization.culling.* Change-Id: Ifbae8dad32e8b43159fee459c75d7e593fc08041 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/35031Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent ac69da70
......@@ -29,7 +29,7 @@ namespace sw
init();
}
bool Context::isDrawPoint() const
bool Context::isDrawPoint(bool polygonModeAware) const
{
switch(topology)
{
......@@ -37,46 +37,48 @@ namespace sw
return true;
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
return false;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
break;
return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_POINT) : false;
default:
UNIMPLEMENTED("topology %d", int(topology));
}
return false;
}
bool Context::isDrawLine() const
bool Context::isDrawLine(bool polygonModeAware) const
{
switch(topology)
{
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return false;
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
return true;
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
break;
return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_LINE) : false;
default:
UNIMPLEMENTED("topology %d", int(topology));
}
return false;
}
bool Context::isDrawTriangle() const
bool Context::isDrawTriangle(bool polygonModeAware) const
{
switch(topology)
{
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
return true;
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
break;
return false;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
return polygonModeAware ? (polygonMode == VK_POLYGON_MODE_FILL) : true;
default:
UNIMPLEMENTED("topology %d", int(topology));
}
......
......@@ -74,9 +74,9 @@ namespace sw
void init();
bool isDrawPoint() const;
bool isDrawLine() const;
bool isDrawTriangle() const;
bool isDrawPoint(bool polygonModeAware) const;
bool isDrawLine(bool polygonModeAware) const;
bool isDrawTriangle(bool polygonModeAware) const;
bool depthWriteActive() const;
bool depthBufferActive() const;
......@@ -96,6 +96,7 @@ namespace sw
// Pixel processor states
VkCullModeFlags cullMode;
VkFrontFace frontFace;
VkPolygonMode polygonMode;
float depthBias;
float slopeDepthBias;
......
......@@ -206,16 +206,33 @@ namespace sw
}
DrawCall::SetupFunction setupPrimitives = nullptr;
unsigned int numPrimitivesPerBatch = MaxBatchSize / ms;
if(context->isDrawTriangle())
if(context->isDrawTriangle(false))
{
setupPrimitives = &DrawCall::setupTriangles;
switch(context->polygonMode)
{
case VK_POLYGON_MODE_FILL:
setupPrimitives = &DrawCall::setupSolidTriangles;
break;
case VK_POLYGON_MODE_LINE:
setupPrimitives = &DrawCall::setupWireframeTriangles;
numPrimitivesPerBatch = 1;
break;
case VK_POLYGON_MODE_POINT:
setupPrimitives = &DrawCall::setupPointTriangles;
numPrimitivesPerBatch = 1;
break;
default:
UNSUPPORTED("polygon mode: %d", int(context->polygonMode));
return;
}
}
else if(context->isDrawLine())
else if(context->isDrawLine(false))
{
setupPrimitives = &DrawCall::setupLines;
}
else // Point draw
else // Point primitive topology
{
setupPrimitives = &DrawCall::setupPoints;
}
......@@ -224,7 +241,7 @@ namespace sw
draw->occlusionQuery = occlusionQuery;
draw->batchDataPool = &batchDataPool;
draw->numPrimitives = count;
draw->numPrimitivesPerBatch = MaxBatchSize / ms;
draw->numPrimitivesPerBatch = numPrimitivesPerBatch;
draw->numBatches = (count + draw->numPrimitivesPerBatch - 1) / draw->numPrimitivesPerBatch;
draw->topology = context->topology;
draw->indexType = indexType;
......@@ -297,7 +314,7 @@ namespace sw
float F = viewport.maxDepth;
float Z = F - N;
if(context->isDrawTriangle())
if(context->isDrawTriangle(false))
{
N += context->depthBias;
}
......@@ -567,7 +584,7 @@ namespace sw
triangleIndicesOut[triangleCount][2] = triangleIndicesOut[triangleCount - 1][2];
}
int DrawCall::setupTriangles(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
int DrawCall::setupSolidTriangles(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
{
auto &state = drawCall->setupState;
auto setupRoutine = drawCall->setupPointer;
......@@ -607,6 +624,94 @@ namespace sw
return visible;
}
int DrawCall::setupWireframeTriangles(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
{
auto& state = drawCall->setupState;
int ms = state.multiSample;
int visible = 0;
const Vertex &v0 = triangles[0].v0;
const Vertex &v1 = triangles[0].v1;
const Vertex &v2 = triangles[0].v2;
float d = (v0.position.y * v1.position.x - v0.position.x * v1.position.y) * v2.position.w +
(v0.position.x * v2.position.y - v0.position.y * v2.position.x) * v1.position.w +
(v2.position.x * v1.position.y - v1.position.x * v2.position.y) * v0.position.w;
bool frontFacing = (state.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE) ? d > 0.0f : d < 0.0f;
if(state.cullMode & VK_CULL_MODE_FRONT_BIT)
{
if(frontFacing) return 0;
}
if(state.cullMode & VK_CULL_MODE_BACK_BIT)
{
if(!frontFacing) return 0;
}
// Copy attributes
triangles[1].v0 = v1;
triangles[1].v1 = v2;
triangles[2].v0 = v2;
triangles[2].v1 = v0;
for(int i = 0; i < 3; i++)
{
if(setupLine(*primitives, *triangles, *drawCall))
{
primitives += ms;
visible++;
}
triangles++;
}
return visible;
}
int DrawCall::setupPointTriangles(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
{
auto& state = drawCall->setupState;
int ms = state.multiSample;
int visible = 0;
const Vertex &v0 = triangles[0].v0;
const Vertex &v1 = triangles[0].v1;
const Vertex &v2 = triangles[0].v2;
float d = (v0.position.y * v1.position.x - v0.position.x * v1.position.y) * v2.position.w +
(v0.position.x * v2.position.y - v0.position.y * v2.position.x) * v1.position.w +
(v2.position.x * v1.position.y - v1.position.x * v2.position.y) * v0.position.w;
bool frontFacing = (state.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE) ? d > 0.0f : d < 0.0f;
if(state.cullMode & VK_CULL_MODE_FRONT_BIT)
{
if(frontFacing) return 0;
}
if(state.cullMode & VK_CULL_MODE_BACK_BIT)
{
if(!frontFacing) return 0;
}
// Copy attributes
triangles[1].v0 = v1;
triangles[2].v0 = v2;
for(int i = 0; i < 3; i++)
{
if(setupPoint(*primitives, *triangles, *drawCall))
{
primitives += ms;
visible++;
}
triangles++;
}
return visible;
}
int DrawCall::setupLines(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count)
{
auto &state = drawCall->setupState;
......
......@@ -179,7 +179,9 @@ namespace sw
unsigned int triangleCount,
VkPrimitiveTopology topology);
static int setupTriangles(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count);
static int setupSolidTriangles(Triangle* triangles, Primitive* primitives, const DrawCall* drawCall, int count);
static int setupWireframeTriangles(Triangle* triangles, Primitive* primitives, const DrawCall* drawCall, int count);
static int setupPointTriangles(Triangle* triangles, Primitive* primitives, const DrawCall* drawCall, int count);
static int setupLines(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count);
static int setupPoints(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count);
......
......@@ -69,14 +69,14 @@ namespace sw
bool vPosZW = (context->pixelShader && context->pixelShader->hasBuiltinInput(spv::BuiltInFragCoord));
state.isDrawPoint = context->isDrawPoint();
state.isDrawLine = context->isDrawLine();
state.isDrawTriangle = context->isDrawTriangle();
state.isDrawPoint = context->isDrawPoint(true);
state.isDrawLine = context->isDrawLine(true);
state.isDrawTriangle = context->isDrawTriangle(true);
state.applySlopeDepthBias = context->isDrawTriangle(false) && (context->slopeDepthBias != 0.0f);
state.interpolateZ = context->depthBufferActive() || vPosZW;
state.interpolateW = context->pixelShader != nullptr;
state.frontFace = context->frontFace;
state.cullMode = context->cullMode;
state.slopeDepthBias = context->slopeDepthBias != 0.0f;
state.multiSample = context->sampleCount;
state.rasterizerDiscard = context->rasterizerDiscard;
......
......@@ -42,11 +42,11 @@ namespace sw
bool isDrawPoint : 1;
bool isDrawLine : 1;
bool isDrawTriangle : 1;
bool applySlopeDepthBias : 1;
bool interpolateZ : 1;
bool interpolateW : 1;
VkFrontFace frontFace : BITS(VK_FRONT_FACE_MAX_ENUM);
VkCullModeFlags cullMode : BITS(VK_CULL_MODE_FLAG_BITS_MAX_ENUM);
bool slopeDepthBias : 1;
unsigned int multiSample : 3; // 1, 2 or 4
bool rasterizerDiscard : 1;
......
......@@ -427,7 +427,7 @@ namespace sw
Float c = z0;
if(state.isDrawTriangle && state.slopeDepthBias)
if(state.applySlopeDepthBias)
{
Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x)));
bias *= *Pointer<Float>(data + OFFSET(DrawData,slopeDepthBias));
......
......@@ -44,7 +44,7 @@ const VkPhysicalDeviceFeatures& PhysicalDevice::getFeatures() const
VK_TRUE, // drawIndirectFirstInstance
VK_FALSE, // depthClamp
VK_FALSE, // depthBiasClamp
VK_FALSE, // fillModeNonSolid
VK_TRUE, // fillModeNonSolid
VK_FALSE, // depthBounds
VK_FALSE, // wideLines
VK_FALSE, // largePoints
......
......@@ -382,8 +382,7 @@ GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
const VkPipelineRasterizationStateCreateInfo* rasterizationState = pCreateInfo->pRasterizationState;
if((rasterizationState->flags != 0) ||
(rasterizationState->depthClampEnable != VK_FALSE) ||
(rasterizationState->polygonMode != VK_POLYGON_MODE_FILL))
(rasterizationState->depthClampEnable != VK_FALSE))
{
UNIMPLEMENTED("pCreateInfo->pRasterizationState settings");
}
......@@ -391,6 +390,7 @@ GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo* pCreateIn
context.rasterizerDiscard = (rasterizationState->rasterizerDiscardEnable == VK_TRUE);
context.cullMode = rasterizationState->cullMode;
context.frontFace = rasterizationState->frontFace;
context.polygonMode = rasterizationState->polygonMode;
context.depthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasConstantFactor : 0.0f;
context.slopeDepthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasSlopeFactor : 0.0f;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment