Commit 00bfa189 by Nicolas Capens

Support frustum clipping against z = -1.

This allows performing the depth range adjustment only once as part of the viewport transform and not have it be affected by transform feedback. Change-Id: I89fba3b131c234bea064b1b65f50b62261f4c307 Reviewed-on: https://swiftshader-review.googlesource.com/5421Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 53bf0a11
......@@ -2425,12 +2425,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
{
if(!mState.currentProgram)
{
const sw::Matrix Z(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0.5, 0.5,
0, 0, 0, 1); // Map depth range from [-1, 1] to [0, 1]
device->setProjectionMatrix(Z * projection.current());
device->setProjectionMatrix(projection.current());
device->setViewMatrix(modelView.current());
device->setTextureMatrix(0, texture[0].current());
device->setTextureMatrix(1, texture[1].current());
......@@ -3462,12 +3457,7 @@ void Context::end()
return error(GL_INVALID_OPERATION);
}
const sw::Matrix Z(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0.5, 0.5,
0, 0, 0, 1); // Map depth range from [-1, 1] to [0, 1]
device->setProjectionMatrix(Z * projection.current());
device->setProjectionMatrix(projection.current());
device->setViewMatrix(modelView.current());
device->setTextureMatrix(0, texture[0].current());
device->setTextureMatrix(1, texture[1].current());
......
......@@ -1959,12 +1959,7 @@ void Context::applyState(GLenum drawMode)
device->setAmbientMaterialSource(sw::MATERIAL_MATERIAL);
device->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
const sw::Matrix Z(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0.5, 0.5,
0, 0, 0, 1); // Map depth range from [-1, 1] to [0, 1]
device->setProjectionMatrix(Z * projectionStack.current());
device->setProjectionMatrix(projectionStack.current());
device->setModelMatrix(modelViewStack.current());
device->setTextureMatrix(0, textureStack0.current());
device->setTextureMatrix(1, textureStack1.current());
......
......@@ -20,8 +20,9 @@
namespace sw
{
Clipper::Clipper()
Clipper::Clipper(bool symmetricNormalizedDepth)
{
n = symmetricNormalizedDepth ? -1.0f : 0.0f;
}
Clipper::~Clipper()
......@@ -30,12 +31,12 @@ namespace sw
unsigned int Clipper::computeClipFlags(const float4 &v)
{
return ((v.x > v.w) ? CLIP_RIGHT : 0) |
((v.y > v.w) ? CLIP_TOP : 0) |
((v.z > v.w) ? CLIP_FAR : 0) |
((v.x < -v.w) ? CLIP_LEFT : 0) |
((v.y < -v.w) ? CLIP_BOTTOM : 0) |
((v.z < 0) ? CLIP_NEAR : 0) |
return ((v.x > v.w) ? CLIP_RIGHT : 0) |
((v.y > v.w) ? CLIP_TOP : 0) |
((v.z > v.w) ? CLIP_FAR : 0) |
((v.x < -v.w) ? CLIP_LEFT : 0) |
((v.y < -v.w) ? CLIP_BOTTOM : 0) |
((v.z < n * v.w) ? CLIP_NEAR : 0) |
Clipper::CLIP_FINITE; // FIXME: xyz finite
}
......@@ -90,8 +91,8 @@ namespace sw
{
int j = i == polygon.n - 1 ? 0 : i + 1;
float di = V[i]->z;
float dj = V[j]->z;
float di = V[i]->z - n * V[i]->w;
float dj = V[j]->z - n * V[j]->w;
if(di >= 0)
{
......@@ -100,7 +101,7 @@ namespace sw
if(dj < 0)
{
clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
polygon.B[polygon.b].z = 0;
polygon.B[polygon.b].z = n * polygon.B[polygon.b].w;
T[t++] = &polygon.B[polygon.b++];
}
}
......@@ -109,7 +110,7 @@ namespace sw
if(dj > 0)
{
clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
polygon.B[polygon.b].z = 0;
polygon.B[polygon.b].z = n * polygon.B[polygon.b].w;
T[t++] = &polygon.B[polygon.b++];
}
}
......
......@@ -52,7 +52,7 @@ namespace sw
CLIP_USER = 0x3F00
};
Clipper();
Clipper(bool symmetricNormalizedDepth);
~Clipper();
......@@ -69,6 +69,8 @@ namespace sw
void clipPlane(Polygon &polygon, const Plane &plane);
void clipEdge(float4 &Vo, const float4 &Vi, const float4 &Vj, float di, float dj) const;
float n; // Near clip plane distance
};
}
......
......@@ -113,7 +113,7 @@ namespace sw
sw::exactColorRounding = exactColorRounding;
setRenderTarget(0, 0);
clipper = new Clipper();
clipper = new Clipper(symmetricNormalizedDepth);
updateViewMatrix = true;
updateBaseMatrix = true;
......
......@@ -302,13 +302,9 @@ namespace sw
conditionalRotate2(wMax == w2, v0, v1, v2);
}
Float4 p0 = *Pointer<Float4>(v0 + pos * 16, 16);
Float4 p1 = *Pointer<Float4>(v1 + pos * 16, 16);
Float4 p2 = *Pointer<Float4>(v2 + pos * 16, 16);
Float w0 = p0.w;
Float w1 = p1.w;
Float w2 = p2.w;
Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
Float w2 = *Pointer<Float>(v2 + pos * 16 + 12);
Float4 w012;
......
......@@ -72,13 +72,12 @@ namespace sw
UInt cacheIndex = index & 0x0000003F;
Pointer<Byte> cacheLine = vertexCache + cacheIndex * UInt((int)sizeof(Vertex));
writeVertex(vertex, cacheLine, primitiveNumber, indexInPrimitive);
writeVertex(vertex, cacheLine);
vertex += sizeof(Vertex);
batch += sizeof(unsigned int);
vertexCount--;
if(state.transformFeedbackEnabled != 0)
{
transformFeedback(vertex, primitiveNumber, indexInPrimitive);
indexInPrimitive++;
If(indexInPrimitive == 3)
{
......@@ -86,6 +85,10 @@ namespace sw
indexInPrimitive = 0;
}
}
vertex += sizeof(Vertex);
batch += sizeof(unsigned int);
vertexCount--;
}
Until(vertexCount == 0)
......@@ -107,41 +110,26 @@ namespace sw
{
int pos = state.positionRegister;
Float4 outPosZ = o[pos].z;
if(state.transformFeedbackEnabled && symmetricNormalizedDepth && !state.fixedFunction)
{
outPosZ = (outPosZ + o[pos].w) * Float4(0.5f);
}
Int4 maxX = CmpLT(o[pos].w, o[pos].x);
Int4 maxY = CmpLT(o[pos].w, o[pos].y);
Int4 maxZ = CmpLT(o[pos].w, outPosZ);
Int4 maxZ = CmpLT(o[pos].w, o[pos].z);
Int4 minX = CmpNLE(-o[pos].w, o[pos].x);
Int4 minY = CmpNLE(-o[pos].w, o[pos].y);
Int4 minZ = CmpNLE(Float4(0.0f), outPosZ);
Int flags;
flags = SignMask(maxX);
clipFlags = *Pointer<Int>(constants + OFFSET(Constants,maxX) + flags * 4); // FIXME: Array indexing
flags = SignMask(maxY);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,maxY) + flags * 4);
flags = SignMask(maxZ);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,maxZ) + flags * 4);
flags = SignMask(minX);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minX) + flags * 4);
flags = SignMask(minY);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minY) + flags * 4);
flags = SignMask(minZ);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minZ) + flags * 4);
Int4 minZ = symmetricNormalizedDepth ? CmpNLE(-o[pos].w, o[pos].z) : CmpNLE(Float4(0.0f), o[pos].z);
clipFlags = *Pointer<Int>(constants + OFFSET(Constants,maxX) + SignMask(maxX) * 4); // FIXME: Array indexing
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,maxY) + SignMask(maxY) * 4);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,maxZ) + SignMask(maxZ) * 4);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minX) + SignMask(minX) * 4);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minY) + SignMask(minY) * 4);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minZ) + SignMask(minZ) * 4);
Int4 finiteX = CmpLE(Abs(o[pos].x), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
Int4 finiteY = CmpLE(Abs(o[pos].y), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
Int4 finiteZ = CmpLE(Abs(outPosZ), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
Int4 finiteZ = CmpLE(Abs(o[pos].z), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
flags = SignMask(finiteX & finiteY & finiteZ);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,fini) + flags * 4);
Int4 finiteXYZ = finiteX & finiteY & finiteZ;
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,fini) + SignMask(finiteXYZ) * 4);
if(state.preTransformed)
{
......@@ -586,11 +574,6 @@ namespace sw
o[pos].x = o[pos].x + *Pointer<Float4>(data + OFFSET(DrawData,XXXX)) * o[pos].w;
o[pos].y = o[pos].y + *Pointer<Float4>(data + OFFSET(DrawData,YYYY)) * o[pos].w;
}
if(!state.transformFeedbackEnabled && symmetricNormalizedDepth && !state.fixedFunction)
{
o[pos].z = (o[pos].z + o[pos].w) * Float4(0.5f);
}
}
void VertexRoutine::writeCache(Pointer<Byte> &cacheLine)
......@@ -661,6 +644,7 @@ namespace sw
*Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 2) = (clipFlags >> 16) & 0x0000000FF;
*Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 3) = (clipFlags >> 24) & 0x0000000FF;
// Viewport transform
int pos = state.positionRegister;
v.x = o[pos].x;
......@@ -668,6 +652,11 @@ namespace sw
v.z = o[pos].z;
v.w = o[pos].w;
if(symmetricNormalizedDepth)
{
v.z = (v.z + v.w) * Float4(0.5f); // [-1, 1] -> [0, 1]
}
Float4 w = As<Float4>(As<Int4>(v.w) | (As<Int4>(CmpEQ(v.w, Float4(0.0f))) & As<Int4>(Float4(1.0f))));
Float4 rhw = Float4(1.0f) / w;
......@@ -684,7 +673,7 @@ namespace sw
*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 3, 16) = v.w;
}
void VertexRoutine::writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cache, const UInt &primitiveNumber, const UInt &indexInPrimitive)
void VertexRoutine::writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cache)
{
for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
{
......@@ -696,45 +685,39 @@ namespace sw
*Pointer<Int4>(vertex + OFFSET(Vertex,X)) = *Pointer<Int4>(cache + OFFSET(Vertex,X));
*Pointer<Int>(vertex + OFFSET(Vertex,clipFlags)) = *Pointer<Int>(cache + OFFSET(Vertex,clipFlags));
}
if(state.transformFeedbackEnabled != 0)
void VertexRoutine::transformFeedback(const Pointer<Byte> &vertex, const UInt &primitiveNumber, const UInt &indexInPrimitive)
{
If(indexInPrimitive < state.verticesPerPrimitive)
{
If(indexInPrimitive < state.verticesPerPrimitive)
UInt tOffset = primitiveNumber * state.verticesPerPrimitive + indexInPrimitive;
for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
{
UInt tOffset = primitiveNumber * state.verticesPerPrimitive + indexInPrimitive;
for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++i)
if(state.transformFeedbackEnabled & (1ULL << i))
{
if(state.transformFeedbackEnabled & (1ULL << i))
{
UInt reg = *Pointer<UInt>(data + OFFSET(DrawData, vs.reg[i]));
UInt row = *Pointer<UInt>(data + OFFSET(DrawData, vs.row[i]));
UInt col = *Pointer<UInt>(data + OFFSET(DrawData, vs.col[i]));
UInt str = *Pointer<UInt>(data + OFFSET(DrawData, vs.str[i]));
UInt reg = *Pointer<UInt>(data + OFFSET(DrawData, vs.reg[i]));
UInt row = *Pointer<UInt>(data + OFFSET(DrawData, vs.row[i]));
UInt col = *Pointer<UInt>(data + OFFSET(DrawData, vs.col[i]));
UInt str = *Pointer<UInt>(data + OFFSET(DrawData, vs.str[i]));
Pointer<Byte> t = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.t[i])) + (tOffset * str * sizeof(float));
Pointer<Byte> v = vertex + OFFSET(Vertex, v) + reg * sizeof(float);
Pointer<Byte> t = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.t[i])) + (tOffset * str * sizeof(float));
Pointer<Byte> v = vertex + OFFSET(Vertex, v) + reg * sizeof(float);
For(UInt r = 0, r < row, r++)
{
UInt rOffsetX = r * col * sizeof(float);
UInt rOffset4 = r * sizeof(float4);
For(UInt r = 0, r < row, r++)
For(UInt c = 0, c < col, c++)
{
UInt rOffsetX = r * col * sizeof(float);
UInt rOffset4 = r * sizeof(float4);
For(UInt c = 0, c < col, c++)
{
UInt cOffset = c * sizeof(float);
*Pointer<Float>(t + rOffsetX + cOffset) = *Pointer<Float>(v + rOffset4 + cOffset);
}
UInt cOffset = c * sizeof(float);
*Pointer<Float>(t + rOffsetX + cOffset) = *Pointer<Float>(v + rOffset4 + cOffset);
}
}
}
}
// Make this correction after transform feedback has been outputted
if(symmetricNormalizedDepth && !state.fixedFunction && state.output[state.positionRegister].write)
{
Float z = *Pointer<Float>(vertex + OFFSET(Vertex, v[state.positionRegister]) + 2 * sizeof(float));
Float w = *Pointer<Float>(vertex + OFFSET(Vertex, v[state.positionRegister]) + 3 * sizeof(float));
*Pointer<Float>(vertex + OFFSET(Vertex, v[state.positionRegister]) + 2 * sizeof(float)) = (z + w) * Float(0.5f);
}
}
}
}
......@@ -63,7 +63,8 @@ namespace sw
void computeClipFlags();
void postTransform();
void writeCache(Pointer<Byte> &cacheLine);
void writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cacheLine, const UInt &primitiveNumber, const UInt &indexInPrimitive);
void writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cacheLine);
void transformFeedback(const Pointer<Byte> &vertex, const UInt &primitiveNumber, const UInt &indexInPrimitive);
};
}
......
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