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 ...@@ -177,17 +177,34 @@ namespace sw
} }
case spv::OpConstant: case spv::OpConstant:
case spv::OpConstantComposite: CreateConstant(insn).constantValue[0] = insn.word(3);
break;
case spv::OpConstantFalse: case spv::OpConstantFalse:
CreateConstant(insn).constantValue[0] = 0; // represent boolean false as zero
break;
case spv::OpConstantTrue: case spv::OpConstantTrue:
CreateConstant(insn).constantValue[0] = ~0u; // represent boolean true as all bits set
break;
case spv::OpConstantNull: case spv::OpConstantNull:
{ {
auto typeId = insn.word(1); // OpConstantNull forms a constant of arbitrary type, all zeros.
auto resultId = insn.word(2); auto & object = CreateConstant(insn);
auto &object = defs[resultId]; for (auto i = 0u; i < object.sizeInComponents; i++)
object.kind = Object::Kind::Constant; {
object.definition = insn; object.constantValue[i] = 0;
object.sizeInComponents = getType(typeId).sizeInComponents; }
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; break;
} }
...@@ -254,6 +271,18 @@ namespace sw ...@@ -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) void SpirvShader::ProcessInterfaceVariable(Object &object)
{ {
assert(object.storageClass == spv::StorageClassInput || object.storageClass == spv::StorageClassOutput); assert(object.storageClass == spv::StorageClassInput || object.storageClass == spv::StorageClassOutput);
...@@ -764,7 +793,36 @@ namespace sw ...@@ -764,7 +793,36 @@ namespace sw
} }
SpirvRoutine::Value& ptrBase = routine->getValue(pointer.pointerBase); SpirvRoutine::Value& ptrBase = routine->getValue(pointer.pointerBase);
auto & src = routine->getIntermediate(insn.word(2));;
if (object.kind == Object::Kind::Constant)
{
auto src = reinterpret_cast<float *>(object.constantValue.get());
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, Float(src[i]), j);
}
}
}
else
{
// no divergent offsets
for (auto i = 0u; i < object.sizeInComponents; i++)
{
ptrBase[i] = RValue<Float4>(src[i]);
}
}
}
else
{
auto &src = routine->getIntermediate(insn.word(2));
if (pointer.kind == Object::Kind::Value) if (pointer.kind == Object::Kind::Value)
{ {
...@@ -787,6 +845,7 @@ namespace sw ...@@ -787,6 +845,7 @@ namespace sw
ptrBase[i] = src[i]; ptrBase[i] = src[i];
} }
} }
}
break; break;
} }
default: default:
......
...@@ -206,6 +206,7 @@ namespace sw ...@@ -206,6 +206,7 @@ namespace sw
uint32_t sizeInComponents = 0; uint32_t sizeInComponents = 0;
bool isBuiltInBlock = false; bool isBuiltInBlock = false;
uint32_t pointerBase = 0; uint32_t pointerBase = 0;
std::unique_ptr<uint32_t[]> constantValue = nullptr;
enum class Kind enum class Kind
{ {
...@@ -355,6 +356,7 @@ namespace sw ...@@ -355,6 +356,7 @@ namespace sw
void VisitInterface(uint32_t id, F f) const; void VisitInterface(uint32_t id, F f) const;
uint32_t GetConstantInt(uint32_t id) const; uint32_t GetConstantInt(uint32_t id) const;
Object& CreateConstant(InsnIterator it);
void ProcessInterfaceVariable(Object &object); 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