Commit 1ca8acdb by Chris Forbes

Implement proper handling of constants

Previously we had only supported simple integer constants, as that was enough to parse array declarations etc. Fully implement constants, including large null objects, and constant composites constructed out of other constants. Bug: b/124934655 Change-Id: Ia1087f62a2bd75a3ca2f784ea24b0b3f01984ad9 Reviewed-on: https://swiftshader-review.googlesource.com/c/25148Tested-by: 's avatarChris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarBen Clayton <bclayton@google.com>
parent 7aafb274
......@@ -177,17 +177,34 @@ namespace sw
}
case spv::OpConstant:
case spv::OpConstantComposite:
CreateConstant(insn).constantValue[0] = insn.word(3);
break;
case spv::OpConstantFalse:
CreateConstant(insn).constantValue[0] = 0; // represent boolean false as zero
break;
case spv::OpConstantTrue:
CreateConstant(insn).constantValue[0] = ~0u; // represent boolean true as all bits set
break;
case spv::OpConstantNull:
{
auto typeId = insn.word(1);
auto resultId = insn.word(2);
auto &object = defs[resultId];
object.kind = Object::Kind::Constant;
object.definition = insn;
object.sizeInComponents = getType(typeId).sizeInComponents;
// OpConstantNull forms a constant of arbitrary type, all zeros.
auto & object = CreateConstant(insn);
for (auto i = 0u; i < object.sizeInComponents; i++)
{
object.constantValue[i] = 0;
}
break;
}
case spv::OpConstantComposite:
{
auto &object = CreateConstant(insn);
auto offset = 0u;
for (auto i = 0u; i < insn.wordCount() - 3; i++)
{
auto & constituent = getObject(insn.word(i + 3));
for (auto j = 0u; j < constituent.sizeInComponents; j++)
object.constantValue[offset++] = constituent.constantValue[j];
}
break;
}
......@@ -254,6 +271,18 @@ namespace sw
}
}
SpirvShader::Object& SpirvShader::CreateConstant(InsnIterator insn)
{
auto typeId = insn.word(1);
auto resultId = insn.word(2);
auto &object = defs[resultId];
object.kind = Object::Kind::Constant;
object.definition = insn;
object.sizeInComponents = getType(typeId).sizeInComponents;
object.constantValue = std::unique_ptr<uint32_t[]>(new uint32_t[object.sizeInComponents]);
return object;
}
void SpirvShader::ProcessInterfaceVariable(Object &object)
{
assert(object.storageClass == spv::StorageClassInput || object.storageClass == spv::StorageClassOutput);
......@@ -764,27 +793,57 @@ namespace sw
}
SpirvRoutine::Value& ptrBase = routine->getValue(pointer.pointerBase);
auto & src = routine->getIntermediate(insn.word(2));;
if (pointer.kind == Object::Kind::Value)
if (object.kind == Object::Kind::Constant)
{
auto offsets = As<Int4>(routine->getIntermediate(insn.word(1))[0]);
for (auto i = 0u; i < object.sizeInComponents; i++)
auto src = reinterpret_cast<float *>(object.constantValue.get());
if (pointer.kind == Object::Kind::Value)
{
// Scattered store
for (int j = 0; j < 4; j++)
auto offsets = As<Int4>(routine->getIntermediate(insn.word(1))[0]);
for (auto i = 0u; i < object.sizeInComponents; i++)
{
// Scattered store
for (int j = 0; j < 4; j++)
{
auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Float(src[i]), j);
}
}
}
else
{
// no divergent offsets
for (auto i = 0u; i < object.sizeInComponents; i++)
{
auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Extract(src[i], j), j);
ptrBase[i] = RValue<Float4>(src[i]);
}
}
}
else
{
// no divergent offsets
for (auto i = 0u; i < object.sizeInComponents; i++)
auto &src = routine->getIntermediate(insn.word(2));
if (pointer.kind == Object::Kind::Value)
{
auto offsets = As<Int4>(routine->getIntermediate(insn.word(1))[0]);
for (auto i = 0u; i < object.sizeInComponents; i++)
{
// Scattered store
for (int j = 0; j < 4; j++)
{
auto dst = ptrBase[Int(i) + Extract(offsets, j)];
dst = Insert(dst, Extract(src[i], j), j);
}
}
}
else
{
ptrBase[i] = src[i];
// no divergent offsets
for (auto i = 0u; i < object.sizeInComponents; i++)
{
ptrBase[i] = src[i];
}
}
}
break;
......
......@@ -206,6 +206,7 @@ namespace sw
uint32_t sizeInComponents = 0;
bool isBuiltInBlock = false;
uint32_t pointerBase = 0;
std::unique_ptr<uint32_t[]> constantValue = nullptr;
enum class Kind
{
......@@ -355,6 +356,7 @@ namespace sw
void VisitInterface(uint32_t id, F f) const;
uint32_t GetConstantInt(uint32_t id) const;
Object& CreateConstant(InsnIterator it);
void ProcessInterfaceVariable(Object &object);
......
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