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
......@@ -9,6 +9,7 @@
#ifndef COMPILER_TRANSLATOR_BUILDSPIRV_H_
#define COMPILER_TRANSLATOR_BUILDSPIRV_H_
#include "common/FixedVector.h"
#include "common/hash_utils.h"
#include "common/spirv/spirv_instruction_builder_autogen.h"
#include "compiler/translator/Compiler.h"
......@@ -156,6 +157,16 @@ struct SpirvTypeData
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
// 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
......@@ -213,11 +224,13 @@ class SPIRVBuilder : angle::NonCopyable
public:
SPIRVBuilder(TCompiler *compiler,
ShCompileOptions compileOptions,
bool forceHighp,
ShHashFunction64 hashFunction,
NameMap &nameMap)
: mCompiler(compiler),
mCompileOptions(compileOptions),
mShaderType(gl::FromGLenum<gl::ShaderType>(compiler->getShaderType())),
mDisableRelaxedPrecision(forceHighp),
mNextAvailableId(1),
mHashFunction(hashFunction),
mNameMap(nameMap),
......@@ -226,13 +239,16 @@ class SPIRVBuilder : angle::NonCopyable
mNextUnusedOutputLocation(0)
{}
spirv::IdRef getNewId();
spirv::IdRef getNewId(const SpirvDecorations &decorations);
SpirvType getSpirvType(const TType &type, TLayoutBlockStorage blockStorage) const;
const SpirvTypeData &getTypeData(const TType &type, TLayoutBlockStorage blockStorage);
const SpirvTypeData &getSpirvTypeData(const SpirvType &type, const char *blockName);
spirv::IdRef getTypePointerId(spirv::IdRef typeId, spv::StorageClass storageClass);
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 *getSpirvDecorations() { return &mSpirvDecorations; }
spirv::Blob *getSpirvTypeAndConstantDecls() { return &mSpirvTypeAndConstantDecls; }
......@@ -264,11 +280,6 @@ class SPIRVBuilder : angle::NonCopyable
void writePerVertexBuiltIns(const TType &type, spirv::IdRef typeId);
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 getUintConstant(uint32_t value);
spirv::IdRef getIntConstant(int32_t value);
......@@ -283,6 +294,7 @@ class SPIRVBuilder : angle::NonCopyable
// the current function.
spirv::IdRef declareVariable(spirv::IdRef typeId,
spv::StorageClass storageClass,
const SpirvDecorations &decorations,
spirv::IdRef *initializerId,
const char *name);
// Helper to declare specialization constants.
......@@ -308,6 +320,12 @@ class SPIRVBuilder : angle::NonCopyable
private:
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.
void getImageTypeParameters(TBasicType type,
spirv::IdRef *sampledTypeOut,
......@@ -329,8 +347,9 @@ class SPIRVBuilder : angle::NonCopyable
void generateExecutionModes(spirv::Blob *blob);
ANGLE_MAYBE_UNUSED TCompiler *mCompiler;
ANGLE_MAYBE_UNUSED ShCompileOptions mCompileOptions;
ShCompileOptions mCompileOptions;
gl::ShaderType mShaderType;
const bool mDisableRelaxedPrecision;
// Capabilities the shader is using. Accumulated as the instructions are generated. The Shader
// capability is unconditionally generated, so it's not tracked.
......
......@@ -186,14 +186,6 @@ bool CanFoldAggregateBuiltInOp(TOperator op)
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) \
do \
{ \
......
......@@ -170,6 +170,7 @@ class TIntermTyped : public TIntermNode
bool isVector() const { return getType().isVector(); }
bool isScalar() const { return getType().isScalar(); }
bool isScalarInt() const { return getType().isScalarInt(); }
bool isPrecise() const { return getType().isPrecise(); }
const char *getBasicString() const { return getType().getBasicString(); }
unsigned int getOutermostArraySize() const { return getType().getOutermostArraySize(); }
......@@ -303,7 +304,6 @@ class TIntermExpression : public TIntermTyped
protected:
TType *getTypePointer() { return &mType; }
void setType(const TType &t) { mType = t; }
void setTypePreservePrecision(const TType &t);
TIntermExpression(const TIntermExpression &node) = default;
......
......@@ -13,7 +13,10 @@
namespace sh
{
bool OutputSPIRV(TCompiler *compiler, TIntermBlock *root, ShCompileOptions compileOptions);
bool OutputSPIRV(TCompiler *compiler,
TIntermBlock *root,
ShCompileOptions compileOptions,
bool forceHighp);
} // namespace sh
#endif // COMPILER_TRANSLATOR_OUTPUTSPIRV_H_
......@@ -1313,7 +1313,7 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
return false;
}
return OutputSPIRV(this, root, compileOptions);
return OutputSPIRV(this, root, compileOptions, precisionEmulation);
}
#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