Commit dc1c1cb5 by Xinghua Cao Committed by Commit Bot

Restrict to translate uniform block to StructuredBuffer

We had translated an uniform block only containing a large array member into StructuredBuffer instead of cbuffer on D3D backend for slow fxc compile performance issue with dynamic uniform indexing. Now we add more conditions to restrict the translation. Only indexing operator is allowed to operate on this uniform block variable. And we also restrict the types of uniform block's member. Bug: angleproject:3682 Change-Id: I992b7890d84fcaa6169722af6d7e14785526d48a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2351728 Commit-Queue: Xinghua Cao <xinghua.cao@intel.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJiajia Qin <jiajia.qin@intel.com>
parent 3980b1f8
......@@ -26,7 +26,7 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 236
#define ANGLE_SH_VERSION 237
enum ShShaderSpec
{
......@@ -315,9 +315,8 @@ const ShCompileOptions SH_ADD_BASE_VERTEX_TO_VERTEX_ID = UINT64_C(1) << 48;
// This works around the dynamic lvalue indexing of swizzled vectors on various platforms.
const ShCompileOptions SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR = UINT64_C(1) << 49;
// This flag works a driver bug that fails to allocate ShaderResourceView for StructuredBuffer
// on Windows 7 and earlier.
const ShCompileOptions SH_DONT_TRANSLATE_UNIFORM_BLOCK_TO_STRUCTUREDBUFFER = UINT64_C(1) << 50;
// This flag works around a slow fxc compile performance issue with dynamic uniform indexing.
const ShCompileOptions SH_ALLOW_TRANSLATE_UNIFORM_BLOCK_TO_STRUCTUREDBUFFER = UINT64_C(1) << 50;
// This flag indicates whether Bresenham line raster emulation code should be generated. This
// emulation is necessary if the backend uses a differnet algorithm to draw lines. Currently only
......
......@@ -207,11 +207,13 @@ struct FeaturesD3D : FeatureSetBase
"Some drivers corrupt texture data when clearing for robust resource initialization.",
&members, "http://crbug.com/941620"};
// Don't translate uniform block to StructuredBuffer on Windows 7 and earlier. This is targeted
// to work around a bug that fails to allocate ShaderResourceView for StructuredBuffer.
Feature dontTranslateUniformBlockToStructuredBuffer = {
"dont_translate_uniform_block_to_structured_buffer", FeatureCategory::D3DWorkarounds,
"Fails to allocate ShaderResourceView for StructuredBuffer on some drivers", &members};
// Allow translating uniform block to StructuredBuffer. This is targeted to work around a slow
// fxc compile performance issue with dynamic uniform indexing. http://anglebug.com/3682
Feature allowTranslateUniformBlockToStructuredBuffer = {
"allow_translate_uniform_block_to_structured_buffer", FeatureCategory::D3DWorkarounds,
"There is a slow fxc compile performance issue with dynamic uniform indexing if "
"translating a uniform block with a large array member to cbuffer.",
&members, "http://anglebug.com/3682"};
};
inline FeaturesD3D::FeaturesD3D() = default;
......
......@@ -148,6 +148,8 @@ angle_translator_sources = [
"src/compiler/translator/tree_ops/PruneNoOps.h",
"src/compiler/translator/tree_ops/RecordConstantPrecision.cpp",
"src/compiler/translator/tree_ops/RecordConstantPrecision.h",
"src/compiler/translator/tree_ops/RecordUniformBlocksTranslatedToStructuredBuffers.cpp",
"src/compiler/translator/tree_ops/RecordUniformBlocksTranslatedToStructuredBuffers.h",
"src/compiler/translator/tree_ops/RegenerateStructNames.cpp",
"src/compiler/translator/tree_ops/RegenerateStructNames.h",
"src/compiler/translator/tree_ops/RemoveArrayLengthMethod.cpp",
......
......@@ -297,20 +297,22 @@ const TConstantUnion *OutputHLSL::writeConstantUnionArray(TInfoSinkBase &out,
return constUnionIterated;
}
OutputHLSL::OutputHLSL(sh::GLenum shaderType,
ShShaderSpec shaderSpec,
int shaderVersion,
const TExtensionBehavior &extensionBehavior,
const char *sourcePath,
ShShaderOutput outputType,
int numRenderTargets,
int maxDualSourceDrawBuffers,
const std::vector<ShaderVariable> &uniforms,
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics,
const std::vector<InterfaceBlock> &shaderStorageBlocks)
OutputHLSL::OutputHLSL(
sh::GLenum shaderType,
ShShaderSpec shaderSpec,
int shaderVersion,
const TExtensionBehavior &extensionBehavior,
const char *sourcePath,
ShShaderOutput outputType,
int numRenderTargets,
int maxDualSourceDrawBuffers,
const std::vector<ShaderVariable> &uniforms,
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics,
const std::map<int, const TInterfaceBlock *> &uniformBlocksTranslatedToStructuredBuffers,
const std::vector<InterfaceBlock> &shaderStorageBlocks)
: TIntermTraverser(true, true, true, symbolTable),
mShaderType(shaderType),
mShaderSpec(shaderSpec),
......@@ -321,6 +323,7 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
mCompileOptions(compileOptions),
mInsideFunction(false),
mInsideMain(false),
mUniformBlocksTranslatedToStructuredBuffers(uniformBlocksTranslatedToStructuredBuffers),
mNumRenderTargets(numRenderTargets),
mMaxDualSourceDrawBuffers(maxDualSourceDrawBuffers),
mCurrentFunctionMetadata(nullptr),
......@@ -371,8 +374,7 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
unsigned int firstUniformRegister =
((compileOptions & SH_SKIP_D3D_CONSTANT_REGISTER_ZERO) != 0) ? 1u : 0u;
mResourcesHLSL = new ResourcesHLSL(mStructureHLSL, outputType, compileOptions, uniforms,
firstUniformRegister);
mResourcesHLSL = new ResourcesHLSL(mStructureHLSL, outputType, uniforms, firstUniformRegister);
if (mOutputType == SH_HLSL_3_0_OUTPUT)
{
......@@ -659,7 +661,8 @@ void OutputHLSL::header(TInfoSinkBase &out,
out << mStructureHLSL->structsHeader();
mResourcesHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms, mSymbolTable);
out << mResourcesHLSL->uniformBlocksHeader(mReferencedUniformBlocks);
out << mResourcesHLSL->uniformBlocksHeader(mReferencedUniformBlocks,
mUniformBlocksTranslatedToStructuredBuffers);
mSSBOOutputHLSL->writeShaderStorageBlocksHeader(out);
if (!mEqualityFunctions.empty())
......@@ -1647,14 +1650,18 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
{
const TInterfaceBlock *interfaceBlock =
GetInterfaceBlockOfUniformBlockNearestIndexOperator(node->getLeft());
if (interfaceBlock &&
mResourcesHLSL->shouldTranslateUniformBlockToStructuredBuffer(
*interfaceBlock))
if (interfaceBlock && mUniformBlocksTranslatedToStructuredBuffers.count(
interfaceBlock->uniqueId().get()) != 0)
{
const TField *field = interfaceBlock->fields()[0];
if (field->type()->isMatrix())
// If the uniform block member's type is not structure, we had explicitly
// packed the member into a structure, so need to add an operator of field
// slection.
const TField *field = interfaceBlock->fields()[0];
const TType *fieldType = field->type();
if (fieldType->isMatrix() || fieldType->isVectorArray() ||
fieldType->isScalarArray())
{
out << "._matrix_" << Decorate(field->name());
out << "." << Decorate(field->name());
}
}
}
......@@ -1678,14 +1685,18 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
{
const TInterfaceBlock *interfaceBlock =
GetInterfaceBlockOfUniformBlockNearestIndexOperator(node->getLeft());
if (interfaceBlock &&
mResourcesHLSL->shouldTranslateUniformBlockToStructuredBuffer(
*interfaceBlock))
if (interfaceBlock && mUniformBlocksTranslatedToStructuredBuffers.count(
interfaceBlock->uniqueId().get()) != 0)
{
const TField *field = interfaceBlock->fields()[0];
if (field->type()->isMatrix())
// If the uniform block member's type is not structure, we had explicitly
// packed the member into a structure, so need to add an operator of field
// slection.
const TField *field = interfaceBlock->fields()[0];
const TType *fieldType = field->type();
if (fieldType->isMatrix() || fieldType->isVectorArray() ||
fieldType->isScalarArray())
{
out << "._matrix_" << Decorate(field->name());
out << "." << Decorate(field->name());
}
}
}
......@@ -1746,8 +1757,8 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
node->getLeft()->getType().getInterfaceBlock();
const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
const TField *field = interfaceBlock->fields()[index->getIConst(0)];
if (structInStd140UniformBlock ||
mResourcesHLSL->shouldTranslateUniformBlockToStructuredBuffer(*interfaceBlock))
if (structInStd140UniformBlock || mUniformBlocksTranslatedToStructuredBuffers.count(
interfaceBlock->uniqueId().get()) != 0)
{
out << "_";
}
......
......@@ -37,20 +37,22 @@ using ReferencedVariables = std::map<int, const TVariable *>;
class OutputHLSL : public TIntermTraverser
{
public:
OutputHLSL(sh::GLenum shaderType,
ShShaderSpec shaderSpec,
int shaderVersion,
const TExtensionBehavior &extensionBehavior,
const char *sourcePath,
ShShaderOutput outputType,
int numRenderTargets,
int maxDualSourceDrawBuffers,
const std::vector<ShaderVariable> &uniforms,
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics,
const std::vector<InterfaceBlock> &shaderStorageBlocks);
OutputHLSL(
sh::GLenum shaderType,
ShShaderSpec shaderSpec,
int shaderVersion,
const TExtensionBehavior &extensionBehavior,
const char *sourcePath,
ShShaderOutput outputType,
int numRenderTargets,
int maxDualSourceDrawBuffers,
const std::vector<ShaderVariable> &uniforms,
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics,
const std::map<int, const TInterfaceBlock *> &uniformBlocksTranslatedToStructuredBuffers,
const std::vector<InterfaceBlock> &shaderStorageBlocks);
~OutputHLSL() override;
......@@ -179,6 +181,8 @@ class OutputHLSL : public TIntermTraverser
// Indexed by block id, not instance id.
ReferencedInterfaceBlocks mReferencedUniformBlocks;
std::map<int, const TInterfaceBlock *> mUniformBlocksTranslatedToStructuredBuffers;
ReferencedVariables mReferencedAttributes;
ReferencedVariables mReferencedVaryings;
ReferencedVariables mReferencedOutputVariables;
......
......@@ -24,11 +24,6 @@ namespace
{
constexpr const ImmutableString kAngleDecorString("angle_");
// D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT = 128;
const unsigned int kMaxInputResourceSlotCount = 128u;
// If uniform block member's array size is larger than kMinArraySizeUseStructuredBuffer,
// then we translate uniform block to StructuredBuffer for compiling performance.
const unsigned int kMinArraySizeUseStructuredBuffer = 50u;
static const char *UniformRegisterPrefix(const TType &type)
{
......@@ -104,46 +99,72 @@ void OutputUniformIndexArrayInitializer(TInfoSinkBase &out,
out << "}";
}
// Check whether all fields match std140 storage layout, and do not need to add paddings
// when translating std140 uniform block to StructuredBuffer.
static bool ShouldPadUniformBlockMemberForStructuredBuffer(const TType &type)
static TString InterfaceBlockScalarVectorFieldPaddingString(const TType &type)
{
const TStructure *structure = type.getStruct();
if (structure)
switch (type.getBasicType())
{
const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); i++)
{
if (ShouldPadUniformBlockMemberForStructuredBuffer(*fields[i]->type()))
case EbtFloat:
switch (type.getNominalSize())
{
return true;
case 1:
return "float3 padding;";
case 2:
return "float2 padding;";
case 3:
return "float padding;";
default:
break;
}
}
return false;
}
else if (type.isMatrix())
{
if ((type.getLayoutQualifier().matrixPacking != EmpRowMajor && type.getRows() == 4) ||
(type.getLayoutQualifier().matrixPacking == EmpRowMajor && type.getCols() == 4))
{
return false;
}
}
else
{
if (type.isVector() && type.getNominalSize() == 4)
{
return false;
}
break;
case EbtInt:
switch (type.getNominalSize())
{
case 1:
return "int3 padding;";
case 2:
return "int2 padding;";
case 3:
return "int padding";
default:
break;
}
break;
case EbtUInt:
switch (type.getNominalSize())
{
case 1:
return "uint3 padding;";
case 2:
return "uint2 padding;";
case 3:
return "uint padding;";
default:
break;
}
break;
case EbtBool:
switch (type.getNominalSize())
{
case 1:
return "bool3 padding;";
case 2:
return "bool2 padding;";
case 3:
return "bool padding;";
default:
break;
}
break;
default:
break;
}
return true;
return "";
}
} // anonymous namespace
ResourcesHLSL::ResourcesHLSL(StructureHLSL *structureHLSL,
ShShaderOutput outputType,
ShCompileOptions compileOptions,
const std::vector<ShaderVariable> &uniforms,
unsigned int firstUniformRegister)
: mUniformRegister(firstUniformRegister),
......@@ -153,7 +174,6 @@ ResourcesHLSL::ResourcesHLSL(StructureHLSL *structureHLSL,
mSamplerCount(0),
mStructureHLSL(structureHLSL),
mOutputType(outputType),
mCompileOptions(compileOptions),
mUniforms(uniforms)
{}
......@@ -676,7 +696,8 @@ void ResourcesHLSL::imageMetadataUniforms(TInfoSinkBase &out, unsigned int regIn
}
TString ResourcesHLSL::uniformBlocksHeader(
const ReferencedInterfaceBlocks &referencedInterfaceBlocks)
const ReferencedInterfaceBlocks &referencedInterfaceBlocks,
const std::map<int, const TInterfaceBlock *> &uniformBlockTranslatedToStructuredBuffer)
{
TString interfaceBlocks;
......@@ -691,7 +712,7 @@ TString ResourcesHLSL::uniformBlocksHeader(
// In order to avoid compile performance issue, translate uniform block to structured
// buffer. anglebug.com/3682.
if (shouldTranslateUniformBlockToStructuredBuffer(interfaceBlock))
if (uniformBlockTranslatedToStructuredBuffer.count(interfaceBlock.uniqueId().get()) != 0)
{
unsigned int structuredBufferRegister = mSRVRegister;
if (instanceVariable != nullptr && instanceVariable->getType().isArray())
......@@ -820,10 +841,22 @@ TString ResourcesHLSL::uniformBlockWithOneLargeArrayMemberString(
{
if (arrayIndex == GL_INVALID_INDEX || arrayIndex == 0)
{
hlsl += "struct matrix" + Decorate(field.name()) + " { " + typeString + " _matrix_" +
hlsl += "struct pack" + Decorate(interfaceBlock.name()) + " { " + typeString + " " +
Decorate(field.name()) + "; };\n";
}
typeString = "matrix" + Decorate(field.name());
typeString = "pack" + Decorate(interfaceBlock.name());
}
else if (fieldType.isVectorArray() || fieldType.isScalarArray())
{
// If the member is an array of scalars or vectors, std140 rules require the base array
// stride are rounded up to the base alignment of a vec4.
if (arrayIndex == GL_INVALID_INDEX || arrayIndex == 0)
{
hlsl += "struct pack" + Decorate(interfaceBlock.name()) + " { " + typeString + " " +
Decorate(field.name()) + ";\n";
hlsl += InterfaceBlockScalarVectorFieldPaddingString(fieldType) + " };\n";
}
typeString = "pack" + Decorate(interfaceBlock.name());
}
if (instanceVariable != nullptr)
......@@ -890,7 +923,7 @@ TString ResourcesHLSL::uniformBlockMembersString(const TInterfaceBlock &interfac
if (blockStorage == EbsStd140)
{
// 2 and 3 component vector types in some cases need pre-padding
hlsl += padHelper.prePaddingString(fieldType);
hlsl += padHelper.prePaddingString(fieldType, false);
}
hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage, false) + " " +
......@@ -918,18 +951,4 @@ TString ResourcesHLSL::uniformBlockStructString(const TInterfaceBlock &interface
"{\n" +
uniformBlockMembersString(interfaceBlock, blockStorage) + "};\n\n";
}
bool ResourcesHLSL::shouldTranslateUniformBlockToStructuredBuffer(
const TInterfaceBlock &interfaceBlock)
{
const TType &fieldType = *interfaceBlock.fields()[0]->type();
// Restrict field and sub-fields types match std140 storage layout rules, even the uniform
// does not use std140 qualifier.
bool shouldPadUniformBlockMember = ShouldPadUniformBlockMemberForStructuredBuffer(fieldType);
return (mCompileOptions & SH_DONT_TRANSLATE_UNIFORM_BLOCK_TO_STRUCTUREDBUFFER) == 0 &&
mSRVRegister < kMaxInputResourceSlotCount && interfaceBlock.fields().size() == 1u &&
!shouldPadUniformBlockMember && fieldType.getNumArraySizes() == 1u &&
fieldType.getOutermostArraySize() >= kMinArraySizeUseStructuredBuffer;
}
} // namespace sh
......@@ -24,7 +24,6 @@ class ResourcesHLSL : angle::NonCopyable
public:
ResourcesHLSL(StructureHLSL *structureHLSL,
ShShaderOutput outputType,
ShCompileOptions compileOptions,
const std::vector<ShaderVariable> &uniforms,
unsigned int firstUniformRegister);
......@@ -39,7 +38,9 @@ class ResourcesHLSL : angle::NonCopyable
void samplerMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex);
unsigned int getSamplerCount() const { return mSamplerCount; }
void imageMetadataUniforms(TInfoSinkBase &out, unsigned int regIndex);
TString uniformBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks);
TString uniformBlocksHeader(
const ReferencedInterfaceBlocks &referencedInterfaceBlocks,
const std::map<int, const TInterfaceBlock *> &uniformBlockTranslatedToStructuredBuffer);
TString shaderStorageBlocksHeader(const ReferencedInterfaceBlocks &referencedInterfaceBlocks);
// Used for direct index references
......@@ -68,7 +69,6 @@ class ResourcesHLSL : angle::NonCopyable
unsigned int getReadonlyImage2DRegisterIndex() const { return mReadonlyImage2DRegisterIndex; }
unsigned int getImage2DRegisterIndex() const { return mImage2DRegisterIndex; }
bool shouldTranslateUniformBlockToStructuredBuffer(const TInterfaceBlock &interfaceBlock);
private:
TString uniformBlockString(const TInterfaceBlock &interfaceBlock,
......@@ -138,7 +138,6 @@ class ResourcesHLSL : angle::NonCopyable
unsigned int mImageCount;
StructureHLSL *mStructureHLSL;
ShShaderOutput mOutputType;
ShCompileOptions mCompileOptions;
const std::vector<ShaderVariable> &mUniforms;
std::map<std::string, unsigned int> mUniformBlockRegisterMap;
......
......@@ -23,13 +23,13 @@ namespace
TString Define(const TStructure &structure,
bool useHLSLRowMajorPacking,
bool useStd140Packing,
bool forcePackingEnd,
bool forcePadding,
Std140PaddingHelper *padHelper)
{
const TFieldList &fields = structure.fields();
const bool isNameless = (structure.symbolType() == SymbolType::Empty);
const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking,
useStd140Packing, forcePackingEnd);
useStd140Packing, forcePadding);
const TString declareString = (isNameless ? "struct" : "struct " + structName);
TString string;
......@@ -52,7 +52,8 @@ TString Define(const TStructure &structure,
if (padHelper)
{
string += padHelper->prePaddingString(fieldType);
string += padHelper->prePaddingString(
fieldType, (memberSize != fields.size() - 1) && forcePadding);
}
string += " " + fieldTypeString + " " + DecorateField(field->name(), structure) +
......@@ -61,7 +62,7 @@ TString Define(const TStructure &structure,
if (padHelper)
{
string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking,
memberSize == 0 && forcePackingEnd);
memberSize == 0 && forcePadding);
}
}
}
......@@ -118,7 +119,7 @@ TString Std140PaddingHelper::next()
return str(value);
}
int Std140PaddingHelper::prePadding(const TType &type)
int Std140PaddingHelper::prePadding(const TType &type, bool forcePadding)
{
if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
{
......@@ -139,9 +140,20 @@ int Std140PaddingHelper::prePadding(const TType &type)
if (mElementIndex + numComponents > 4)
{
// no padding needed, HLSL will align the field to a new register
mElementIndex = numComponents;
return 0;
if (forcePadding)
{
// If this structure will be used as HLSL StructuredBuffer member's type, we should add
// padding between the structure's members to follow the std140 rules manually.
const int forcePaddingCount = 4 - mElementIndex;
mElementIndex = numComponents;
return forcePaddingCount;
}
else
{
// no padding needed, HLSL will align the field to a new register
mElementIndex = numComponents;
return 0;
}
}
const int alignment = numComponents == 3 ? 4 : numComponents;
......@@ -155,9 +167,9 @@ int Std140PaddingHelper::prePadding(const TType &type)
return paddingCount;
}
TString Std140PaddingHelper::prePaddingString(const TType &type)
TString Std140PaddingHelper::prePaddingString(const TType &type, bool forcePadding)
{
int paddingCount = prePadding(type);
int paddingCount = prePadding(type, forcePadding);
TString padding;
......@@ -173,8 +185,21 @@ TString Std140PaddingHelper::postPaddingString(const TType &type,
bool useHLSLRowMajorPacking,
bool forcePadding)
{
if (!forcePadding && !type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
{
if (forcePadding)
{
// If this structure will be used as HLSL StructuredBuffer member's type, we
// should force to pad the end of the structure to follow the std140 rules.
TString forcePaddingStr;
const int paddingOffset = mElementIndex % 4;
const int paddingCount = paddingOffset != 0 ? (4 - paddingOffset) : 0;
for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++)
{
forcePaddingStr += " float pad_" + next() + ";\n";
}
return forcePaddingStr;
}
return "";
}
......@@ -229,12 +254,12 @@ Std140PaddingHelper StructureHLSL::getPaddingHelper()
TString StructureHLSL::defineQualified(const TStructure &structure,
bool useHLSLRowMajorPacking,
bool useStd140Packing,
bool forcePackingEnd)
bool forcePadding)
{
if (useStd140Packing)
{
Std140PaddingHelper padHelper = getPaddingHelper();
return Define(structure, useHLSLRowMajorPacking, useStd140Packing, forcePackingEnd,
return Define(structure, useHLSLRowMajorPacking, useStd140Packing, forcePadding,
&padHelper);
}
else
......@@ -282,19 +307,19 @@ StructureHLSL::DefinedStructs::iterator StructureHLSL::defineVariants(const TStr
defineQualified(structure, true, true, false) +
"#pragma pack_matrix(column_major)\n";
// Must use packed structure for StructuredBuffer element type, if qualifier of structure is
// std140.
TString std140PackingEndString = defineQualified(structure, false, true, true);
TString std140RowMajorPackEndingString = "#pragma pack_matrix(row_major)\n" +
defineQualified(structure, true, true, true) +
"#pragma pack_matrix(column_major)\n";
// Must force to pad the structure's elements for StructuredBuffer's element type, if qualifier
// of structure is std140.
TString std140ForcePaddingString = defineQualified(structure, false, true, true);
TString std140RowMajorForcePaddingString = "#pragma pack_matrix(row_major)\n" +
defineQualified(structure, true, true, true) +
"#pragma pack_matrix(column_major)\n";
mStructDeclarations.push_back(structString);
mStructDeclarations.push_back(rowMajorString);
mStructDeclarations.push_back(std140String);
mStructDeclarations.push_back(std140RowMajorString);
mStructDeclarations.push_back(std140PackingEndString);
mStructDeclarations.push_back(std140RowMajorPackEndingString);
mStructDeclarations.push_back(std140ForcePaddingString);
mStructDeclarations.push_back(std140RowMajorForcePaddingString);
return addedStruct;
}
......@@ -596,7 +621,7 @@ void StructureHLSL::storeStd140ElementIndex(const TStructure &structure,
for (const TField *field : fields)
{
padHelper.prePadding(*field->type());
padHelper.prePadding(*field->type(), false);
}
// Add remaining element index to the global map, for use with nested structs in standard
......
......@@ -32,8 +32,8 @@ class Std140PaddingHelper
Std140PaddingHelper &operator=(const Std140PaddingHelper &other);
int elementIndex() const { return mElementIndex; }
int prePadding(const TType &type);
TString prePaddingString(const TType &type);
int prePadding(const TType &type, bool forcePadding);
TString prePaddingString(const TType &type, bool forcePadding);
TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking, bool forcePadding);
private:
......
......@@ -12,6 +12,7 @@
#include "compiler/translator/tree_ops/BreakVariableAliasingInInnerLoops.h"
#include "compiler/translator/tree_ops/ExpandIntegerPowExpressions.h"
#include "compiler/translator/tree_ops/PruneEmptyCases.h"
#include "compiler/translator/tree_ops/RecordUniformBlocksTranslatedToStructuredBuffers.h"
#include "compiler/translator/tree_ops/RemoveDynamicIndexing.h"
#include "compiler/translator/tree_ops/RewriteAtomicFunctionExpressions.h"
#include "compiler/translator/tree_ops/RewriteElseBlocks.h"
......@@ -183,11 +184,25 @@ bool TranslatorHLSL::translate(TIntermBlock *root,
}
}
sh::OutputHLSL outputHLSL(getShaderType(), getShaderSpec(), getShaderVersion(),
getExtensionBehavior(), getSourcePath(), getOutputType(),
numRenderTargets, maxDualSourceDrawBuffers, getUniforms(),
compileOptions, getComputeShaderLocalSize(), &getSymbolTable(),
perfDiagnostics, mShaderStorageBlocks);
mUniformBlocksTranslatedToStructuredBuffers.clear();
// In order to get the exact maximum of slots are available for shader resources, which would
// been bound with StructuredBuffer, we only translate uniform block with a large array member
// into StructuredBuffer when shader version is 300.
if (getShaderVersion() == 300 &&
(compileOptions & SH_ALLOW_TRANSLATE_UNIFORM_BLOCK_TO_STRUCTUREDBUFFER) != 0)
{
if (!sh::RecordUniformBlocksTranslatedToStructuredBuffers(
root, mUniformBlocksTranslatedToStructuredBuffers))
{
return false;
}
}
sh::OutputHLSL outputHLSL(
getShaderType(), getShaderSpec(), getShaderVersion(), getExtensionBehavior(),
getSourcePath(), getOutputType(), numRenderTargets, maxDualSourceDrawBuffers, getUniforms(),
compileOptions, getComputeShaderLocalSize(), &getSymbolTable(), perfDiagnostics,
mUniformBlocksTranslatedToStructuredBuffers, mShaderStorageBlocks);
outputHLSL.output(root, getInfoSink().obj);
......
......@@ -46,6 +46,7 @@ class TranslatorHLSL : public TCompiler
unsigned int mReadonlyImage2DRegisterIndex;
unsigned int mImage2DRegisterIndex;
std::set<std::string> mUsedImage2DFunctionNames;
std::map<int, const TInterfaceBlock *> mUniformBlocksTranslatedToStructuredBuffers;
};
} // namespace sh
......
......@@ -231,10 +231,15 @@ class TType
bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
bool isVector() const { return primarySize > 1 && secondarySize == 1; }
bool isVectorArray() const { return primarySize > 1 && secondarySize == 1 && isArray(); }
bool isScalar() const
{
return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray();
}
bool isScalarArray() const
{
return primarySize == 1 && secondarySize == 1 && !mStructure && isArray();
}
bool isScalarFloat() const { return isScalar() && type == EbtFloat; }
bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
......
......@@ -1009,7 +1009,7 @@ TString StructNameString(const TStructure &structure)
TString QualifiedStructNameString(const TStructure &structure,
bool useHLSLRowMajorPacking,
bool useStd140Packing,
bool forcePackingEnd)
bool forcePadding)
{
if (structure.symbolType() == SymbolType::Empty)
{
......@@ -1031,9 +1031,9 @@ TString QualifiedStructNameString(const TStructure &structure,
prefix += "rm_";
}
if (forcePackingEnd)
if (forcePadding)
{
prefix += "pe_";
prefix += "fp_";
}
return prefix + StructNameString(structure);
......
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// RecordUniformBlocksTranslatedToStructuredBuffers.h:
// Collect all uniform blocks which will been translated to StructuredBuffers on Direct3D
// backend.
//
#ifndef COMPILER_TRANSLATOR_TREEOPS_RECORDUNIFORMBLOCKSTRANSLATEDTOSTRUCTUREDBUFFERS_H_
#define COMPILER_TRANSLATOR_TREEOPS_RECORDUNIFORMBLOCKSTRANSLATEDTOSTRUCTUREDBUFFERS_H_
#include "compiler/translator/IntermNode.h"
namespace sh
{
class TIntermNode;
ANGLE_NO_DISCARD bool RecordUniformBlocksTranslatedToStructuredBuffers(
TIntermNode *root,
std::map<int, const TInterfaceBlock *> &uniformBlockTranslatedToStructuredBuffer);
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEOPS_RECORDACCESSUNIFORMBLOCKENTIREARRAYMEMBER_H_
......@@ -125,9 +125,9 @@ ShaderD3D::ShaderD3D(const gl::ShaderState &state,
{
mAdditionalOptions |= SH_FORCE_ATOMIC_VALUE_RESOLUTION;
}
if (features.dontTranslateUniformBlockToStructuredBuffer.enabled)
if (features.allowTranslateUniformBlockToStructuredBuffer.enabled)
{
mAdditionalOptions |= SH_DONT_TRANSLATE_UNIFORM_BLOCK_TO_STRUCTUREDBUFFER;
mAdditionalOptions |= SH_ALLOW_TRANSLATE_UNIFORM_BLOCK_TO_STRUCTUREDBUFFER;
}
if (extensions.multiview || extensions.multiview2)
{
......
......@@ -2482,9 +2482,10 @@ void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
// Intel, they've been blocklisted to the DX9 runtime.
ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, true);
// There is an issue(crbug.com/1112112) when translating uniform block to StructuredBuffer,
// so disable this feature temporarily.
ANGLE_FEATURE_CONDITION(features, dontTranslateUniformBlockToStructuredBuffer, true);
// Allow translating uniform block to StructuredBuffer on Windows 10. This is targeted
// to work around a slow fxc compile performance issue with dynamic uniform indexing.
ANGLE_FEATURE_CONDITION(features, allowTranslateUniformBlockToStructuredBuffer,
IsWin10OrGreater());
// Call platform hooks for testing overrides.
auto *platform = ANGLEPlatformCurrent();
......
......@@ -21,6 +21,10 @@
# include <sys/utsname.h>
#endif
#if defined(ANGLE_PLATFORM_WINDOWS)
# include <versionhelpers.h>
#endif
namespace rx
{
// Intel
......@@ -284,4 +288,15 @@ bool IsWayland()
return isWayland;
}
bool IsWin10OrGreater()
{
#if defined(ANGLE_ENABLE_WINDOWS_UWP)
return true;
#elif defined(ANGLE_PLATFORM_WINDOWS)
return IsWindows10OrGreater();
#else
return false;
#endif
}
} // namespace rx
......@@ -186,6 +186,7 @@ inline bool IsIOS()
}
bool IsWayland();
bool IsWin10OrGreater();
struct OSVersion
{
......
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