Commit 26f1a86b by Chris Forbes

Rework setup, VS->FS structures, etc for Vulkan

- Remnants of old fixed function attributes all gone - Initial support for some builtins to prove the model - Setup now driven by correct shader state - VS->FS intermediate structure matches SPIRV model -- builtins are not in location space; location space itself is flat scalars rather than vec4-oriented. There are still some vertex pipe features which are not supported, as ES3 didn't have them -- proper handling of noperspective, etc. Change-Id: Ia8e3c72af54c4d1cbcc18482a741daa5e8e7c053 Bug: b/120799499 Reviewed-on: https://swiftshader-review.googlesource.com/c/24376 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarChris Forbes <chrisforbes@google.com>
parent d5aed490
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "System/Timer.hpp" #include "System/Timer.hpp"
#include "Vulkan/VkDebug.hpp" #include "Vulkan/VkDebug.hpp"
#include "Pipeline/SpirvShader.hpp" #include "Pipeline/SpirvShader.hpp"
#include "Vertex.hpp"
#undef max #undef max
...@@ -1236,7 +1237,6 @@ namespace sw ...@@ -1236,7 +1237,6 @@ namespace sw
const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer; const SetupProcessor::RoutinePointer &setupRoutine = draw.setupPointer;
int ms = state.multiSample; int ms = state.multiSample;
int pos = state.positionRegister;
const DrawData *data = draw.data; const DrawData *data = draw.data;
int visible = 0; int visible = 0;
...@@ -1248,7 +1248,7 @@ namespace sw ...@@ -1248,7 +1248,7 @@ namespace sw
if((v0.clipFlags & v1.clipFlags & v2.clipFlags) == Clipper::CLIP_FINITE) if((v0.clipFlags & v1.clipFlags & v2.clipFlags) == Clipper::CLIP_FINITE)
{ {
Polygon polygon(&v0.v[pos], &v1.v[pos], &v2.v[pos]); Polygon polygon(&v0.builtins.position, &v1.builtins.position, &v2.builtins.position);
int clipFlagsOr = v0.clipFlags | v1.clipFlags | v2.clipFlags | draw.clipFlags; int clipFlagsOr = v0.clipFlags | v1.clipFlags | v2.clipFlags | draw.clipFlags;
...@@ -1332,10 +1332,8 @@ namespace sw ...@@ -1332,10 +1332,8 @@ namespace sw
Vertex &v0 = triangle.v0; Vertex &v0 = triangle.v0;
Vertex &v1 = triangle.v1; Vertex &v1 = triangle.v1;
int pos = state.positionRegister; const float4 &P0 = v0.builtins.position;
const float4 &P1 = v1.builtins.position;
const float4 &P0 = v0.v[pos];
const float4 &P1 = v1.v[pos];
if(P0.w <= 0 && P1.w <= 0) if(P0.w <= 0 && P1.w <= 0)
{ {
...@@ -1525,30 +1523,17 @@ namespace sw ...@@ -1525,30 +1523,17 @@ namespace sw
Vertex &v = triangle.v0; Vertex &v = triangle.v0;
float pSize; float pSize = v.builtins.pointSize;
int pts = state.pointSizeRegister;
if(state.pointSizeRegister != Unused)
{
pSize = v.v[pts].y;
}
else
{
pSize = 1.0f;
}
pSize = clamp(pSize, data.pointSizeMin, data.pointSizeMax); pSize = clamp(pSize, data.pointSizeMin, data.pointSizeMax);
float4 P[4]; float4 P[4];
int C[4]; int C[4];
int pos = state.positionRegister; P[0] = v.builtins.position;
P[1] = v.builtins.position;
P[0] = v.v[pos]; P[2] = v.builtins.position;
P[1] = v.v[pos]; P[3] = v.builtins.position;
P[2] = v.v[pos];
P[3] = v.v[pos];
const float X = pSize * P[0].w * data.halfPixelX[0]; const float X = pSize * P[0].w * data.halfPixelX[0];
const float Y = pSize * P[0].w * data.halfPixelY[0]; const float Y = pSize * P[0].w * data.halfPixelY[0];
...@@ -1572,8 +1557,8 @@ namespace sw ...@@ -1572,8 +1557,8 @@ namespace sw
triangle.v1 = triangle.v0; triangle.v1 = triangle.v0;
triangle.v2 = triangle.v0; triangle.v2 = triangle.v0;
triangle.v1.X += iround(16 * 0.5f * pSize); triangle.v1.projected.x += iround(16 * 0.5f * pSize);
triangle.v2.Y -= iround(16 * 0.5f * pSize) * (data.Hx16[0] > 0.0f ? 1 : -1); // Both Direct3D and OpenGL expect (0, 0) in the top-left corner triangle.v2.projected.y -= iround(16 * 0.5f * pSize) * (data.Hx16[0] > 0.0f ? 1 : -1); // Both Direct3D and OpenGL expect (0, 0) in the top-left corner
Polygon polygon(P, 4); Polygon polygon(P, 4);
......
...@@ -87,60 +87,16 @@ namespace sw ...@@ -87,60 +87,16 @@ namespace sw
state.slopeDepthBias = context->slopeDepthBias != 0.0f; state.slopeDepthBias = context->slopeDepthBias != 0.0f;
state.vFace = context->pixelShader && context->pixelShader->hasBuiltinInput(spv::BuiltInFrontFacing); state.vFace = context->pixelShader && context->pixelShader->hasBuiltinInput(spv::BuiltInFrontFacing);
state.positionRegister = Pos;
state.pointSizeRegister = Unused;
state.multiSample = context->getMultiSampleCount(); state.multiSample = context->getMultiSampleCount();
state.rasterizerDiscard = context->rasterizerDiscard; state.rasterizerDiscard = context->rasterizerDiscard;
//TODO: route properly for (int interpolant = 0; interpolant < MAX_INTERFACE_COMPONENTS; interpolant++)
state.positionRegister = 0;//context->vertexShader->getPositionRegister();
state.pointSizeRegister = 1;//context->vertexShader->getPointSizeRegister();
for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
{ {
for(int component = 0; component < 4; component++) state.gradient[interpolant] = context->pixelShader->inputs[interpolant];
{
state.gradient[interpolant][component].attribute = Unused;
state.gradient[interpolant][component].flat = false;
state.gradient[interpolant][component].wrap = false;
}
} }
const bool point = context->isDrawPoint(); const bool point = context->isDrawPoint();
// for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
// {
// for(int component = 0; component < 4; component++)
// {
// const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
//
// if(semantic.active())
// {
// int input = interpolant;
// for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
// {
// if(semantic == context->vertexShader->getOutput(i, component))
// {
// input = i;
// break;
// }
// }
//
// bool flat = point;
//
// switch(semantic.usage)
// {
// case Shader::USAGE_TEXCOORD: flat = false; break;
// case Shader::USAGE_COLOR: flat = semantic.flat || point; break;
// }
//
// state.gradient[interpolant][component].attribute = input;
// state.gradient[interpolant][component].flat = flat;
// }
// }
// }
state.hash = state.computeHash(); state.hash = state.computeHash();
return state; return state;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#ifndef sw_SetupProcessor_hpp #ifndef sw_SetupProcessor_hpp
#define sw_SetupProcessor_hpp #define sw_SetupProcessor_hpp
#include <Pipeline/SpirvShader.hpp>
#include "Context.hpp" #include "Context.hpp"
#include "RoutineCache.hpp" #include "RoutineCache.hpp"
#include "System/Types.hpp" #include "System/Types.hpp"
...@@ -41,8 +42,6 @@ namespace sw ...@@ -41,8 +42,6 @@ namespace sw
bool interpolateZ : 1; bool interpolateZ : 1;
bool interpolateW : 1; bool interpolateW : 1;
bool perspective : 1; bool perspective : 1;
unsigned int positionRegister : BITS(VERTEX_OUTPUT_LAST);
unsigned int pointSizeRegister : BITS(VERTEX_OUTPUT_LAST);
CullMode cullMode : BITS(CULL_LAST); CullMode cullMode : BITS(CULL_LAST);
bool twoSidedStencil : 1; bool twoSidedStencil : 1;
bool slopeDepthBias : 1; bool slopeDepthBias : 1;
...@@ -50,14 +49,7 @@ namespace sw ...@@ -50,14 +49,7 @@ namespace sw
unsigned int multiSample : 3; // 1, 2 or 4 unsigned int multiSample : 3; // 1, 2 or 4
bool rasterizerDiscard : 1; bool rasterizerDiscard : 1;
struct Gradient SpirvShader::InterfaceComponent gradient[MAX_INTERFACE_COMPONENTS];
{
unsigned char attribute : BITS(VERTEX_OUTPUT_LAST);
bool flat : 1;
bool wrap : 1;
};
Gradient gradient[MAX_FRAGMENT_INPUTS][4];
}; };
struct State : States struct State : States
......
...@@ -21,75 +21,25 @@ ...@@ -21,75 +21,25 @@
namespace sw namespace sw
{ {
enum Out ALIGN(16, struct Vertex
{
// Default vertex output semantics
Pos = 0,
C0 = 1, // Diffuse
C1 = 2, // Specular
T0 = 3,
T1 = 4,
T2 = 5,
T3 = 6,
T4 = 7,
T5 = 8,
T6 = 9,
T7 = 10,
Fog = 11, // x component
Pts = Fog, // y component
// Variable semantics
V0 = 0,
Vn_1 = MAX_VERTEX_OUTPUTS - 1,
Unused,
VERTEX_OUTPUT_LAST = Unused,
};
struct UVWQ
{ {
float u; float v[MAX_INTERFACE_COMPONENTS];
float v;
float w;
float q;
float &operator[](int i) struct
{ {
return (&u)[i]; float4 position;
} float pointSize;
}; } builtins;
struct
ALIGN(16, struct Vertex
{
union
{ {
struct // Fixed semantics int x;
{ int y;
// Position float z;
float x; float w;
float y; } projected;
float z;
float w;
float4 C[2]; // Diffuse and specular color
UVWQ T[8]; // Texture coordinates
float f; // Fog
float pSize; // Point size
};
float4 v[MAX_VERTEX_OUTPUTS]; // Generic components using semantic declaration
};
// Projected coordinates
int X;
int Y;
float Z;
float W;
int clipFlags; int clipFlags;
int padding[3]; int padding[2];
}); });
static_assert((sizeof(Vertex) & 0x0000000F) == 0, "Vertex size not a multiple of 16 bytes (alignment requirement)"); static_assert((sizeof(Vertex) & 0x0000000F) == 0, "Vertex size not a multiple of 16 bytes (alignment requirement)");
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <Device/Vertex.hpp>
#include "SetupRoutine.hpp" #include "SetupRoutine.hpp"
#include "Constants.hpp" #include "Constants.hpp"
...@@ -54,8 +55,6 @@ namespace sw ...@@ -54,8 +55,6 @@ namespace sw
const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0); const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0);
const int V2 = triangle ? OFFSET(Triangle,v2) : (line ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0)); const int V2 = triangle ? OFFSET(Triangle,v2) : (line ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0));
int pos = state.positionRegister;
Pointer<Byte> v0 = tri + V0; Pointer<Byte> v0 = tri + V0;
Pointer<Byte> v1 = tri + V1; Pointer<Byte> v1 = tri + V1;
Pointer<Byte> v2 = tri + V2; Pointer<Byte> v2 = tri + V2;
...@@ -63,13 +62,13 @@ namespace sw ...@@ -63,13 +62,13 @@ namespace sw
Array<Int> X(16); Array<Int> X(16);
Array<Int> Y(16); Array<Int> Y(16);
X[0] = *Pointer<Int>(v0 + OFFSET(Vertex,X)); X[0] = *Pointer<Int>(v0 + OFFSET(Vertex,projected.x));
X[1] = *Pointer<Int>(v1 + OFFSET(Vertex,X)); X[1] = *Pointer<Int>(v1 + OFFSET(Vertex,projected.x));
X[2] = *Pointer<Int>(v2 + OFFSET(Vertex,X)); X[2] = *Pointer<Int>(v2 + OFFSET(Vertex,projected.x));
Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex,Y)); Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex,projected.y));
Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex,Y)); Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex,projected.y));
Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex,Y)); Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex,projected.y));
Int d = 1; // Winding direction Int d = 1; // Winding direction
...@@ -91,9 +90,9 @@ namespace sw ...@@ -91,9 +90,9 @@ namespace sw
Return(false); Return(false);
} }
Int w0w1w2 = *Pointer<Int>(v0 + pos * 16 + 12) ^ Int w0w1w2 = *Pointer<Int>(v0 + OFFSET(Vertex, builtins.position.w)) ^
*Pointer<Int>(v1 + pos * 16 + 12) ^ *Pointer<Int>(v1 + OFFSET(Vertex, builtins.position.w)) ^
*Pointer<Int>(v2 + pos * 16 + 12); *Pointer<Int>(v2 + OFFSET(Vertex, builtins.position.w));
A = IfThenElse(w0w1w2 < 0, -A, A); A = IfThenElse(w0w1w2 < 0, -A, A);
...@@ -279,9 +278,9 @@ namespace sw ...@@ -279,9 +278,9 @@ namespace sw
// Sort by minimum y // Sort by minimum y
if(triangle) if(triangle)
{ {
Float y0 = *Pointer<Float>(v0 + pos * 16 + 4); Float y0 = *Pointer<Float>(v0 + OFFSET(Vertex, builtins.position.y));
Float y1 = *Pointer<Float>(v1 + pos * 16 + 4); Float y1 = *Pointer<Float>(v1 + OFFSET(Vertex, builtins.position.y));
Float y2 = *Pointer<Float>(v2 + pos * 16 + 4); Float y2 = *Pointer<Float>(v2 + OFFSET(Vertex, builtins.position.y));
Float yMin = Min(Min(y0, y1), y2); Float yMin = Min(Min(y0, y1), y2);
...@@ -292,9 +291,9 @@ namespace sw ...@@ -292,9 +291,9 @@ namespace sw
// Sort by maximum w // Sort by maximum w
if(triangle) if(triangle)
{ {
Float w0 = *Pointer<Float>(v0 + pos * 16 + 12); Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, builtins.position.w));
Float w1 = *Pointer<Float>(v1 + pos * 16 + 12); Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, builtins.position.w));
Float w2 = *Pointer<Float>(v2 + pos * 16 + 12); Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, builtins.position.w));
Float wMax = Max(Max(w0, w1), w2); Float wMax = Max(Max(w0, w1), w2);
...@@ -302,9 +301,9 @@ namespace sw ...@@ -302,9 +301,9 @@ namespace sw
conditionalRotate2(wMax == w2, v0, v1, v2); conditionalRotate2(wMax == w2, v0, v1, v2);
} }
Float w0 = *Pointer<Float>(v0 + pos * 16 + 12); Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, builtins.position.w));
Float w1 = *Pointer<Float>(v1 + pos * 16 + 12); Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, builtins.position.w));
Float w2 = *Pointer<Float>(v2 + pos * 16 + 12); Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, builtins.position.w));
Float4 w012; Float4 w012;
...@@ -313,15 +312,15 @@ namespace sw ...@@ -313,15 +312,15 @@ namespace sw
w012.z = w2; w012.z = w2;
w012.w = 1; w012.w = 1;
Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex,W)); Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex,projected.w));
Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex,X)); Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex,projected.x));
Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex,X)); Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex,projected.x));
Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex,X)); Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex,projected.x));
Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex,Y)); Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex,projected.y));
Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex,Y)); Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex,projected.y));
Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex,Y)); Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex,projected.y));
if(line) if(line)
{ {
...@@ -396,9 +395,9 @@ namespace sw ...@@ -396,9 +395,9 @@ namespace sw
if(state.interpolateZ) if(state.interpolateZ)
{ {
Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex,Z)); Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex,projected.z));
Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex,Z)); Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex,projected.z));
Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex,Z)); Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex,projected.z));
z1 -= z0; z1 -= z0;
z2 -= z0; z2 -= z0;
...@@ -451,19 +450,16 @@ namespace sw ...@@ -451,19 +450,16 @@ namespace sw
*Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) = C; *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) = C;
} }
for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) for (int interpolant = 0; interpolant < MAX_INTERFACE_COMPONENTS; interpolant++)
{ {
for(int component = 0; component < 4; component++) // TODO: fix point, perspective, etc. Not convinced various edge cases are really correct here for either VK or GL.
{ if (state.gradient[interpolant].Type != SpirvShader::ATTRIBTYPE_UNUSED)
int attribute = state.gradient[interpolant][component].attribute; setupGradient(primitive, tri, w012, M, v0, v1, v2,
bool flat = state.gradient[interpolant][component].flat; OFFSET(Vertex, v[interpolant]),
bool wrap = state.gradient[interpolant][component].wrap; OFFSET(Primitive, V[interpolant]),
state.gradient[interpolant].Flat,
if(attribute != Unused) point,
{ state.perspective, 0);
setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,v[attribute][component]), OFFSET(Primitive,V[interpolant][component]), flat, point, state.perspective, wrap, component);
}
}
} }
Return(true); Return(true);
...@@ -472,7 +468,7 @@ namespace sw ...@@ -472,7 +468,7 @@ namespace sw
routine = function("SetupRoutine"); routine = function("SetupRoutine");
} }
void SetupRoutine::setupGradient(Pointer<Byte> &primitive, Pointer<Byte> &triangle, Float4 &w012, Float4 (&m)[3], Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2, int attribute, int planeEquation, bool flat, bool sprite, bool perspective, bool wrap, int component) void SetupRoutine::setupGradient(Pointer<Byte> &primitive, Pointer<Byte> &triangle, Float4 &w012, Float4 (&m)[3], Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2, int attribute, int planeEquation, bool flat, bool sprite, bool perspective, int component)
{ {
Float4 i; Float4 i;
...@@ -505,21 +501,6 @@ namespace sw ...@@ -505,21 +501,6 @@ namespace sw
i.w = 0; i.w = 0;
} }
if(wrap)
{
Float m;
m = *Pointer<Float>(v0 + attribute);
m = Max(m, *Pointer<Float>(v1 + attribute));
m = Max(m, *Pointer<Float>(v2 + attribute));
m -= 0.5f;
// TODO: Vectorize
If(Float(i.x) < m) i.x = i.x + 1.0f;
If(Float(i.y) < m) i.y = i.y + 1.0f;
If(Float(i.z) < m) i.z = i.z + 1.0f;
}
if(!perspective) if(!perspective)
{ {
i *= w012; i *= w012;
......
...@@ -33,7 +33,7 @@ namespace sw ...@@ -33,7 +33,7 @@ namespace sw
Routine *getRoutine(); Routine *getRoutine();
private: private:
void setupGradient(Pointer<Byte> &primitive, Pointer<Byte> &triangle, Float4 &w012, Float4 (&m)[3], Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2, int attribute, int planeEquation, bool flatShading, bool sprite, bool perspective, bool wrap, int component); void setupGradient(Pointer<Byte> &primitive, Pointer<Byte> &triangle, Float4 &w012, Float4 (&m)[3], Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2, int attribute, int planeEquation, bool flatShading, bool sprite, bool perspective, int component);
void edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &Xa, const Int &Ya, const Int &Xb, const Int &Yb, Int &q); void edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &Xa, const Int &Ya, const Int &Xb, const Int &Yb, Int &q);
void conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2); void conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2);
void conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2); void conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2);
......
...@@ -32,11 +32,14 @@ namespace sw ...@@ -32,11 +32,14 @@ namespace sw
enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
// TODO: wire up builtins auto it = spirvShader->inputBuiltins.find(spv::BuiltInInstanceIndex);
//if(shader->isInstanceIdDeclared()) if (it != spirvShader->inputBuiltins.end())
//{ {
// instanceID = *Pointer<Int>(data + OFFSET(DrawData,instanceID)); // TODO: we could do better here; we know InstanceIndex is uniform across all lanes
//} assert(it->second.SizeInComponents == 1);
(*routine.lvalues[it->second.Id])[it->second.FirstComponent] =
As<Float4>(Int4((*Pointer<Int>(data + OFFSET(DrawData, instanceID)))));
}
} }
VertexProgram::~VertexProgram() VertexProgram::~VertexProgram()
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <Device/Vertex.hpp>
#include "VertexRoutine.hpp" #include "VertexRoutine.hpp"
#include "Constants.hpp" #include "Constants.hpp"
...@@ -94,14 +95,21 @@ namespace sw ...@@ -94,14 +95,21 @@ namespace sw
void VertexRoutine::computeClipFlags() void VertexRoutine::computeClipFlags()
{ {
int pos = state.positionRegister; auto it = spirvShader->outputBuiltins.find(spv::BuiltInPosition);
assert(it != spirvShader->outputBuiltins.end());
Int4 maxX = CmpLT(o[pos].w, o[pos].x); assert(it->second.SizeInComponents == 4);
Int4 maxY = CmpLT(o[pos].w, o[pos].y); auto &pos = (*routine.lvalues[it->second.Id]);
Int4 maxZ = CmpLT(o[pos].w, o[pos].z); auto posX = pos[it->second.FirstComponent];
Int4 minX = CmpNLE(-o[pos].w, o[pos].x); auto posY = pos[it->second.FirstComponent + 1];
Int4 minY = CmpNLE(-o[pos].w, o[pos].y); auto posZ = pos[it->second.FirstComponent + 2];
Int4 minZ = CmpNLE(Float4(0.0f), o[pos].z); auto posW = pos[it->second.FirstComponent + 3];
Int4 maxX = CmpLT(posW, posX);
Int4 maxY = CmpLT(posW, posY);
Int4 maxZ = CmpLT(posW, posZ);
Int4 minX = CmpNLE(-posW, posX);
Int4 minY = CmpNLE(-posW, posY);
Int4 minZ = CmpNLE(Float4(0.0f), posZ);
clipFlags = *Pointer<Int>(constants + OFFSET(Constants,maxX) + SignMask(maxX) * 4); // FIXME: Array indexing 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,maxY) + SignMask(maxY) * 4);
...@@ -110,9 +118,9 @@ namespace sw ...@@ -110,9 +118,9 @@ namespace sw
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minY) + SignMask(minY) * 4); clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minY) + SignMask(minY) * 4);
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minZ) + SignMask(minZ) * 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 finiteX = CmpLE(Abs(posX), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
Int4 finiteY = CmpLE(Abs(o[pos].y), *Pointer<Float4>(constants + OFFSET(Constants,maxPos))); Int4 finiteY = CmpLE(Abs(posY), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
Int4 finiteZ = CmpLE(Abs(o[pos].z), *Pointer<Float4>(constants + OFFSET(Constants,maxPos))); Int4 finiteZ = CmpLE(Abs(posZ), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
Int4 finiteXYZ = finiteX & finiteY & finiteZ; Int4 finiteXYZ = finiteX & finiteY & finiteZ;
clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,fini) + SignMask(finiteXYZ) * 4); clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,fini) + SignMask(finiteXYZ) * 4);
...@@ -658,12 +666,28 @@ namespace sw ...@@ -658,12 +666,28 @@ namespace sw
*Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 3) = (clipFlags >> 24) & 0x0000000FF; *Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 3) = (clipFlags >> 24) & 0x0000000FF;
// Viewport transform // Viewport transform
int pos = state.positionRegister; auto it = spirvShader->outputBuiltins.find(spv::BuiltInPosition);
assert(it != spirvShader->outputBuiltins.end());
v.x = o[pos].x; assert(it->second.SizeInComponents == 4);
v.y = o[pos].y; auto &pos = (*routine.lvalues[it->second.Id]);
v.z = o[pos].z; auto posX = pos[it->second.FirstComponent];
v.w = o[pos].w; auto posY = pos[it->second.FirstComponent + 1];
auto posZ = pos[it->second.FirstComponent + 2];
auto posW = pos[it->second.FirstComponent + 3];
v.x = posX;
v.y = posY;
v.z = posZ;
v.w = posW;
// Write the builtin pos into the vertex; it's not going to be consumed by the FS, but may need to reproject if we have to clip.
Vector4f v2 = v;
transpose4x4(v2.x, v2.y, v2.z, v2.w);
*Pointer<Float4>(cacheLine + OFFSET(Vertex,builtins.position) + sizeof(Vertex) * 0, 16) = v2.x;
*Pointer<Float4>(cacheLine + OFFSET(Vertex,builtins.position) + sizeof(Vertex) * 1, 16) = v2.y;
*Pointer<Float4>(cacheLine + OFFSET(Vertex,builtins.position) + sizeof(Vertex) * 2, 16) = v2.z;
*Pointer<Float4>(cacheLine + OFFSET(Vertex,builtins.position) + sizeof(Vertex) * 3, 16) = v2.w;
Float4 w = As<Float4>(As<Int4>(v.w) | (As<Int4>(CmpEQ(v.w, Float4(0.0f))) & As<Int4>(Float4(1.0f)))); 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; Float4 rhw = Float4(1.0f) / w;
...@@ -675,23 +699,26 @@ namespace sw ...@@ -675,23 +699,26 @@ namespace sw
transpose4x4(v.x, v.y, v.z, v.w); transpose4x4(v.x, v.y, v.z, v.w);
*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 0, 16) = v.x; *Pointer<Float4>(cacheLine + OFFSET(Vertex,projected) + sizeof(Vertex) * 0, 16) = v.x;
*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 1, 16) = v.y; *Pointer<Float4>(cacheLine + OFFSET(Vertex,projected) + sizeof(Vertex) * 1, 16) = v.y;
*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 2, 16) = v.z; *Pointer<Float4>(cacheLine + OFFSET(Vertex,projected) + sizeof(Vertex) * 2, 16) = v.z;
*Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 3, 16) = v.w; *Pointer<Float4>(cacheLine + OFFSET(Vertex,projected) + sizeof(Vertex) * 3, 16) = v.w;
} }
void VertexRoutine::writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cache) void VertexRoutine::writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cache)
{ {
for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++) for(int i = 0; i < MAX_INTERFACE_COMPONENTS; i++)
{ {
if(state.output[i].write) if(spirvShader->outputs[i].Type != SpirvShader::ATTRIBTYPE_UNUSED)
{ {
*Pointer<Int4>(vertex + OFFSET(Vertex,v[i]), 16) = *Pointer<Int4>(cache + OFFSET(Vertex,v[i]), 16); *Pointer<Int>(vertex + OFFSET(Vertex, v[i]), 4) = *Pointer<Int>(cache + OFFSET(Vertex, v[i]), 4);
} }
} }
*Pointer<Int4>(vertex + OFFSET(Vertex,X)) = *Pointer<Int4>(cache + OFFSET(Vertex,X)); *Pointer<Int4>(vertex + OFFSET(Vertex,projected)) = *Pointer<Int4>(cache + OFFSET(Vertex,projected));
*Pointer<Int>(vertex + OFFSET(Vertex,clipFlags)) = *Pointer<Int>(cache + OFFSET(Vertex,clipFlags)); *Pointer<Int>(vertex + OFFSET(Vertex,clipFlags)) = *Pointer<Int>(cache + OFFSET(Vertex,clipFlags));
*Pointer<Int4>(vertex + OFFSET(Vertex,builtins.position)) = *Pointer<Int4>(cache + OFFSET(Vertex,builtins.position));
*Pointer<Int>(vertex + OFFSET(Vertex,builtins.pointSize)) = *Pointer<Int>(cache + OFFSET(Vertex,builtins.pointSize));
} }
} }
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