Commit 18ddd131 by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: SPIR-V Gen: Support mediump/lowp

The mediump and lowp precisions translate to a RelaxedPrecision decoration in SPIR-V. This change implements this decoration and enables SPIR-V generation when emulating Bresenham lines. Prior to this change, Bresenham line emulation resulted in a validation error due to the vertex shader output being without RelaxedPrecision but the fragment shader input (translated by glslang) with it. The function that produces a new id is given a list of decorations to apply, which itself is automatically deriven from the TType where applicable, to minimize the risk of any id missing this decoration. Bug: angleproject:4889 Change-Id: I30cc5a278634c5d83d63cd65b057336f9f573baa Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2946113 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 33aa7ef0
...@@ -44,10 +44,16 @@ bool operator==(const SpirvType &a, const SpirvType &b) ...@@ -44,10 +44,16 @@ bool operator==(const SpirvType &a, const SpirvType &b)
(a.arraySizes.empty() || a.blockStorage == b.blockStorage); (a.arraySizes.empty() || a.blockStorage == b.blockStorage);
} }
spirv::IdRef SPIRVBuilder::getNewId() spirv::IdRef SPIRVBuilder::getNewId(const SpirvDecorations &decorations)
{ {
spirv::IdRef newId = mNextAvailableId; spirv::IdRef newId = mNextAvailableId;
mNextAvailableId = spirv::IdRef(mNextAvailableId + 1); mNextAvailableId = spirv::IdRef(mNextAvailableId + 1);
for (const spv::Decoration decoration : decorations)
{
spirv::WriteDecorate(&mSpirvDecorations, newId, decoration, {});
}
return newId; return newId;
} }
...@@ -133,7 +139,7 @@ spirv::IdRef SPIRVBuilder::getTypePointerId(spirv::IdRef typeId, spv::StorageCla ...@@ -133,7 +139,7 @@ spirv::IdRef SPIRVBuilder::getTypePointerId(spirv::IdRef typeId, spv::StorageCla
auto iter = mTypePointerIdMap.find(key); auto iter = mTypePointerIdMap.find(key);
if (iter == mTypePointerIdMap.end()) if (iter == mTypePointerIdMap.end())
{ {
const spirv::IdRef typePointerId = getNewId(); const spirv::IdRef typePointerId = getNewId({});
spirv::WriteTypePointer(&mSpirvTypePointerDecls, typePointerId, storageClass, typeId); spirv::WriteTypePointer(&mSpirvTypePointerDecls, typePointerId, storageClass, typeId);
...@@ -151,7 +157,7 @@ spirv::IdRef SPIRVBuilder::getFunctionTypeId(spirv::IdRef returnTypeId, ...@@ -151,7 +157,7 @@ spirv::IdRef SPIRVBuilder::getFunctionTypeId(spirv::IdRef returnTypeId,
auto iter = mFunctionTypeIdMap.find(key); auto iter = mFunctionTypeIdMap.find(key);
if (iter == mFunctionTypeIdMap.end()) if (iter == mFunctionTypeIdMap.end())
{ {
const spirv::IdRef functionTypeId = getNewId(); const spirv::IdRef functionTypeId = getNewId({});
spirv::WriteTypeFunction(&mSpirvFunctionTypeDecls, functionTypeId, returnTypeId, spirv::WriteTypeFunction(&mSpirvFunctionTypeDecls, functionTypeId, returnTypeId,
paramTypeIds); paramTypeIds);
...@@ -162,6 +168,25 @@ spirv::IdRef SPIRVBuilder::getFunctionTypeId(spirv::IdRef returnTypeId, ...@@ -162,6 +168,25 @@ spirv::IdRef SPIRVBuilder::getFunctionTypeId(spirv::IdRef returnTypeId,
return iter->second; return iter->second;
} }
SpirvDecorations SPIRVBuilder::getDecorations(const TType &type)
{
const bool enablePrecision = (mCompileOptions & SH_IGNORE_PRECISION_QUALIFIERS) == 0;
const TPrecision precision = type.getPrecision();
SpirvDecorations decorations;
// Handle precision.
if (enablePrecision && !mDisableRelaxedPrecision &&
(precision == EbpMedium || precision == EbpLow))
{
decorations.push_back(spv::DecorationRelaxedPrecision);
}
// TODO: Handle |precise|. http://anglebug.com/4889.
return decorations;
}
SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *blockName) SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *blockName)
{ {
// Recursively declare the type. Type id is allocated afterwards purely for better id order in // Recursively declare the type. Type id is allocated afterwards purely for better id order in
...@@ -183,7 +208,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -183,7 +208,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
const spirv::IdRef subTypeId = getSpirvTypeData(subType, blockName).id; const spirv::IdRef subTypeId = getSpirvTypeData(subType, blockName).id;
const unsigned int length = type.arraySizes.back(); const unsigned int length = type.arraySizes.back();
typeId = getNewId(); typeId = getNewId({});
if (length == 0) if (length == 0)
{ {
...@@ -209,7 +234,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -209,7 +234,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
fieldTypeIds.push_back(fieldTypeId); fieldTypeIds.push_back(fieldTypeId);
} }
typeId = getNewId(); typeId = getNewId({});
spirv::WriteTypeStruct(&mSpirvTypeAndConstantDecls, typeId, fieldTypeIds); spirv::WriteTypeStruct(&mSpirvTypeAndConstantDecls, typeId, fieldTypeIds);
} }
else if (IsSampler(type.type) && !type.isSamplerBaseImage) else if (IsSampler(type.type) && !type.isSamplerBaseImage)
...@@ -223,7 +248,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -223,7 +248,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
const spirv::IdRef nonSampledId = getSpirvTypeData(imageType, "").id; const spirv::IdRef nonSampledId = getSpirvTypeData(imageType, "").id;
typeId = getNewId(); typeId = getNewId({});
spirv::WriteTypeSampledImage(&mSpirvTypeAndConstantDecls, typeId, nonSampledId); spirv::WriteTypeSampledImage(&mSpirvTypeAndConstantDecls, typeId, nonSampledId);
} }
else if (IsImage(type.type) || type.isSamplerBaseImage) else if (IsImage(type.type) || type.isSamplerBaseImage)
...@@ -241,7 +266,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -241,7 +266,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
&sampled); &sampled);
spv::ImageFormat imageFormat = getImageFormat(type.imageInternalFormat); spv::ImageFormat imageFormat = getImageFormat(type.imageInternalFormat);
typeId = getNewId(); typeId = getNewId({});
spirv::WriteTypeImage(&mSpirvTypeAndConstantDecls, typeId, sampledType, dim, depth, arrayed, spirv::WriteTypeImage(&mSpirvTypeAndConstantDecls, typeId, sampledType, dim, depth, arrayed,
multisampled, sampled, imageFormat, nullptr); multisampled, sampled, imageFormat, nullptr);
} }
...@@ -260,7 +285,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -260,7 +285,7 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
const spirv::IdRef columnTypeId = getSpirvTypeData(columnType, "").id; const spirv::IdRef columnTypeId = getSpirvTypeData(columnType, "").id;
typeId = getNewId(); typeId = getNewId({});
spirv::WriteTypeMatrix(&mSpirvTypeAndConstantDecls, typeId, columnTypeId, spirv::WriteTypeMatrix(&mSpirvTypeAndConstantDecls, typeId, columnTypeId,
spirv::LiteralInteger(type.secondarySize)); spirv::LiteralInteger(type.secondarySize));
} }
...@@ -274,13 +299,13 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -274,13 +299,13 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
const spirv::IdRef componentTypeId = getSpirvTypeData(componentType, "").id; const spirv::IdRef componentTypeId = getSpirvTypeData(componentType, "").id;
typeId = getNewId(); typeId = getNewId({});
spirv::WriteTypeVector(&mSpirvTypeAndConstantDecls, typeId, componentTypeId, spirv::WriteTypeVector(&mSpirvTypeAndConstantDecls, typeId, componentTypeId,
spirv::LiteralInteger(type.primarySize)); spirv::LiteralInteger(type.primarySize));
} }
else else
{ {
typeId = getNewId(); typeId = getNewId({});
// Declaring a basic type. There's a different instruction for each. // Declaring a basic type. There's a different instruction for each.
switch (type.type) switch (type.type)
...@@ -358,7 +383,11 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -358,7 +383,11 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
} }
} }
// TODO: handle RelaxedPrecision types. http://anglebug.com/4889. // Write other member decorations.
if (type.block != nullptr && type.arraySizes.empty())
{
writeMemberDecorations(type, typeId);
}
return {typeId, baseAlignment, sizeInStorageBlock, matrixStride}; return {typeId, baseAlignment, sizeInStorageBlock, matrixStride};
} }
...@@ -717,7 +746,7 @@ spirv::IdRef SPIRVBuilder::getBoolConstant(bool value) ...@@ -717,7 +746,7 @@ spirv::IdRef SPIRVBuilder::getBoolConstant(bool value)
const spirv::IdRef boolTypeId = getSpirvTypeData(boolType, "").id; const spirv::IdRef boolTypeId = getSpirvTypeData(boolType, "").id;
mBoolConstants[asInt] = constantId = getNewId(); mBoolConstants[asInt] = constantId = getNewId({});
if (value) if (value)
{ {
spirv::WriteConstantTrue(&mSpirvTypeAndConstantDecls, boolTypeId, constantId); spirv::WriteConstantTrue(&mSpirvTypeAndConstantDecls, boolTypeId, constantId);
...@@ -742,7 +771,7 @@ spirv::IdRef SPIRVBuilder::getBasicConstantHelper(uint32_t value, ...@@ -742,7 +771,7 @@ spirv::IdRef SPIRVBuilder::getBasicConstantHelper(uint32_t value,
spirvType.type = type; spirvType.type = type;
const spirv::IdRef typeId = getSpirvTypeData(spirvType, "").id; const spirv::IdRef typeId = getSpirvTypeData(spirvType, "").id;
const spirv::IdRef constantId = getNewId(); const spirv::IdRef constantId = getNewId({});
spirv::WriteConstant(&mSpirvTypeAndConstantDecls, typeId, constantId, spirv::WriteConstant(&mSpirvTypeAndConstantDecls, typeId, constantId,
spirv::LiteralContextDependentNumber(value)); spirv::LiteralContextDependentNumber(value));
...@@ -782,7 +811,7 @@ spirv::IdRef SPIRVBuilder::getCompositeConstant(spirv::IdRef typeId, const spirv ...@@ -782,7 +811,7 @@ spirv::IdRef SPIRVBuilder::getCompositeConstant(spirv::IdRef typeId, const spirv
auto iter = mCompositeConstants.find(key); auto iter = mCompositeConstants.find(key);
if (iter == mCompositeConstants.end()) if (iter == mCompositeConstants.end())
{ {
const spirv::IdRef constantId = getNewId(); const spirv::IdRef constantId = getNewId({});
spirv::WriteConstantComposite(&mSpirvTypeAndConstantDecls, typeId, constantId, values); spirv::WriteConstantComposite(&mSpirvTypeAndConstantDecls, typeId, constantId, values);
...@@ -798,7 +827,7 @@ void SPIRVBuilder::startNewFunction(spirv::IdRef functionId, const char *name) ...@@ -798,7 +827,7 @@ void SPIRVBuilder::startNewFunction(spirv::IdRef functionId, const char *name)
// Add the first block of the function. // Add the first block of the function.
mSpirvCurrentFunctionBlocks.emplace_back(); mSpirvCurrentFunctionBlocks.emplace_back();
mSpirvCurrentFunctionBlocks.back().labelId = getNewId(); mSpirvCurrentFunctionBlocks.back().labelId = getNewId({});
// Output debug information. // Output debug information.
if (name) if (name)
...@@ -832,6 +861,7 @@ void SPIRVBuilder::assembleSpirvFunctionBlocks() ...@@ -832,6 +861,7 @@ void SPIRVBuilder::assembleSpirvFunctionBlocks()
spirv::IdRef SPIRVBuilder::declareVariable(spirv::IdRef typeId, spirv::IdRef SPIRVBuilder::declareVariable(spirv::IdRef typeId,
spv::StorageClass storageClass, spv::StorageClass storageClass,
const SpirvDecorations &decorations,
spirv::IdRef *initializerId, spirv::IdRef *initializerId,
const char *name) const char *name)
{ {
...@@ -846,7 +876,7 @@ spirv::IdRef SPIRVBuilder::declareVariable(spirv::IdRef typeId, ...@@ -846,7 +876,7 @@ spirv::IdRef SPIRVBuilder::declareVariable(spirv::IdRef typeId,
? &mSpirvCurrentFunctionBlocks.front().localVariables ? &mSpirvCurrentFunctionBlocks.front().localVariables
: &mSpirvVariableDecls; : &mSpirvVariableDecls;
const spirv::IdRef variableId = getNewId(); const spirv::IdRef variableId = getNewId(decorations);
const spirv::IdRef typePointerId = getTypePointerId(typeId, storageClass); const spirv::IdRef typePointerId = getTypePointerId(typeId, storageClass);
spirv::WriteVariable(spirvSection, typePointerId, variableId, storageClass, initializerId); spirv::WriteVariable(spirvSection, typePointerId, variableId, storageClass, initializerId);
...@@ -862,7 +892,7 @@ spirv::IdRef SPIRVBuilder::declareVariable(spirv::IdRef typeId, ...@@ -862,7 +892,7 @@ spirv::IdRef SPIRVBuilder::declareVariable(spirv::IdRef typeId,
spirv::IdRef SPIRVBuilder::declareSpecConst(TBasicType type, int id, const char *name) spirv::IdRef SPIRVBuilder::declareSpecConst(TBasicType type, int id, const char *name)
{ {
const spirv::IdRef specConstId = getNewId(); const spirv::IdRef specConstId = getNewId({});
SpirvType spirvType; SpirvType spirvType;
spirvType.type = type; spirvType.type = type;
...@@ -902,7 +932,7 @@ void SPIRVBuilder::startConditional(size_t blockCount, bool isContinuable, bool ...@@ -902,7 +932,7 @@ void SPIRVBuilder::startConditional(size_t blockCount, bool isContinuable, bool
conditional.blockIds.resize(blockCount); conditional.blockIds.resize(blockCount);
for (spirv::IdRef &blockId : conditional.blockIds) for (spirv::IdRef &blockId : conditional.blockIds)
{ {
blockId = getNewId(); blockId = getNewId({});
} }
conditional.isContinuable = isContinuable; conditional.isContinuable = isContinuable;
...@@ -1004,6 +1034,9 @@ void SPIRVBuilder::writePerVertexBuiltIns(const TType &type, spirv::IdRef typeId ...@@ -1004,6 +1034,9 @@ void SPIRVBuilder::writePerVertexBuiltIns(const TType &type, spirv::IdRef typeId
spv::DecorationBuiltIn, spv::DecorationBuiltIn,
{spirv::LiteralInteger(decorationValue)}); {spirv::LiteralInteger(decorationValue)});
} }
SpirvType spirvType = getSpirvType(type, EbsUnspecified);
writeMemberDecorations(spirvType, typeId);
} }
void SPIRVBuilder::writeInterfaceVariableDecorations(const TType &type, spirv::IdRef variableId) void SPIRVBuilder::writeInterfaceVariableDecorations(const TType &type, spirv::IdRef variableId)
...@@ -1247,7 +1280,36 @@ uint32_t SPIRVBuilder::calculateSizeAndWriteOffsetDecorations(const SpirvType &t ...@@ -1247,7 +1280,36 @@ uint32_t SPIRVBuilder::calculateSizeAndWriteOffsetDecorations(const SpirvType &t
spirv::WriteMemberDecorate(&mSpirvDecorations, typeId, spirv::LiteralInteger(fieldIndex), spirv::WriteMemberDecorate(&mSpirvDecorations, typeId, spirv::LiteralInteger(fieldIndex),
spv::DecorationOffset, {spirv::LiteralInteger(nextOffset)}); spv::DecorationOffset, {spirv::LiteralInteger(nextOffset)});
// While here, add matrix decorations if any. // Calculate the next offset. The next offset is the current offset plus the size of the
// field, aligned to its base alignment.
//
// > Rule 4. ... the base offset of the member following the array is rounded up to the next
// > multiple of the base alignment.
//
// > Rule 9. ... the base offset of the member following the sub-structure is rounded up to
// > the next multiple of the base alignment of the structure.
nextOffset = nextOffset + fieldTypeData.sizeInStorageBlock;
nextOffset = rx::roundUp(nextOffset, fieldTypeData.baseAlignment);
++fieldIndex;
}
return nextOffset;
}
void SPIRVBuilder::writeMemberDecorations(const SpirvType &type, spirv::IdRef typeId)
{
ASSERT(type.block != nullptr);
uint32_t fieldIndex = 0;
for (const TField *field : type.block->fields())
{
const TType &fieldType = *field->type();
const SpirvTypeData &fieldTypeData = getTypeData(fieldType, type.blockStorage);
// Add matrix decorations if any.
if (fieldType.isMatrix()) if (fieldType.isMatrix())
{ {
ASSERT(fieldTypeData.matrixStride != 0); ASSERT(fieldTypeData.matrixStride != 0);
...@@ -1264,21 +1326,16 @@ uint32_t SPIRVBuilder::calculateSizeAndWriteOffsetDecorations(const SpirvType &t ...@@ -1264,21 +1326,16 @@ uint32_t SPIRVBuilder::calculateSizeAndWriteOffsetDecorations(const SpirvType &t
isRowMajor ? spv::DecorationRowMajor : spv::DecorationColMajor, {}); isRowMajor ? spv::DecorationRowMajor : spv::DecorationColMajor, {});
} }
// Calculate the next offset. The next offset is the current offset plus the size of the // Add other decorations.
// field, aligned to its base alignment. SpirvDecorations decorations = getDecorations(fieldType);
// for (const spv::Decoration decoration : decorations)
// > Rule 4. ... the base offset of the member following the array is rounded up to the next {
// > multiple of the base alignment. spirv::WriteMemberDecorate(&mSpirvDecorations, typeId,
// spirv::LiteralInteger(fieldIndex), decoration, {});
// > Rule 9. ... the base offset of the member following the sub-structure is rounded up to }
// > the next multiple of the base alignment of the structure.
nextOffset = nextOffset + fieldTypeData.sizeInStorageBlock;
nextOffset = rx::roundUp(nextOffset, fieldTypeData.baseAlignment);
++fieldIndex; ++fieldIndex;
} }
return nextOffset;
} }
ImmutableString SPIRVBuilder::hashName(const TSymbol *symbol) ImmutableString SPIRVBuilder::hashName(const TSymbol *symbol)
...@@ -1330,7 +1387,7 @@ spirv::Blob SPIRVBuilder::getSpirv() ...@@ -1330,7 +1387,7 @@ spirv::Blob SPIRVBuilder::getSpirv()
mSpirvFunctions.size()); mSpirvFunctions.size());
// Generate any necessary id before writing the id bound in header. // Generate any necessary id before writing the id bound in header.
const spirv::IdRef extInstImportId = getNewId(); const spirv::IdRef extInstImportId = getNewId({});
// Generate the SPIR-V header. // Generate the SPIR-V header.
spirv::WriteSpirvHeader(&result, mNextAvailableId); spirv::WriteSpirvHeader(&result, mNextAvailableId);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef COMPILER_TRANSLATOR_BUILDSPIRV_H_ #ifndef COMPILER_TRANSLATOR_BUILDSPIRV_H_
#define COMPILER_TRANSLATOR_BUILDSPIRV_H_ #define COMPILER_TRANSLATOR_BUILDSPIRV_H_
#include "common/FixedVector.h"
#include "common/hash_utils.h" #include "common/hash_utils.h"
#include "common/spirv/spirv_instruction_builder_autogen.h" #include "common/spirv/spirv_instruction_builder_autogen.h"
#include "compiler/translator/Compiler.h" #include "compiler/translator/Compiler.h"
...@@ -156,6 +157,16 @@ struct SpirvTypeData ...@@ -156,6 +157,16 @@ struct SpirvTypeData
uint32_t matrixStride; uint32_t matrixStride;
}; };
// Decorations to be applied to variable or intermediate ids which are not part of the SPIR-V type
// and are not specific enough (like DescriptorSet) to be handled automatically. Currently, these
// are:
//
// RelaxedPrecision: used to implement |lowp| and |mediump|
// NoContraction: used to implement |precise|. TODO: support this. It requires the precise
// property to be promoted through the nodes in the AST, which currently isn't.
// http://anglebug.com/4889
using SpirvDecorations = angle::FixedVector<spv::Decoration, 2>;
// A block of code. SPIR-V produces forward references to blocks, such as OpBranchConditional // A block of code. SPIR-V produces forward references to blocks, such as OpBranchConditional
// specifying the id of the if and else blocks, each of those referencing the id of the block after // specifying the id of the if and else blocks, each of those referencing the id of the block after
// the else. Additionally, local variable declarations are accumulated at the top of the first // the else. Additionally, local variable declarations are accumulated at the top of the first
...@@ -213,11 +224,13 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -213,11 +224,13 @@ class SPIRVBuilder : angle::NonCopyable
public: public:
SPIRVBuilder(TCompiler *compiler, SPIRVBuilder(TCompiler *compiler,
ShCompileOptions compileOptions, ShCompileOptions compileOptions,
bool forceHighp,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap &nameMap) NameMap &nameMap)
: mCompiler(compiler), : mCompiler(compiler),
mCompileOptions(compileOptions), mCompileOptions(compileOptions),
mShaderType(gl::FromGLenum<gl::ShaderType>(compiler->getShaderType())), mShaderType(gl::FromGLenum<gl::ShaderType>(compiler->getShaderType())),
mDisableRelaxedPrecision(forceHighp),
mNextAvailableId(1), mNextAvailableId(1),
mHashFunction(hashFunction), mHashFunction(hashFunction),
mNameMap(nameMap), mNameMap(nameMap),
...@@ -226,13 +239,16 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -226,13 +239,16 @@ class SPIRVBuilder : angle::NonCopyable
mNextUnusedOutputLocation(0) mNextUnusedOutputLocation(0)
{} {}
spirv::IdRef getNewId(); spirv::IdRef getNewId(const SpirvDecorations &decorations);
SpirvType getSpirvType(const TType &type, TLayoutBlockStorage blockStorage) const; SpirvType getSpirvType(const TType &type, TLayoutBlockStorage blockStorage) const;
const SpirvTypeData &getTypeData(const TType &type, TLayoutBlockStorage blockStorage); const SpirvTypeData &getTypeData(const TType &type, TLayoutBlockStorage blockStorage);
const SpirvTypeData &getSpirvTypeData(const SpirvType &type, const char *blockName); const SpirvTypeData &getSpirvTypeData(const SpirvType &type, const char *blockName);
spirv::IdRef getTypePointerId(spirv::IdRef typeId, spv::StorageClass storageClass); spirv::IdRef getTypePointerId(spirv::IdRef typeId, spv::StorageClass storageClass);
spirv::IdRef getFunctionTypeId(spirv::IdRef returnTypeId, const spirv::IdRefList &paramTypeIds); spirv::IdRef getFunctionTypeId(spirv::IdRef returnTypeId, const spirv::IdRefList &paramTypeIds);
// Decorations that may apply to intermediate instructions (in addition to variables).
SpirvDecorations getDecorations(const TType &type);
spirv::Blob *getSpirvDebug() { return &mSpirvDebug; } spirv::Blob *getSpirvDebug() { return &mSpirvDebug; }
spirv::Blob *getSpirvDecorations() { return &mSpirvDecorations; } spirv::Blob *getSpirvDecorations() { return &mSpirvDecorations; }
spirv::Blob *getSpirvTypeAndConstantDecls() { return &mSpirvTypeAndConstantDecls; } spirv::Blob *getSpirvTypeAndConstantDecls() { return &mSpirvTypeAndConstantDecls; }
...@@ -264,11 +280,6 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -264,11 +280,6 @@ class SPIRVBuilder : angle::NonCopyable
void writePerVertexBuiltIns(const TType &type, spirv::IdRef typeId); void writePerVertexBuiltIns(const TType &type, spirv::IdRef typeId);
void writeInterfaceVariableDecorations(const TType &type, spirv::IdRef variableId); void writeInterfaceVariableDecorations(const TType &type, spirv::IdRef variableId);
uint32_t calculateBaseAlignmentAndSize(const SpirvType &type,
uint32_t *sizeInStorageBlockOut,
uint32_t *matrixStrideOut);
uint32_t calculateSizeAndWriteOffsetDecorations(const SpirvType &type, spirv::IdRef typeId);
spirv::IdRef getBoolConstant(bool value); spirv::IdRef getBoolConstant(bool value);
spirv::IdRef getUintConstant(uint32_t value); spirv::IdRef getUintConstant(uint32_t value);
spirv::IdRef getIntConstant(int32_t value); spirv::IdRef getIntConstant(int32_t value);
...@@ -283,6 +294,7 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -283,6 +294,7 @@ class SPIRVBuilder : angle::NonCopyable
// the current function. // the current function.
spirv::IdRef declareVariable(spirv::IdRef typeId, spirv::IdRef declareVariable(spirv::IdRef typeId,
spv::StorageClass storageClass, spv::StorageClass storageClass,
const SpirvDecorations &decorations,
spirv::IdRef *initializerId, spirv::IdRef *initializerId,
const char *name); const char *name);
// Helper to declare specialization constants. // Helper to declare specialization constants.
...@@ -308,6 +320,12 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -308,6 +320,12 @@ class SPIRVBuilder : angle::NonCopyable
private: private:
SpirvTypeData declareType(const SpirvType &type, const char *blockName); SpirvTypeData declareType(const SpirvType &type, const char *blockName);
uint32_t calculateBaseAlignmentAndSize(const SpirvType &type,
uint32_t *sizeInStorageBlockOut,
uint32_t *matrixStrideOut);
uint32_t calculateSizeAndWriteOffsetDecorations(const SpirvType &type, spirv::IdRef typeId);
void writeMemberDecorations(const SpirvType &type, spirv::IdRef typeId);
// Helpers for type declaration. // Helpers for type declaration.
void getImageTypeParameters(TBasicType type, void getImageTypeParameters(TBasicType type,
spirv::IdRef *sampledTypeOut, spirv::IdRef *sampledTypeOut,
...@@ -329,8 +347,9 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -329,8 +347,9 @@ class SPIRVBuilder : angle::NonCopyable
void generateExecutionModes(spirv::Blob *blob); void generateExecutionModes(spirv::Blob *blob);
ANGLE_MAYBE_UNUSED TCompiler *mCompiler; ANGLE_MAYBE_UNUSED TCompiler *mCompiler;
ANGLE_MAYBE_UNUSED ShCompileOptions mCompileOptions; ShCompileOptions mCompileOptions;
gl::ShaderType mShaderType; gl::ShaderType mShaderType;
const bool mDisableRelaxedPrecision;
// Capabilities the shader is using. Accumulated as the instructions are generated. The Shader // Capabilities the shader is using. Accumulated as the instructions are generated. The Shader
// capability is unconditionally generated, so it's not tracked. // capability is unconditionally generated, so it's not tracked.
......
...@@ -186,14 +186,6 @@ bool CanFoldAggregateBuiltInOp(TOperator op) ...@@ -186,14 +186,6 @@ bool CanFoldAggregateBuiltInOp(TOperator op)
TIntermExpression::TIntermExpression(const TType &t) : TIntermTyped(), mType(t) {} TIntermExpression::TIntermExpression(const TType &t) : TIntermTyped(), mType(t) {}
void TIntermExpression::setTypePreservePrecision(const TType &t)
{
TPrecision precision = getPrecision();
mType = t;
ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
mType.setPrecision(precision);
}
#define REPLACE_IF_IS(node, type, original, replacement) \ #define REPLACE_IF_IS(node, type, original, replacement) \
do \ do \
{ \ { \
......
...@@ -170,6 +170,7 @@ class TIntermTyped : public TIntermNode ...@@ -170,6 +170,7 @@ class TIntermTyped : public TIntermNode
bool isVector() const { return getType().isVector(); } bool isVector() const { return getType().isVector(); }
bool isScalar() const { return getType().isScalar(); } bool isScalar() const { return getType().isScalar(); }
bool isScalarInt() const { return getType().isScalarInt(); } bool isScalarInt() const { return getType().isScalarInt(); }
bool isPrecise() const { return getType().isPrecise(); }
const char *getBasicString() const { return getType().getBasicString(); } const char *getBasicString() const { return getType().getBasicString(); }
unsigned int getOutermostArraySize() const { return getType().getOutermostArraySize(); } unsigned int getOutermostArraySize() const { return getType().getOutermostArraySize(); }
...@@ -303,7 +304,6 @@ class TIntermExpression : public TIntermTyped ...@@ -303,7 +304,6 @@ class TIntermExpression : public TIntermTyped
protected: protected:
TType *getTypePointer() { return &mType; } TType *getTypePointer() { return &mType; }
void setType(const TType &t) { mType = t; } void setType(const TType &t) { mType = t; }
void setTypePreservePrecision(const TType &t);
TIntermExpression(const TIntermExpression &node) = default; TIntermExpression(const TIntermExpression &node) = default;
......
...@@ -137,7 +137,7 @@ bool IsAccessChainUnindexedLValue(const NodeData &data) ...@@ -137,7 +137,7 @@ bool IsAccessChainUnindexedLValue(const NodeData &data)
class OutputSPIRVTraverser : public TIntermTraverser class OutputSPIRVTraverser : public TIntermTraverser
{ {
public: public:
OutputSPIRVTraverser(TCompiler *compiler, ShCompileOptions compileOptions); OutputSPIRVTraverser(TCompiler *compiler, ShCompileOptions compileOptions, bool forceHighp);
~OutputSPIRVTraverser() override; ~OutputSPIRVTraverser() override;
spirv::Blob getSpirv(); spirv::Blob getSpirv();
...@@ -179,7 +179,7 @@ class OutputSPIRVTraverser : public TIntermTraverser ...@@ -179,7 +179,7 @@ class OutputSPIRVTraverser : public TIntermTraverser
uint8_t componentCount) const; uint8_t componentCount) const;
void accessChainPushDynamicComponent(NodeData *data, spirv::IdRef index, spirv::IdRef typeId); void accessChainPushDynamicComponent(NodeData *data, spirv::IdRef index, spirv::IdRef typeId);
spirv::IdRef accessChainCollapse(NodeData *data); spirv::IdRef accessChainCollapse(NodeData *data);
spirv::IdRef accessChainLoad(NodeData *data); spirv::IdRef accessChainLoad(NodeData *data, const SpirvDecorations &decorations);
void accessChainStore(NodeData *data, spirv::IdRef value); void accessChainStore(NodeData *data, spirv::IdRef value);
// Access chain helpers. // Access chain helpers.
...@@ -316,11 +316,17 @@ spv::StorageClass GetStorageClass(const TType &type) ...@@ -316,11 +316,17 @@ spv::StorageClass GetStorageClass(const TType &type)
return spv::StorageClassPrivate; return spv::StorageClassPrivate;
} }
OutputSPIRVTraverser::OutputSPIRVTraverser(TCompiler *compiler, ShCompileOptions compileOptions) OutputSPIRVTraverser::OutputSPIRVTraverser(TCompiler *compiler,
ShCompileOptions compileOptions,
bool forceHighp)
: TIntermTraverser(true, true, true, &compiler->getSymbolTable()), : TIntermTraverser(true, true, true, &compiler->getSymbolTable()),
mCompiler(compiler), mCompiler(compiler),
mCompileOptions(compileOptions), mCompileOptions(compileOptions),
mBuilder(compiler, compileOptions, compiler->getHashFunction(), compiler->getNameMap()) mBuilder(compiler,
compileOptions,
forceHighp,
compiler->getHashFunction(),
compiler->getNameMap())
{} {}
OutputSPIRVTraverser::~OutputSPIRVTraverser() OutputSPIRVTraverser::~OutputSPIRVTraverser()
...@@ -391,7 +397,8 @@ spirv::IdRef OutputSPIRVTraverser::getSymbolIdAndStorageClass(const TSymbol *sym ...@@ -391,7 +397,8 @@ spirv::IdRef OutputSPIRVTraverser::getSymbolIdAndStorageClass(const TSymbol *sym
} }
const spirv::IdRef typeId = mBuilder.getSpirvTypeData(spirvType, "").id; const spirv::IdRef typeId = mBuilder.getSpirvTypeData(spirvType, "").id;
const spirv::IdRef varId = mBuilder.declareVariable(typeId, *storageClass, nullptr, name); const spirv::IdRef varId = mBuilder.declareVariable(
typeId, *storageClass, mBuilder.getDecorations(type), nullptr, name);
mBuilder.addEntryPointInterfaceVariableId(varId); mBuilder.addEntryPointInterfaceVariableId(varId);
spirv::WriteDecorate(mBuilder.getSpirvDecorations(), varId, spv::DecorationBuiltIn, spirv::WriteDecorate(mBuilder.getSpirvDecorations(), varId, spv::DecorationBuiltIn,
...@@ -513,13 +520,13 @@ void OutputSPIRVTraverser::accessChainPushDynamicComponent(NodeData *data, ...@@ -513,13 +520,13 @@ void OutputSPIRVTraverser::accessChainPushDynamicComponent(NodeData *data,
type.primarySize = static_cast<uint8_t>(swizzleIds.size()); type.primarySize = static_cast<uint8_t>(swizzleIds.size());
const spirv::IdRef uvecTypeId = mBuilder.getSpirvTypeData(type, "").id; const spirv::IdRef uvecTypeId = mBuilder.getSpirvTypeData(type, "").id;
const spirv::IdRef swizzlesId = mBuilder.getNewId(); const spirv::IdRef swizzlesId = mBuilder.getNewId({});
spirv::WriteConstantComposite(mBuilder.getSpirvTypeAndConstantDecls(), uvecTypeId, spirv::WriteConstantComposite(mBuilder.getSpirvTypeAndConstantDecls(), uvecTypeId,
swizzlesId, swizzleIds); swizzlesId, swizzleIds);
// Index that vector constant with the dynamic index. For example, vec.ywxz[i] becomes the // Index that vector constant with the dynamic index. For example, vec.ywxz[i] becomes the
// constant {1, 3, 0, 2} indexed with i, and that index used on vec. // constant {1, 3, 0, 2} indexed with i, and that index used on vec.
const spirv::IdRef newIndex = mBuilder.getNewId(); const spirv::IdRef newIndex = mBuilder.getNewId({});
spirv::WriteVectorExtractDynamic(mBuilder.getSpirvCurrentFunctionBlock(), uintTypeId, spirv::WriteVectorExtractDynamic(mBuilder.getSpirvCurrentFunctionBlock(), uintTypeId,
newIndex, swizzlesId, index); newIndex, swizzlesId, index);
...@@ -557,14 +564,15 @@ spirv::IdRef OutputSPIRVTraverser::accessChainCollapse(NodeData *data) ...@@ -557,14 +564,15 @@ spirv::IdRef OutputSPIRVTraverser::accessChainCollapse(NodeData *data)
const spirv::IdRef typePointerId = const spirv::IdRef typePointerId =
mBuilder.getTypePointerId(accessChain.preSwizzleTypeId, accessChain.storageClass); mBuilder.getTypePointerId(accessChain.preSwizzleTypeId, accessChain.storageClass);
accessChain.accessChainId = mBuilder.getNewId(); accessChain.accessChainId = mBuilder.getNewId({});
spirv::WriteAccessChain(mBuilder.getSpirvCurrentFunctionBlock(), typePointerId, spirv::WriteAccessChain(mBuilder.getSpirvCurrentFunctionBlock(), typePointerId,
accessChain.accessChainId, data->baseId, indexIds); accessChain.accessChainId, data->baseId, indexIds);
return accessChain.accessChainId; return accessChain.accessChainId;
} }
spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data) spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data,
const SpirvDecorations &decorations)
{ {
// Loading through the access chain can generate different instructions based on whether it's an // Loading through the access chain can generate different instructions based on whether it's an
// rvalue, the indices are literal, there's a swizzle etc. // rvalue, the indices are literal, there's a swizzle etc.
...@@ -595,7 +603,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data) ...@@ -595,7 +603,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data)
spirv::LiteralIntegerList indexList; spirv::LiteralIntegerList indexList;
makeAccessChainLiteralList(data, &indexList); makeAccessChainLiteralList(data, &indexList);
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(decorations);
spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(),
accessChain.preSwizzleTypeId, result, loadResult, accessChain.preSwizzleTypeId, result, loadResult,
indexList); indexList);
...@@ -605,7 +613,8 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data) ...@@ -605,7 +613,8 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data)
{ {
// Create a temp variable to hold the rvalue so an access chain can be made on it. // Create a temp variable to hold the rvalue so an access chain can be made on it.
const spirv::IdRef tempVar = mBuilder.declareVariable( const spirv::IdRef tempVar = mBuilder.declareVariable(
accessChain.preSwizzleTypeId, spv::StorageClassFunction, nullptr, "indexable"); accessChain.preSwizzleTypeId, spv::StorageClassFunction, decorations, nullptr,
"indexable");
// Write the rvalue into the temp variable // Write the rvalue into the temp variable
spirv::WriteStore(mBuilder.getSpirvCurrentFunctionBlock(), tempVar, loadResult, spirv::WriteStore(mBuilder.getSpirvCurrentFunctionBlock(), tempVar, loadResult,
...@@ -617,7 +626,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data) ...@@ -617,7 +626,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data)
// Load from the temp variable. // Load from the temp variable.
const spirv::IdRef accessChainId = accessChainCollapse(data); const spirv::IdRef accessChainId = accessChainCollapse(data);
loadResult = mBuilder.getNewId(); loadResult = mBuilder.getNewId(decorations);
spirv::WriteLoad(mBuilder.getSpirvCurrentFunctionBlock(), spirv::WriteLoad(mBuilder.getSpirvCurrentFunctionBlock(),
accessChain.preSwizzleTypeId, loadResult, accessChainId, nullptr); accessChain.preSwizzleTypeId, loadResult, accessChainId, nullptr);
} }
...@@ -627,7 +636,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data) ...@@ -627,7 +636,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data)
{ {
// Load from the access chain. // Load from the access chain.
const spirv::IdRef accessChainId = accessChainCollapse(data); const spirv::IdRef accessChainId = accessChainCollapse(data);
loadResult = mBuilder.getNewId(); loadResult = mBuilder.getNewId(decorations);
spirv::WriteLoad(mBuilder.getSpirvCurrentFunctionBlock(), accessChain.preSwizzleTypeId, spirv::WriteLoad(mBuilder.getSpirvCurrentFunctionBlock(), accessChain.preSwizzleTypeId,
loadResult, accessChainId, nullptr); loadResult, accessChainId, nullptr);
} }
...@@ -644,7 +653,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data) ...@@ -644,7 +653,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data)
swizzleList.push_back(spirv::LiteralInteger(component)); swizzleList.push_back(spirv::LiteralInteger(component));
} }
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(decorations);
spirv::WriteVectorShuffle(mBuilder.getSpirvCurrentFunctionBlock(), spirv::WriteVectorShuffle(mBuilder.getSpirvCurrentFunctionBlock(),
accessChain.postSwizzleTypeId, result, loadResult, loadResult, accessChain.postSwizzleTypeId, result, loadResult, loadResult,
swizzleList); swizzleList);
...@@ -657,7 +666,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data) ...@@ -657,7 +666,7 @@ spirv::IdRef OutputSPIRVTraverser::accessChainLoad(NodeData *data)
ASSERT(accessChain.swizzles.empty()); ASSERT(accessChain.swizzles.empty());
// Use OpVectorExtractDynamic to select the component. // Use OpVectorExtractDynamic to select the component.
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(decorations);
spirv::WriteVectorExtractDynamic(mBuilder.getSpirvCurrentFunctionBlock(), spirv::WriteVectorExtractDynamic(mBuilder.getSpirvCurrentFunctionBlock(),
accessChain.postDynamicComponentTypeId, result, loadResult, accessChain.postDynamicComponentTypeId, result, loadResult,
accessChain.dynamicComponent); accessChain.dynamicComponent);
...@@ -689,7 +698,7 @@ void OutputSPIRVTraverser::accessChainStore(NodeData *data, spirv::IdRef value) ...@@ -689,7 +698,7 @@ void OutputSPIRVTraverser::accessChainStore(NodeData *data, spirv::IdRef value)
if (!accessChain.swizzles.empty()) if (!accessChain.swizzles.empty())
{ {
// Load the vector before the swizzle. // Load the vector before the swizzle.
const spirv::IdRef loadResult = mBuilder.getNewId(); const spirv::IdRef loadResult = mBuilder.getNewId({});
spirv::WriteLoad(mBuilder.getSpirvCurrentFunctionBlock(), accessChain.preSwizzleTypeId, spirv::WriteLoad(mBuilder.getSpirvCurrentFunctionBlock(), accessChain.preSwizzleTypeId,
loadResult, accessChainId, nullptr); loadResult, accessChainId, nullptr);
...@@ -722,7 +731,7 @@ void OutputSPIRVTraverser::accessChainStore(NodeData *data, spirv::IdRef value) ...@@ -722,7 +731,7 @@ void OutputSPIRVTraverser::accessChainStore(NodeData *data, spirv::IdRef value)
// Use the generated swizzle to select components from the loaded vector and the value to be // Use the generated swizzle to select components from the loaded vector and the value to be
// written. Use the final result as the value to be written to the vector. // written. Use the final result as the value to be written to the vector.
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId({});
spirv::WriteVectorShuffle(mBuilder.getSpirvCurrentFunctionBlock(), spirv::WriteVectorShuffle(mBuilder.getSpirvCurrentFunctionBlock(),
accessChain.postSwizzleTypeId, result, loadResult, value, accessChain.postSwizzleTypeId, result, loadResult, value,
swizzleList); swizzleList);
...@@ -893,7 +902,9 @@ spirv::IdRef OutputSPIRVTraverser::createConstructor(TIntermAggregate *node, spi ...@@ -893,7 +902,9 @@ spirv::IdRef OutputSPIRVTraverser::createConstructor(TIntermAggregate *node, spi
// Take each constructor argument that is visited and evaluate it as rvalue // Take each constructor argument that is visited and evaluate it as rvalue
NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex]; NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex];
const spirv::IdRef paramValue = accessChainLoad(&param); const spirv::IdRef paramValue = accessChainLoad(
&param,
mBuilder.getDecorations(node->getChildNode(paramIndex)->getAsTyped()->getType()));
// TODO: handle mismatching types. http://anglebug.com/6000 // TODO: handle mismatching types. http://anglebug.com/6000
...@@ -970,7 +981,7 @@ spirv::IdRef OutputSPIRVTraverser::createArrayOrStructConstructor( ...@@ -970,7 +981,7 @@ spirv::IdRef OutputSPIRVTraverser::createArrayOrStructConstructor(
spirv::IdRef typeId, spirv::IdRef typeId,
const spirv::IdRefList &parameters) const spirv::IdRefList &parameters)
{ {
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(node->getType()));
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result,
parameters); parameters);
return result; return result;
...@@ -985,7 +996,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorVectorFromScalar( ...@@ -985,7 +996,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorVectorFromScalar(
ASSERT(parameters.size() == 1); ASSERT(parameters.size() == 1);
spirv::IdRefList replicatedParameter(type.getNominalSize(), parameters[0]); spirv::IdRefList replicatedParameter(type.getNominalSize(), parameters[0]);
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(type));
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result,
replicatedParameter); replicatedParameter);
return result; return result;
...@@ -1001,7 +1012,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorVectorFromNonScalar( ...@@ -1001,7 +1012,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorVectorFromNonScalar(
spirv::IdRefList extractedComponents; spirv::IdRefList extractedComponents;
extractComponents(node, node->getType().getNominalSize(), parameters, &extractedComponents); extractComponents(node, node->getType().getNominalSize(), parameters, &extractedComponents);
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(node->getType()));
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result,
extractedComponents); extractedComponents);
return result; return result;
...@@ -1025,6 +1036,8 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromScalar( ...@@ -1025,6 +1036,8 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromScalar(
const spirv::IdRef scalarId = parameters[0]; const spirv::IdRef scalarId = parameters[0];
spirv::IdRef zeroId; spirv::IdRef zeroId;
SpirvDecorations decorations = mBuilder.getDecorations(type);
switch (type.getBasicType()) switch (type.getBasicType())
{ {
case EbtFloat: case EbtFloat:
...@@ -1052,7 +1065,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromScalar( ...@@ -1052,7 +1065,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromScalar(
for (int columnIndex = 0; columnIndex < type.getCols(); ++columnIndex) for (int columnIndex = 0; columnIndex < type.getCols(); ++columnIndex)
{ {
columnIds.push_back(mBuilder.getNewId()); columnIds.push_back(mBuilder.getNewId(decorations));
// Place the scalar at the correct index (diagonal of the matrix, i.e. row == col). // Place the scalar at the correct index (diagonal of the matrix, i.e. row == col).
componentIds[columnIndex] = scalarId; componentIds[columnIndex] = scalarId;
...@@ -1067,7 +1080,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromScalar( ...@@ -1067,7 +1080,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromScalar(
} }
// Create the matrix out of the columns. // Create the matrix out of the columns.
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(decorations);
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result,
columnIds); columnIds);
return result; return result;
...@@ -1086,6 +1099,8 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromVectors( ...@@ -1086,6 +1099,8 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromVectors(
const TType &type = node->getType(); const TType &type = node->getType();
SpirvDecorations decorations = mBuilder.getDecorations(type);
spirv::IdRefList extractedComponents; spirv::IdRefList extractedComponents;
extractComponents(node, type.getCols() * type.getRows(), parameters, &extractedComponents); extractComponents(node, type.getCols() * type.getRows(), parameters, &extractedComponents);
...@@ -1098,7 +1113,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromVectors( ...@@ -1098,7 +1113,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromVectors(
// Chunk up the extracted components by column and construct intermediary vectors. // Chunk up the extracted components by column and construct intermediary vectors.
for (int columnIndex = 0; columnIndex < type.getCols(); ++columnIndex) for (int columnIndex = 0; columnIndex < type.getCols(); ++columnIndex)
{ {
columnIds.push_back(mBuilder.getNewId()); columnIds.push_back(mBuilder.getNewId(decorations));
auto componentsStart = extractedComponents.begin() + columnIndex * type.getRows(); auto componentsStart = extractedComponents.begin() + columnIndex * type.getRows();
const spirv::IdRefList componentIds(componentsStart, componentsStart + type.getRows()); const spirv::IdRefList componentIds(componentsStart, componentsStart + type.getRows());
...@@ -1108,7 +1123,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromVectors( ...@@ -1108,7 +1123,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromVectors(
columnIds.back(), componentIds); columnIds.back(), componentIds);
} }
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(decorations);
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result,
columnIds); columnIds);
return result; return result;
...@@ -1141,6 +1156,8 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix( ...@@ -1141,6 +1156,8 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix(
const TType &type = node->getType(); const TType &type = node->getType();
const TType &parameterType = (*node->getSequence())[0]->getAsTyped()->getType(); const TType &parameterType = (*node->getSequence())[0]->getAsTyped()->getType();
SpirvDecorations decorations = mBuilder.getDecorations(type);
// TODO: handle casting. http://anglebug.com/4889. // TODO: handle casting. http://anglebug.com/4889.
ASSERT(parameters.size() == 1); ASSERT(parameters.size() == 1);
...@@ -1167,7 +1184,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix( ...@@ -1167,7 +1184,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix(
for (int columnIndex = 0; columnIndex < type.getCols(); ++columnIndex) for (int columnIndex = 0; columnIndex < type.getCols(); ++columnIndex)
{ {
// Extract the column. // Extract the column.
const spirv::IdRef parameterColumnId = mBuilder.getNewId(); const spirv::IdRef parameterColumnId = mBuilder.getNewId(decorations);
spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), paramColumnTypeId, spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), paramColumnTypeId,
parameterColumnId, parameters[0], parameterColumnId, parameters[0],
{spirv::LiteralInteger(columnIndex)}); {spirv::LiteralInteger(columnIndex)});
...@@ -1176,7 +1193,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix( ...@@ -1176,7 +1193,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix(
spirv::IdRef constructorColumnId = parameterColumnId; spirv::IdRef constructorColumnId = parameterColumnId;
if (needsSwizzle) if (needsSwizzle)
{ {
constructorColumnId = mBuilder.getNewId(); constructorColumnId = mBuilder.getNewId(decorations);
spirv::WriteVectorShuffle(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId, spirv::WriteVectorShuffle(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId,
constructorColumnId, parameterColumnId, parameterColumnId, constructorColumnId, parameterColumnId, parameterColumnId,
swizzle); swizzle);
...@@ -1205,7 +1222,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix( ...@@ -1205,7 +1222,7 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix(
spirv::IdRef componentId; spirv::IdRef componentId;
if (componentIndex < parameterType.getRows()) if (componentIndex < parameterType.getRows())
{ {
componentId = mBuilder.getNewId(); componentId = mBuilder.getNewId(decorations);
spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(),
paramComponentTypeId, componentId, parameters[0], paramComponentTypeId, componentId, parameters[0],
{spirv::LiteralInteger(columnIndex), {spirv::LiteralInteger(columnIndex),
...@@ -1237,13 +1254,13 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix( ...@@ -1237,13 +1254,13 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix(
} }
// Create the column vector. // Create the column vector.
columnIds.push_back(mBuilder.getNewId()); columnIds.push_back(mBuilder.getNewId(decorations));
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId, spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId,
columnIds.back(), componentIds); columnIds.back(), componentIds);
} }
} }
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(decorations);
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result,
columnIds); columnIds);
return result; return result;
...@@ -1258,6 +1275,8 @@ void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node, ...@@ -1258,6 +1275,8 @@ void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node,
// more components than necessary) and extracts the first componentCount components. // more components than necessary) and extracts the first componentCount components.
const TIntermSequence &arguments = *node->getSequence(); const TIntermSequence &arguments = *node->getSequence();
SpirvDecorations decorations = mBuilder.getDecorations(node->getType());
// TODO: handle casting. http://anglebug.com/4889. // TODO: handle casting. http://anglebug.com/4889.
ASSERT(arguments.size() == parameters.size()); ASSERT(arguments.size() == parameters.size());
...@@ -1286,7 +1305,7 @@ void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node, ...@@ -1286,7 +1305,7 @@ void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node,
extractedComponentsOut->size() < componentCount; extractedComponentsOut->size() < componentCount;
++componentIndex) ++componentIndex)
{ {
const spirv::IdRef componentId = mBuilder.getNewId(); const spirv::IdRef componentId = mBuilder.getNewId(decorations);
spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(),
componentTypeId, componentId, parameterId, componentTypeId, componentId, parameterId,
{spirv::LiteralInteger(componentIndex)}); {spirv::LiteralInteger(componentIndex)});
...@@ -1313,7 +1332,7 @@ void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node, ...@@ -1313,7 +1332,7 @@ void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node,
extractedComponentsOut->size() < componentCount; extractedComponentsOut->size() < componentCount;
++componentIndex) ++componentIndex)
{ {
const spirv::IdRef componentId = mBuilder.getNewId(); const spirv::IdRef componentId = mBuilder.getNewId(decorations);
spirv::WriteCompositeExtract( spirv::WriteCompositeExtract(
mBuilder.getSpirvCurrentFunctionBlock(), componentTypeId, componentId, mBuilder.getSpirvCurrentFunctionBlock(), componentTypeId, componentId,
parameterId, parameterId,
...@@ -1368,6 +1387,7 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node, ...@@ -1368,6 +1387,7 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node,
NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex]; NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex];
spirv::IdRef paramValue; spirv::IdRef paramValue;
SpirvDecorations decorations = mBuilder.getDecorations(paramType);
if (IsOpaqueType(paramType.getBasicType()) || paramQualifier == EvqConst || if (IsOpaqueType(paramType.getBasicType()) || paramQualifier == EvqConst ||
IsAccessChainUnindexedLValue(param)) IsAccessChainUnindexedLValue(param))
...@@ -1377,7 +1397,7 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node, ...@@ -1377,7 +1397,7 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node,
// - Opaque uniforms, // - Opaque uniforms,
// - const parameters, // - const parameters,
// - unindexed lvalues. // - unindexed lvalues.
paramValue = accessChainLoad(&param); paramValue = accessChainLoad(&param, decorations);
} }
else else
{ {
...@@ -1386,8 +1406,9 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node, ...@@ -1386,8 +1406,9 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node,
// Need to create a temp variable and pass that. // Need to create a temp variable and pass that.
tempVarTypeIds[paramIndex] = mBuilder.getTypeData(paramType, EbsUnspecified).id; tempVarTypeIds[paramIndex] = mBuilder.getTypeData(paramType, EbsUnspecified).id;
tempVarIds[paramIndex] = mBuilder.declareVariable( tempVarIds[paramIndex] =
tempVarTypeIds[paramIndex], spv::StorageClassFunction, nullptr, "param"); mBuilder.declareVariable(tempVarTypeIds[paramIndex], spv::StorageClassFunction,
decorations, nullptr, "param");
// If it's an in or inout parameter, the temp variable needs to be initialized with the // If it's an in or inout parameter, the temp variable needs to be initialized with the
// value of the parameter first. // value of the parameter first.
...@@ -1395,7 +1416,7 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node, ...@@ -1395,7 +1416,7 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node,
// TODO: handle mismatching types. http://anglebug.com/6000 // TODO: handle mismatching types. http://anglebug.com/6000
if (paramQualifier == EvqIn || paramQualifier == EvqInOut) if (paramQualifier == EvqIn || paramQualifier == EvqInOut)
{ {
paramValue = accessChainLoad(&param); paramValue = accessChainLoad(&param, decorations);
spirv::WriteStore(mBuilder.getSpirvCurrentFunctionBlock(), tempVarIds[paramIndex], spirv::WriteStore(mBuilder.getSpirvCurrentFunctionBlock(), tempVarIds[paramIndex],
paramValue, nullptr); paramValue, nullptr);
} }
...@@ -1407,7 +1428,7 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node, ...@@ -1407,7 +1428,7 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node,
} }
// Make the actual function call. // Make the actual function call.
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(node->getType()));
spirv::WriteFunctionCall(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result, spirv::WriteFunctionCall(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result,
functionId, parameters); functionId, parameters);
...@@ -1419,7 +1440,8 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node, ...@@ -1419,7 +1440,8 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node,
continue; continue;
} }
const TQualifier &paramQualifier = function->getParam(paramIndex)->getType().getQualifier(); const TType &paramType = function->getParam(paramIndex)->getType();
const TQualifier &paramQualifier = paramType.getQualifier();
NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex]; NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex];
if (paramQualifier == EvqIn) if (paramQualifier == EvqIn)
...@@ -1433,7 +1455,8 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node, ...@@ -1433,7 +1455,8 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node,
NodeData tempVarData; NodeData tempVarData;
nodeDataInitLValue(&tempVarData, tempVarIds[paramIndex], tempVarTypeIds[paramIndex], nodeDataInitLValue(&tempVarData, tempVarIds[paramIndex], tempVarTypeIds[paramIndex],
spv::StorageClassFunction, EbsUnspecified); spv::StorageClassFunction, EbsUnspecified);
const spirv::IdRef tempVarValue = accessChainLoad(&tempVarData); const spirv::IdRef tempVarValue =
accessChainLoad(&tempVarData, mBuilder.getDecorations(paramType));
accessChainStore(&param, tempVarValue); accessChainStore(&param, tempVarValue);
} }
...@@ -1468,7 +1491,9 @@ spirv::IdRef OutputSPIRVTraverser::createAtomicBuiltIn(TIntermAggregate *node, ...@@ -1468,7 +1491,9 @@ spirv::IdRef OutputSPIRVTraverser::createAtomicBuiltIn(TIntermAggregate *node,
for (size_t paramIndex = 1; paramIndex < parameterCount; ++paramIndex) for (size_t paramIndex = 1; paramIndex < parameterCount; ++paramIndex)
{ {
NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex]; NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex];
parameters.push_back(accessChainLoad(&param)); parameters.push_back(accessChainLoad(
&param,
mBuilder.getDecorations(node->getChildNode(paramIndex)->getAsTyped()->getType())));
} }
// The scope of the operation is always Device as we don't enable the Vulkan memory model // The scope of the operation is always Device as we don't enable the Vulkan memory model
...@@ -1485,7 +1510,7 @@ spirv::IdRef OutputSPIRVTraverser::createAtomicBuiltIn(TIntermAggregate *node, ...@@ -1485,7 +1510,7 @@ spirv::IdRef OutputSPIRVTraverser::createAtomicBuiltIn(TIntermAggregate *node,
spirv::IdRef value); spirv::IdRef value);
WriteAtomicOp writeAtomicOp = nullptr; WriteAtomicOp writeAtomicOp = nullptr;
const spirv::IdRef result = mBuilder.getNewId(); const spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(node->getType()));
const bool isUnsigned = const bool isUnsigned =
node->getChildNode(0)->getAsTyped()->getType().getBasicType() == EbtUInt; node->getChildNode(0)->getAsTyped()->getType().getBasicType() == EbtUInt;
...@@ -1741,7 +1766,8 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1741,7 +1766,8 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
// Load the result of the right node right away. // Load the result of the right node right away.
spirv::IdRef typeId = getAccessChainTypeId(&mNodeData.back()); spirv::IdRef typeId = getAccessChainTypeId(&mNodeData.back());
spirv::IdRef rightValue = accessChainLoad(&mNodeData.back()); spirv::IdRef rightValue =
accessChainLoad(&mNodeData.back(), mBuilder.getDecorations(node->getRight()->getType()));
mNodeData.pop_back(); mNodeData.pop_back();
// For EOpIndex* operations, push the right value as an index to the left value's access chain. // For EOpIndex* operations, push the right value as an index to the left value's access chain.
...@@ -1943,7 +1969,8 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1943,7 +1969,8 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
if (writeBinaryOp) if (writeBinaryOp)
{ {
// Load the left value. // Load the left value.
spirv::IdRef leftValue = accessChainLoad(&left); spirv::IdRef leftValue =
accessChainLoad(&left, mBuilder.getDecorations(node->getLeft()->getType()));
typeId = mBuilder.getTypeData(node->getType(), EbsUnspecified).id; typeId = mBuilder.getTypeData(node->getType(), EbsUnspecified).id;
...@@ -1970,7 +1997,7 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1970,7 +1997,7 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
} }
// Write the operation that combines the left and right values. // Write the operation that combines the left and right values.
spirv::IdRef result = mBuilder.getNewId(); spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(node->getType()));
writeBinaryOp(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, leftValue, writeBinaryOp(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, leftValue,
rightValue); rightValue);
...@@ -2018,7 +2045,8 @@ bool OutputSPIRVTraverser::visitIfElse(Visit visit, TIntermIfElse *node) ...@@ -2018,7 +2045,8 @@ bool OutputSPIRVTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
// If the condition was just visited, evaluate it and create the branch instructions. // If the condition was just visited, evaluate it and create the branch instructions.
if (lastChildIndex == 0) if (lastChildIndex == 0)
{ {
const spirv::IdRef conditionValue = accessChainLoad(&mNodeData.back()); const spirv::IdRef conditionValue = accessChainLoad(
&mNodeData.back(), mBuilder.getDecorations(node->getCondition()->getType()));
// Create a conditional with maximum 3 blocks, one for the true block (if any), one for the // Create a conditional with maximum 3 blocks, one for the true block (if any), one for the
// else block (if any), and one for the merge block. getChildCount() works here as it // else block (if any), and one for the merge block. getChildCount() works here as it
...@@ -2139,12 +2167,14 @@ bool OutputSPIRVTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionD ...@@ -2139,12 +2167,14 @@ bool OutputSPIRVTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionD
for (size_t paramIndex = 0; paramIndex < function->getParamCount(); ++paramIndex) for (size_t paramIndex = 0; paramIndex < function->getParamCount(); ++paramIndex)
{ {
const spirv::IdRef paramId = mBuilder.getNewId(); const TVariable *paramVariable = function->getParam(paramIndex);
const spirv::IdRef paramId =
mBuilder.getNewId(mBuilder.getDecorations(paramVariable->getType()));
spirv::WriteFunctionParameter(mBuilder.getSpirvFunctions(), spirv::WriteFunctionParameter(mBuilder.getSpirvFunctions(),
ids.parameterTypeIds[paramIndex], paramId); ids.parameterTypeIds[paramIndex], paramId);
// Remember the id of the variable for future look up. // Remember the id of the variable for future look up.
const TVariable *paramVariable = function->getParam(paramIndex);
ASSERT(mSymbolIdMap.count(paramVariable) == 0); ASSERT(mSymbolIdMap.count(paramVariable) == 0);
mSymbolIdMap[paramVariable] = paramId; mSymbolIdMap[paramVariable] = paramId;
} }
...@@ -2216,7 +2246,10 @@ void OutputSPIRVTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node ...@@ -2216,7 +2246,10 @@ void OutputSPIRVTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node
ids.functionTypeId = mBuilder.getFunctionTypeId(ids.returnTypeId, ids.parameterTypeIds); ids.functionTypeId = mBuilder.getFunctionTypeId(ids.returnTypeId, ids.parameterTypeIds);
// Allocate an id for the function up-front. // Allocate an id for the function up-front.
ids.functionId = mBuilder.getNewId(); //
// Apply decorations to the return value of the function by applying them to the OpFunction
// instruction.
ids.functionId = mBuilder.getNewId(mBuilder.getDecorations(function->getReturnType()));
// Remember the ID of main() for the sake of OpEntryPoint. // Remember the ID of main() for the sake of OpEntryPoint.
if (function->isMain()) if (function->isMain())
...@@ -2361,7 +2394,8 @@ bool OutputSPIRVTraverser::visitDeclaration(Visit visit, TIntermDeclaration *nod ...@@ -2361,7 +2394,8 @@ bool OutputSPIRVTraverser::visitDeclaration(Visit visit, TIntermDeclaration *nod
else else
{ {
// Otherwise generate code to load from right hand side expression. // Otherwise generate code to load from right hand side expression.
initializerId = accessChainLoad(&mNodeData.back()); initializerId =
accessChainLoad(&mNodeData.back(), mBuilder.getDecorations(initializer->getType()));
} }
// TODO: handle mismatching types. http://anglebug.com/4889. // TODO: handle mismatching types. http://anglebug.com/4889.
...@@ -2387,8 +2421,8 @@ bool OutputSPIRVTraverser::visitDeclaration(Visit visit, TIntermDeclaration *nod ...@@ -2387,8 +2421,8 @@ bool OutputSPIRVTraverser::visitDeclaration(Visit visit, TIntermDeclaration *nod
spv::StorageClass storageClass = GetStorageClass(type); spv::StorageClass storageClass = GetStorageClass(type);
const spirv::IdRef variableId = mBuilder.declareVariable( const spirv::IdRef variableId = mBuilder.declareVariable(
typeId, storageClass, initializeWithDeclaration ? &initializerId : nullptr, typeId, storageClass, mBuilder.getDecorations(type),
mBuilder.hashName(variable).data()); initializeWithDeclaration ? &initializerId : nullptr, mBuilder.hashName(variable).data());
if (!initializeWithDeclaration && initializerId.valid()) if (!initializeWithDeclaration && initializerId.valid())
{ {
...@@ -2491,7 +2525,8 @@ bool OutputSPIRVTraverser::visitBranch(Visit visit, TIntermBranch *node) ...@@ -2491,7 +2525,8 @@ bool OutputSPIRVTraverser::visitBranch(Visit visit, TIntermBranch *node)
{ {
ASSERT(mNodeData.size() >= 1); ASSERT(mNodeData.size() >= 1);
const spirv::IdRef expressionValue = accessChainLoad(&mNodeData.back()); const spirv::IdRef expressionValue = accessChainLoad(
&mNodeData.back(), mBuilder.getDecorations(node->getExpression()->getType()));
mNodeData.pop_back(); mNodeData.pop_back();
// TODO: handle mismatching types. http://anglebug.com/6000 // TODO: handle mismatching types. http://anglebug.com/6000
...@@ -2537,10 +2572,13 @@ spirv::Blob OutputSPIRVTraverser::getSpirv() ...@@ -2537,10 +2572,13 @@ spirv::Blob OutputSPIRVTraverser::getSpirv()
} }
} // anonymous namespace } // anonymous namespace
bool OutputSPIRV(TCompiler *compiler, TIntermBlock *root, ShCompileOptions compileOptions) bool OutputSPIRV(TCompiler *compiler,
TIntermBlock *root,
ShCompileOptions compileOptions,
bool forceHighp)
{ {
// Traverse the tree and generate SPIR-V instructions // Traverse the tree and generate SPIR-V instructions
OutputSPIRVTraverser traverser(compiler, compileOptions); OutputSPIRVTraverser traverser(compiler, compileOptions, forceHighp);
root->traverse(&traverser); root->traverse(&traverser);
// Generate the final SPIR-V and store in the sink // Generate the final SPIR-V and store in the sink
......
...@@ -13,7 +13,10 @@ ...@@ -13,7 +13,10 @@
namespace sh namespace sh
{ {
bool OutputSPIRV(TCompiler *compiler, TIntermBlock *root, ShCompileOptions compileOptions); bool OutputSPIRV(TCompiler *compiler,
TIntermBlock *root,
ShCompileOptions compileOptions,
bool forceHighp);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_OUTPUTSPIRV_H_ #endif // COMPILER_TRANSLATOR_OUTPUTSPIRV_H_
...@@ -1313,7 +1313,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root, ...@@ -1313,7 +1313,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
return false; return false;
} }
return OutputSPIRV(this, root, compileOptions); return OutputSPIRV(this, root, compileOptions, precisionEmulation);
} }
#endif #endif
......
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