Commit 5bff4059 by Nicolas Capens Committed by Nicolas Capens

Implement gather/scatter operations for shader register files.

This allows to address the registers with a vector of indices. Also rename 'dynamic' register files to 'indirect addressable', to disambiguate from 'dynamic indexing' at the shader level. Indexing with a uniform does not require gather/scatter operations, but does require indirect addressing. Bug chromium:845103 Bug skia:7846 Change-Id: I3c42be33def66328688f2900c61c80246bf1e584 Reviewed-on: https://swiftshader-review.googlesource.com/18989Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent ac3f2fac
...@@ -24,7 +24,7 @@ namespace sw ...@@ -24,7 +24,7 @@ namespace sw
{ {
public: public:
PixelProgram(const PixelProcessor::State &state, const PixelShader *shader) : PixelProgram(const PixelProcessor::State &state, const PixelShader *shader) :
PixelRoutine(state, shader), r(shader->dynamicallyIndexedTemporaries), PixelRoutine(state, shader), r(shader->indirectAddressableTemporaries),
loopDepth(-1), ifDepth(0), loopRepDepth(0), currentLabel(-1), whileTest(false) loopDepth(-1), ifDepth(0), loopRepDepth(0), currentLabel(-1), whileTest(false)
{ {
for(int i = 0; i < 2048; ++i) for(int i = 0; i < 2048; ++i)
......
...@@ -29,7 +29,8 @@ namespace sw ...@@ -29,7 +29,8 @@ namespace sw
extern bool exactColorRounding; extern bool exactColorRounding;
extern bool forceClearRegisters; extern bool forceClearRegisters;
PixelRoutine::PixelRoutine(const PixelProcessor::State &state, const PixelShader *shader) : QuadRasterizer(state, shader), v(shader && shader->dynamicallyIndexedInput) PixelRoutine::PixelRoutine(const PixelProcessor::State &state, const PixelShader *shader)
: QuadRasterizer(state, shader), v(shader && shader->indirectAddressableInput)
{ {
if(!shader || shader->getShaderModel() < 0x0200 || forceClearRegisters) if(!shader || shader->getShaderModel() < 0x0200 || forceClearRegisters)
{ {
......
...@@ -160,7 +160,7 @@ namespace sw ...@@ -160,7 +160,7 @@ namespace sw
analyzeDynamicBranching(); analyzeDynamicBranching();
analyzeSamplers(); analyzeSamplers();
analyzeCallSites(); analyzeCallSites();
analyzeDynamicIndexing(); analyzeIndirectAddressing();
} }
void PixelShader::analyzeZOverride() void PixelShader::analyzeZOverride()
......
...@@ -1890,40 +1890,34 @@ namespace sw ...@@ -1890,40 +1890,34 @@ namespace sw
} }
} }
void Shader::analyzeDynamicIndexing() void Shader::analyzeIndirectAddressing()
{ {
dynamicallyIndexedTemporaries = false; indirectAddressableTemporaries = false;
dynamicallyIndexedInput = false; indirectAddressableInput = false;
dynamicallyIndexedOutput = false; indirectAddressableOutput = false;
for(const auto &inst : instruction) for(const auto &inst : instruction)
{ {
if(inst->dst.rel.type == PARAMETER_ADDR || if(inst->dst.rel.type != PARAMETER_VOID)
inst->dst.rel.type == PARAMETER_LOOP ||
inst->dst.rel.type == PARAMETER_TEMP ||
inst->dst.rel.type == PARAMETER_CONST)
{ {
switch(inst->dst.type) switch(inst->dst.type)
{ {
case PARAMETER_TEMP: dynamicallyIndexedTemporaries = true; break; case PARAMETER_TEMP: indirectAddressableTemporaries = true; break;
case PARAMETER_INPUT: dynamicallyIndexedInput = true; break; case PARAMETER_INPUT: indirectAddressableInput = true; break;
case PARAMETER_OUTPUT: dynamicallyIndexedOutput = true; break; case PARAMETER_OUTPUT: indirectAddressableOutput = true; break;
default: break; default: break;
} }
} }
for(int j = 0; j < 3; j++) for(int j = 0; j < 3; j++)
{ {
if(inst->src[j].rel.type == PARAMETER_ADDR || if(inst->src[j].rel.type != PARAMETER_VOID)
inst->src[j].rel.type == PARAMETER_LOOP ||
inst->src[j].rel.type == PARAMETER_TEMP ||
inst->src[j].rel.type == PARAMETER_CONST)
{ {
switch(inst->src[j].type) switch(inst->src[j].type)
{ {
case PARAMETER_TEMP: dynamicallyIndexedTemporaries = true; break; case PARAMETER_TEMP: indirectAddressableTemporaries = true; break;
case PARAMETER_INPUT: dynamicallyIndexedInput = true; break; case PARAMETER_INPUT: indirectAddressableInput = true; break;
case PARAMETER_OUTPUT: dynamicallyIndexedOutput = true; break; case PARAMETER_OUTPUT: indirectAddressableOutput = true; break;
default: break; default: break;
} }
} }
......
...@@ -612,9 +612,9 @@ namespace sw ...@@ -612,9 +612,9 @@ namespace sw
unsigned int dirtyConstantsI; unsigned int dirtyConstantsI;
unsigned int dirtyConstantsB; unsigned int dirtyConstantsB;
bool dynamicallyIndexedTemporaries; bool indirectAddressableTemporaries;
bool dynamicallyIndexedInput; bool indirectAddressableInput;
bool dynamicallyIndexedOutput; bool indirectAddressableOutput;
protected: protected:
void parse(const unsigned long *token); void parse(const unsigned long *token);
...@@ -627,7 +627,7 @@ namespace sw ...@@ -627,7 +627,7 @@ namespace sw
void analyzeDynamicBranching(); void analyzeDynamicBranching();
void analyzeSamplers(); void analyzeSamplers();
void analyzeCallSites(); void analyzeCallSites();
void analyzeDynamicIndexing(); void analyzeIndirectAddressing();
void markFunctionAnalysis(unsigned int functionLabel, Analysis flag); void markFunctionAnalysis(unsigned int functionLabel, Analysis flag);
ShaderType shaderType; ShaderType shaderType;
......
...@@ -560,6 +560,100 @@ namespace sw ...@@ -560,6 +560,100 @@ namespace sw
} }
} }
const Vector4f RegisterFile::operator[](RValue<Int4> index)
{
ASSERT(indirectAddressable);
Int index0 = Extract(index, 0);
Int index1 = Extract(index, 1);
Int index2 = Extract(index, 2);
Int index3 = Extract(index, 3);
Vector4f r;
r.x.x = Extract(x[0][index0], 0);
r.x.y = Extract(x[0][index1], 1);
r.x.z = Extract(x[0][index2], 2);
r.x.w = Extract(x[0][index3], 3);
r.y.x = Extract(y[0][index0], 0);
r.y.y = Extract(y[0][index1], 1);
r.y.z = Extract(y[0][index2], 2);
r.y.w = Extract(y[0][index3], 3);
r.z.x = Extract(z[0][index0], 0);
r.z.y = Extract(z[0][index1], 1);
r.z.z = Extract(z[0][index2], 2);
r.z.w = Extract(z[0][index3], 3);
r.w.x = Extract(w[0][index0], 0);
r.w.y = Extract(w[0][index1], 1);
r.w.z = Extract(w[0][index2], 2);
r.w.w = Extract(w[0][index3], 3);
return r;
}
void RegisterFile::scatter_x(Int4 index, RValue<Float4> r)
{
ASSERT(indirectAddressable);
Int index0 = Extract(index, 0);
Int index1 = Extract(index, 1);
Int index2 = Extract(index, 2);
Int index3 = Extract(index, 3);
x[0][index0] = Insert(x[0][index0], Extract(r, 0), 0);
x[0][index1] = Insert(x[0][index1], Extract(r, 1), 1);
x[0][index2] = Insert(x[0][index2], Extract(r, 2), 2);
x[0][index3] = Insert(x[0][index3], Extract(r, 3), 3);
}
void RegisterFile::scatter_y(Int4 index, RValue<Float4> r)
{
ASSERT(indirectAddressable);
Int index0 = Extract(index, 0);
Int index1 = Extract(index, 1);
Int index2 = Extract(index, 2);
Int index3 = Extract(index, 3);
y[0][index0] = Insert(y[0][index0], Extract(r, 0), 0);
y[0][index1] = Insert(y[0][index1], Extract(r, 1), 1);
y[0][index2] = Insert(y[0][index2], Extract(r, 2), 2);
y[0][index3] = Insert(y[0][index3], Extract(r, 3), 3);
}
void RegisterFile::scatter_z(Int4 index, RValue<Float4> r)
{
ASSERT(indirectAddressable);
Int index0 = Extract(index, 0);
Int index1 = Extract(index, 1);
Int index2 = Extract(index, 2);
Int index3 = Extract(index, 3);
z[0][index0] = Insert(z[0][index0], Extract(r, 0), 0);
z[0][index1] = Insert(z[0][index1], Extract(r, 1), 1);
z[0][index2] = Insert(z[0][index2], Extract(r, 2), 2);
z[0][index3] = Insert(z[0][index3], Extract(r, 3), 3);
}
void RegisterFile::scatter_w(Int4 index, RValue<Float4> r)
{
ASSERT(indirectAddressable);
Int index0 = Extract(index, 0);
Int index1 = Extract(index, 1);
Int index2 = Extract(index, 2);
Int index3 = Extract(index, 3);
w[0][index0] = Insert(w[0][index0], Extract(r, 0), 0);
w[0][index1] = Insert(w[0][index1], Extract(r, 1), 1);
w[0][index2] = Insert(w[0][index2], Extract(r, 2), 2);
w[0][index3] = Insert(w[0][index3], Extract(r, 3), 3);
}
void ShaderCore::mov(Vector4f &dst, const Vector4f &src, bool integerDestination) void ShaderCore::mov(Vector4f &dst, const Vector4f &src, bool integerDestination)
{ {
if(integerDestination) if(integerDestination)
......
...@@ -147,31 +147,30 @@ namespace sw ...@@ -147,31 +147,30 @@ namespace sw
Reference<Float4> w; Reference<Float4> w;
}; };
template<int S, bool D = false> class RegisterFile
class RegisterArray
{ {
public: public:
RegisterArray(bool dynamic = D) : dynamic(dynamic) RegisterFile(int size, bool indirectAddressable) : size(size), indirectAddressable(indirectAddressable)
{ {
if(dynamic) if(indirectAddressable)
{ {
x = new Array<Float4>(S); x = new Array<Float4>(size);
y = new Array<Float4>(S); y = new Array<Float4>(size);
z = new Array<Float4>(S); z = new Array<Float4>(size);
w = new Array<Float4>(S); w = new Array<Float4>(size);
} }
else else
{ {
x = new Array<Float4>[S]; x = new Array<Float4>[size];
y = new Array<Float4>[S]; y = new Array<Float4>[size];
z = new Array<Float4>[S]; z = new Array<Float4>[size];
w = new Array<Float4>[S]; w = new Array<Float4>[size];
} }
} }
~RegisterArray() ~RegisterFile()
{ {
if(dynamic) if(indirectAddressable)
{ {
delete x; delete x;
delete y; delete y;
...@@ -189,7 +188,7 @@ namespace sw ...@@ -189,7 +188,7 @@ namespace sw
Register operator[](int i) Register operator[](int i)
{ {
if(dynamic) if(indirectAddressable)
{ {
return Register(x[0][i], y[0][i], z[0][i], w[0][i]); return Register(x[0][i], y[0][i], z[0][i], w[0][i]);
} }
...@@ -201,19 +200,36 @@ namespace sw ...@@ -201,19 +200,36 @@ namespace sw
Register operator[](RValue<Int> i) Register operator[](RValue<Int> i)
{ {
ASSERT(dynamic); ASSERT(indirectAddressable);
return Register(x[0][i], y[0][i], z[0][i], w[0][i]); return Register(x[0][i], y[0][i], z[0][i], w[0][i]);
} }
private: const Vector4f operator[](RValue<Int4> i); // Gather operation (read only).
const bool dynamic;
void scatter_x(Int4 i, RValue<Float4> r);
void scatter_y(Int4 i, RValue<Float4> r);
void scatter_z(Int4 i, RValue<Float4> r);
void scatter_w(Int4 i, RValue<Float4> r);
protected:
const int size;
const bool indirectAddressable;
Array<Float4> *x; Array<Float4> *x;
Array<Float4> *y; Array<Float4> *y;
Array<Float4> *z; Array<Float4> *z;
Array<Float4> *w; Array<Float4> *w;
}; };
template<int S, bool I = false>
class RegisterArray : public RegisterFile
{
public:
RegisterArray(bool indirectAddressable = I) : RegisterFile(S, indirectAddressable)
{
}
};
class ShaderCore class ShaderCore
{ {
typedef Shader::Control Control; typedef Shader::Control Control;
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
namespace sw namespace sw
{ {
VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader) VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader)
: VertexRoutine(state, shader), shader(shader), r(shader->dynamicallyIndexedTemporaries) : VertexRoutine(state, shader), shader(shader), r(shader->indirectAddressableTemporaries)
{ {
ifDepth = 0; ifDepth = 0;
loopRepDepth = 0; loopRepDepth = 0;
......
...@@ -27,8 +27,8 @@ namespace sw ...@@ -27,8 +27,8 @@ namespace sw
extern bool symmetricNormalizedDepth; // [-1, 1] instead of [0, 1] extern bool symmetricNormalizedDepth; // [-1, 1] instead of [0, 1]
VertexRoutine::VertexRoutine(const VertexProcessor::State &state, const VertexShader *shader) VertexRoutine::VertexRoutine(const VertexProcessor::State &state, const VertexShader *shader)
: v(shader && shader->dynamicallyIndexedInput), : v(shader && shader->indirectAddressableInput),
o(shader && shader->dynamicallyIndexedOutput), o(shader && shader->indirectAddressableOutput),
state(state) state(state)
{ {
} }
......
...@@ -176,7 +176,7 @@ namespace sw ...@@ -176,7 +176,7 @@ namespace sw
setOutput(posReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0)); setOutput(posReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0));
positionRegister = posReg; positionRegister = posReg;
} }
void VertexShader::setPointSizeRegister(int ptSizeReg) void VertexShader::setPointSizeRegister(int ptSizeReg)
{ {
setOutput(ptSizeReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0)); setOutput(ptSizeReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0));
...@@ -207,7 +207,7 @@ namespace sw ...@@ -207,7 +207,7 @@ namespace sw
analyzeDynamicBranching(); analyzeDynamicBranching();
analyzeSamplers(); analyzeSamplers();
analyzeCallSites(); analyzeCallSites();
analyzeDynamicIndexing(); analyzeIndirectAddressing();
} }
void VertexShader::analyzeInput() void VertexShader::analyzeInput()
......
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