Commit 2f4b603e by Nicolas Capens Committed by Nicolas Capens

Only store component count in Operand

The Operand class is a low-level abstraction of rvalues and constants. It should not carry the SPIR-V type ID. We only need the size in components. Bug: b/129000021 Change-Id: I6cb3ed6341b1ccf5ef759075d7410ba447617c8b Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/43693 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent ff9f9b5d
......@@ -795,7 +795,7 @@ SpirvShader::Object &SpirvShader::CreateConstant(InsnIterator insn)
auto &objectTy = getType(typeId);
object.kind = Object::Kind::Constant;
object.definition = insn;
object.constantValue = std::unique_ptr<uint32_t[]>(new uint32_t[objectTy.componentCount]);
object.constantValue.resize(objectTy.componentCount);
return object;
}
......@@ -2138,7 +2138,7 @@ SpirvShader::EmitResult SpirvShader::EmitSelect(InsnIterator insn, EmitState *st
auto &type = getType(insn.resultTypeId());
auto &dst = state->createIntermediate(insn.resultId(), type.componentCount);
auto cond = Operand(this, state, insn.word(3));
auto condIsScalar = (getType(cond).componentCount == 1);
auto condIsScalar = (cond.componentCount == 1);
auto lhs = Operand(this, state, insn.word(4));
auto rhs = Operand(this, state, insn.word(5));
......@@ -2419,11 +2419,18 @@ VkShaderStageFlagBits SpirvShader::executionModelToStage(spv::ExecutionModel mod
}
}
SpirvShader::Operand::Operand(SpirvShader const *shader, EmitState const *state, SpirvShader::Object::ID objId)
: obj(shader->getObject(objId))
, intermediate(obj.kind == SpirvShader::Object::Kind::Intermediate ? &state->getIntermediate(objId) : nullptr)
SpirvShader::Operand::Operand(const SpirvShader *shader, const EmitState *state, SpirvShader::Object::ID objectId)
: Operand(state, shader->getObject(objectId))
{}
SpirvShader::Operand::Operand(const EmitState *state, const Object &object)
: constant(object.constantValue.data())
, intermediate(object.kind == SpirvShader::Object::Kind::Intermediate ? &state->getIntermediate(object.id()) : nullptr)
, componentCount(intermediate ? intermediate->componentCount : object.constantValue.size())
{
ASSERT(intermediate || (object.kind == SpirvShader::Object::Kind::Constant));
}
SpirvRoutine::SpirvRoutine(vk::PipelineLayout const *pipelineLayout)
: pipelineLayout(pipelineLayout)
{
......
......@@ -72,10 +72,10 @@ class Intermediate
{
public:
Intermediate(uint32_t componentCount)
: scalar(new rr::Value *[componentCount])
, componentCount(componentCount)
: componentCount(componentCount)
, scalar(new rr::Value *[componentCount])
{
memset(scalar, 0, sizeof(rr::Value *) * componentCount);
for(auto i = 0u; i < componentCount; i++) { scalar[i] = nullptr; }
}
~Intermediate()
......@@ -119,6 +119,8 @@ public:
Intermediate &operator=(Intermediate const &) = delete;
Intermediate &operator=(Intermediate &&) = delete;
const uint32_t componentCount;
private:
void emplace(uint32_t i, rr::Value *value)
{
......@@ -128,7 +130,6 @@ private:
}
rr::Value **const scalar;
uint32_t componentCount;
};
class SpirvShader
......@@ -276,7 +277,7 @@ public:
Object::ID id() const { return definition.resultId(); }
InsnIterator definition;
std::unique_ptr<uint32_t[]> constantValue = nullptr;
std::vector<uint32_t> constantValue;
enum class Kind
{
......@@ -989,11 +990,8 @@ private:
// significantly different based on whether the value is uniform across lanes.
class Operand
{
SpirvShader::Object const &obj;
Intermediate const *intermediate;
public:
Operand(SpirvShader const *shader, EmitState const *state, SpirvShader::Object::ID objId);
Operand(const SpirvShader *shader, const EmitState *state, SpirvShader::Object::ID objectId);
RValue<SIMD::Float> Float(uint32_t i) const
{
......@@ -1005,9 +1003,7 @@ private:
// Constructing a constant SIMD::Float is not guaranteed to preserve the data's exact
// bit pattern, but SPIR-V provides 32-bit words representing "the bit pattern for the constant".
// Thus we must first construct an integer constant, and bitcast to float.
ASSERT(obj.kind == SpirvShader::Object::Kind::Constant);
auto constantValue = reinterpret_cast<uint32_t *>(obj.constantValue.get());
return As<SIMD::Float>(SIMD::UInt(constantValue[i]));
return As<SIMD::Float>(SIMD::UInt(constant[i]));
}
RValue<SIMD::Int> Int(uint32_t i) const
......@@ -1016,9 +1012,8 @@ private:
{
return intermediate->Int(i);
}
ASSERT(obj.kind == SpirvShader::Object::Kind::Constant);
auto constantValue = reinterpret_cast<int *>(obj.constantValue.get());
return SIMD::Int(constantValue[i]);
return SIMD::Int(constant[i]);
}
RValue<SIMD::UInt> UInt(uint32_t i) const
......@@ -1027,15 +1022,19 @@ private:
{
return intermediate->UInt(i);
}
ASSERT(obj.kind == SpirvShader::Object::Kind::Constant);
auto constantValue = reinterpret_cast<uint32_t *>(obj.constantValue.get());
return SIMD::UInt(constantValue[i]);
}
Type::ID typeId() const
{
return obj.typeId();
return SIMD::UInt(constant[i]);
}
private:
// Delegate constructor
Operand(const EmitState *state, const Object &object);
const uint32_t *constant;
const Intermediate *intermediate;
public:
const uint32_t componentCount;
};
Type const &getType(Type::ID id) const
......@@ -1050,11 +1049,6 @@ private:
return getType(object.typeId());
}
Type const &getType(const Operand &operand) const
{
return getType(operand.typeId());
}
Object const &getObject(Object::ID id) const
{
auto it = defs.find(id);
......
......@@ -41,12 +41,11 @@ SpirvShader::EmitResult SpirvShader::EmitMatrixTimesVector(InsnIterator insn, Em
auto &dst = state->createIntermediate(insn.resultId(), type.componentCount);
auto lhs = Operand(this, state, insn.word(3));
auto rhs = Operand(this, state, insn.word(4));
auto rhsType = getType(rhs);
for(auto i = 0u; i < type.componentCount; i++)
{
SIMD::Float v = lhs.Float(i) * rhs.Float(0);
for(auto j = 1u; j < rhsType.componentCount; j++)
for(auto j = 1u; j < rhs.componentCount; j++)
{
v += lhs.Float(i + type.componentCount * j) * rhs.Float(j);
}
......@@ -62,14 +61,13 @@ SpirvShader::EmitResult SpirvShader::EmitVectorTimesMatrix(InsnIterator insn, Em
auto &dst = state->createIntermediate(insn.resultId(), type.componentCount);
auto lhs = Operand(this, state, insn.word(3));
auto rhs = Operand(this, state, insn.word(4));
auto lhsType = getType(lhs);
for(auto i = 0u; i < type.componentCount; i++)
{
SIMD::Float v = lhs.Float(0) * rhs.Float(i * lhsType.componentCount);
for(auto j = 1u; j < lhsType.componentCount; j++)
SIMD::Float v = lhs.Float(0) * rhs.Float(i * lhs.componentCount);
for(auto j = 1u; j < lhs.componentCount; j++)
{
v += lhs.Float(j) * rhs.Float(i * lhsType.componentCount + j);
v += lhs.Float(j) * rhs.Float(i * lhs.componentCount + j);
}
dst.move(i, v);
}
......@@ -110,17 +108,9 @@ SpirvShader::EmitResult SpirvShader::EmitOuterProduct(InsnIterator insn, EmitSta
auto &dst = state->createIntermediate(insn.resultId(), type.componentCount);
auto lhs = Operand(this, state, insn.word(3));
auto rhs = Operand(this, state, insn.word(4));
auto &lhsType = getType(lhs);
auto &rhsType = getType(rhs);
ASSERT(type.definition.opcode() == spv::OpTypeMatrix);
ASSERT(lhsType.definition.opcode() == spv::OpTypeVector);
ASSERT(rhsType.definition.opcode() == spv::OpTypeVector);
ASSERT(getType(lhsType.element).opcode() == spv::OpTypeFloat);
ASSERT(getType(rhsType.element).opcode() == spv::OpTypeFloat);
auto numRows = lhsType.definition.word(3);
auto numCols = rhsType.definition.word(3);
auto numRows = lhs.componentCount;
auto numCols = rhs.componentCount;
for(auto col = 0u; col < numCols; col++)
{
......
......@@ -496,7 +496,7 @@ SpirvShader::EmitResult SpirvShader::EmitBranchConditional(InsnIterator insn, Em
auto falseBlockId = Block::ID(block.branchInstruction.word(3));
auto cond = Operand(this, state, condId);
ASSERT_MSG(getType(cond).componentCount == 1, "Condition must be a Boolean type scalar");
ASSERT_MSG(getType(getObject(condId)).componentCount == 1, "Condition must be a Boolean type scalar");
// TODO: Optimize for case where all lanes take same path.
......@@ -515,7 +515,7 @@ SpirvShader::EmitResult SpirvShader::EmitSwitch(InsnIterator insn, EmitState *st
auto selId = Object::ID(block.branchInstruction.word(1));
auto sel = Operand(this, state, selId);
ASSERT_MSG(getType(sel).componentCount == 1, "Selector must be a scalar");
ASSERT_MSG(sel.componentCount == 1, "Selector must be a scalar");
auto numCases = (block.branchInstruction.wordCount() - 3) / 2;
......
......@@ -1153,11 +1153,12 @@ void SpirvShader::Impl::Debugger::exposeVariable(
EmitState *state,
int wordOffset /* = 0 */) const
{
auto &obj = shader->getObject(id);
if(type != nullptr)
{
if(auto ty = debug::cast<debug::BasicType>(type))
{
auto &obj = shader->getObject(id);
SIMD::Int val;
switch(obj.kind)
{
......@@ -1288,7 +1289,7 @@ void SpirvShader::Impl::Debugger::exposeVariable(
// No debug type information. Derive from SPIR-V.
Operand val(shader, state, id);
switch(shader->getType(val).opcode())
switch(shader->getType(obj).opcode())
{
case spv::OpTypeInt:
{
......@@ -1302,7 +1303,7 @@ void SpirvShader::Impl::Debugger::exposeVariable(
break;
case spv::OpTypeVector:
{
auto count = shader->getType(val).definition.word(3);
auto count = shader->getType(obj).definition.word(3);
switch(count)
{
case 1:
......
......@@ -338,12 +338,11 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
{
auto p0 = Operand(this, state, insn.word(5));
auto p1 = Operand(this, state, insn.word(6));
auto p0Type = getType(p0);
// sqrt(dot(p0-p1, p0-p1))
SIMD::Float d = (p0.Float(0) - p1.Float(0)) * (p0.Float(0) - p1.Float(0));
for(auto i = 1u; i < p0Type.componentCount; i++)
for(auto i = 1u; i < p0.componentCount; i++)
{
d += (p0.Float(i) - p1.Float(i)) * (p0.Float(i) - p1.Float(i));
}
......@@ -378,14 +377,13 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
case GLSLstd450ModfStruct:
{
auto val = Operand(this, state, insn.word(5));
auto valTy = getType(val);
for(auto i = 0u; i < valTy.componentCount; i++)
for(auto i = 0u; i < val.componentCount; i++)
{
SIMD::Float whole, frac;
std::tie(whole, frac) = Modf(val.Float(i));
dst.move(i, frac);
dst.move(i + valTy.componentCount, whole);
dst.move(i + val.componentCount, whole);
}
break;
}
......@@ -527,12 +525,12 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
case GLSLstd450FrexpStruct:
{
auto val = Operand(this, state, insn.word(5));
auto numComponents = getType(val).componentCount;
for(auto i = 0u; i < numComponents; i++)
for(auto i = 0u; i < val.componentCount; i++)
{
auto significandAndExponent = Frexp(val.Float(i));
dst.move(i, significandAndExponent.first);
dst.move(i + numComponents, significandAndExponent.second);
dst.move(val.componentCount + i, significandAndExponent.second);
}
break;
}
......@@ -785,8 +783,8 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
case GLSLstd450Determinant:
{
auto mat = Operand(this, state, insn.word(5));
auto numComponents = getType(mat).componentCount;
switch(numComponents)
switch(mat.componentCount)
{
case 4: // 2x2
dst.move(0, Determinant(
......@@ -807,15 +805,15 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
mat.Float(12), mat.Float(13), mat.Float(14), mat.Float(15)));
break;
default:
UNREACHABLE("GLSLstd450Determinant can only operate with square matrices. Got %d elements", int(numComponents));
UNREACHABLE("GLSLstd450Determinant can only operate with square matrices. Got %d elements", int(mat.componentCount));
}
break;
}
case GLSLstd450MatrixInverse:
{
auto mat = Operand(this, state, insn.word(5));
auto numComponents = getType(mat).componentCount;
switch(numComponents)
switch(mat.componentCount)
{
case 4: // 2x2
{
......@@ -854,7 +852,7 @@ SpirvShader::EmitResult SpirvShader::EmitExtGLSLstd450(InsnIterator insn, EmitSt
break;
}
default:
UNREACHABLE("GLSLstd450MatrixInverse can only operate with square matrices. Got %d elements", int(numComponents));
UNREACHABLE("GLSLstd450MatrixInverse can only operate with square matrices. Got %d elements", int(mat.componentCount));
}
break;
}
......
......@@ -119,7 +119,6 @@ SpirvShader::EmitResult SpirvShader::EmitImageSample(ImageInstruction instructio
auto samplerDescriptor = (sampledImage.opcode() == spv::OpSampledImage) ? state->getPointer(sampledImage.definition.word(4)).base : imageDescriptor;
auto coordinate = Operand(this, state, coordinateId);
auto &coordinateType = getType(coordinate);
Pointer<Byte> sampler = samplerDescriptor + OFFSET(vk::SampledImageDescriptor, sampler); // vk::Sampler*
Pointer<Byte> texture = imageDescriptor + OFFSET(vk::SampledImageDescriptor, texture); // sw::Texture*
......@@ -204,7 +203,7 @@ SpirvShader::EmitResult SpirvShader::EmitImageSample(ImageInstruction instructio
Array<SIMD::Float> in(16); // Maximum 16 input parameter components.
uint32_t coordinates = coordinateType.componentCount - instruction.isProj();
uint32_t coordinates = coordinate.componentCount - instruction.isProj();
instruction.coordinates = coordinates;
uint32_t i = 0;
......@@ -246,17 +245,16 @@ SpirvShader::EmitResult SpirvShader::EmitImageSample(ImageInstruction instructio
{
auto dxValue = Operand(this, state, gradDxId);
auto dyValue = Operand(this, state, gradDyId);
auto &dxyType = getType(dxValue);
ASSERT(dxyType.componentCount == getType(dyValue).componentCount);
ASSERT(dxValue.componentCount == dxValue.componentCount);
instruction.grad = dxyType.componentCount;
instruction.grad = dxValue.componentCount;
for(uint32_t j = 0; j < dxyType.componentCount; j++, i++)
for(uint32_t j = 0; j < dxValue.componentCount; j++, i++)
{
in[i] = dxValue.Float(j);
}
for(uint32_t j = 0; j < dxyType.componentCount; j++, i++)
for(uint32_t j = 0; j < dxValue.componentCount; j++, i++)
{
in[i] = dyValue.Float(j);
}
......@@ -273,11 +271,9 @@ SpirvShader::EmitResult SpirvShader::EmitImageSample(ImageInstruction instructio
if(constOffset)
{
auto offsetValue = Operand(this, state, offsetId);
auto &offsetType = getType(offsetValue);
instruction.offset = offsetValue.componentCount;
instruction.offset = offsetType.componentCount;
for(uint32_t j = 0; j < offsetType.componentCount; j++, i++)
for(uint32_t j = 0; j < offsetValue.componentCount; j++, i++)
{
in[i] = As<SIMD::Float>(offsetValue.Int(j)); // Integer values, but transfered as float.
}
......@@ -383,7 +379,7 @@ void SpirvShader::GetImageDimensions(EmitState const *state, Type const &resultT
if(lodId != 0)
{
auto lodVal = Operand(this, state, lodId);
ASSERT(getType(lodVal).componentCount == 1);
ASSERT(lodVal.componentCount == 1);
auto lod = lodVal.Int(0);
auto one = SIMD::Int(1);
for(uint32_t i = 0; i < dimensions; i++)
......@@ -476,12 +472,12 @@ SIMD::Pointer SpirvShader::GetTexelAddress(EmitState const *state, SIMD::Pointer
auto routine = state->routine;
bool isArrayed = imageType.definition.word(5) != 0;
auto dim = static_cast<spv::Dim>(imageType.definition.word(3));
int dims = getType(coordinate).componentCount - (isArrayed ? 1 : 0);
int dims = coordinate.componentCount - (isArrayed ? 1 : 0);
SIMD::Int u = coordinate.Int(0);
SIMD::Int v = SIMD::Int(0);
if(getType(coordinate).componentCount > 1)
if(coordinate.componentCount > 1)
{
v = coordinate.Int(1);
}
......
......@@ -99,7 +99,7 @@ SpirvShader::EmitResult SpirvShader::EmitStore(InsnIterator insn, EmitState *sta
if(object.kind == Object::Kind::Constant)
{
// Constant source data.
const uint32_t *src = object.constantValue.get();
const uint32_t *src = object.constantValue.data();
VisitMemoryObject(pointerId, [&](const MemoryElement &el) {
auto p = ptr + el.offset;
if(interleavedByLane) { p = InterleaveByLane(p); }
......
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