Add support to the HLSL translator to output interface blocks to constant buffers, using HLSL register packing rules.
TRAC #22930
Signed-off-by: Nicolas Capens
Signed-off-by: Geoff Lang
Author: Jamie Madill
git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2344 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 3b6ad2d..808c99b 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -7,6 +7,7 @@
#include "compiler/OutputHLSL.h"
#include "common/angleutils.h"
+#include "common/utilities.h"
#include "compiler/debug.h"
#include "compiler/DetectDiscontinuity.h"
#include "compiler/InfoSink.h"
@@ -113,6 +114,7 @@
}
mSamplerRegister = 0;
+ mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants
}
OutputHLSL::~OutputHLSL()
@@ -141,6 +143,11 @@
return mActiveUniforms;
}
+const ActiveInterfaceBlocks &OutputHLSL::getInterfaceBlocks() const
+{
+ return mActiveInterfaceBlocks;
+}
+
int OutputHLSL::vectorSize(const TType &type) const
{
int elementSize = type.isMatrix() ? type.getNominalSize() : 1;
@@ -165,6 +172,7 @@
}
TString uniforms;
+ TString interfaceBlocks;
TString varyings;
TString attributes;
@@ -180,7 +188,7 @@
uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) +
" : register(s" + str(index) + ");\n";
- uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) +
+ uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) +
" : register(t" + str(index) + ");\n";
}
else
@@ -190,6 +198,36 @@
}
}
+ for (ReferencedSymbols::const_iterator interfaceBlockIt = mReferencedInterfaceBlocks.begin(); interfaceBlockIt != mReferencedInterfaceBlocks.end(); interfaceBlockIt++)
+ {
+ const TType &interfaceBlockType = *interfaceBlockIt->second->getType().getInterfaceBlockType();
+ const TString &blockName = interfaceBlockType.getTypeName();
+ const TTypeList &typeList = *interfaceBlockType.getStruct();
+
+ sh::InterfaceBlock interfaceBlock(blockName.c_str(), 0, mInterfaceBlockRegister++);
+ for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
+ {
+ const TType &memberType = *typeList[typeIndex].type;
+ declareUniformToList(memberType, memberType.getFieldName(), typeIndex, interfaceBlock.activeUniforms);
+ }
+
+ // TODO: handle other block layouts
+ interfaceBlock.setPackedBlockLayout();
+ mActiveInterfaceBlocks.push_back(interfaceBlock);
+
+ interfaceBlocks += "cbuffer " + blockName + " : register(b" + str(interfaceBlock.registerIndex) + ")\n"
+ "{\n";
+
+ for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
+ {
+ // TODO: padding for standard layout
+ const TType &memberType = *typeList[typeIndex].type;
+ interfaceBlocks += " " + typeString(memberType) + " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
+ }
+
+ interfaceBlocks += "};\n\n";
+ }
+
for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
{
const TType &type = varying->second->getType();
@@ -310,6 +348,12 @@
out << uniforms;
out << "\n";
+ if (!interfaceBlocks.empty())
+ {
+ out << interfaceBlocks;
+ out << "\n";
+ }
+
if (mUsesTexture2D)
{
if (mOutputType == SH_HLSL9_OUTPUT)
@@ -678,6 +722,12 @@
out << uniforms;
out << "\n";
+ if (!interfaceBlocks.empty())
+ {
+ out << interfaceBlocks;
+ out << "\n";
+ }
+
if (mUsesTexture2D)
{
if (mOutputType == SH_HLSL9_OUTPUT)
@@ -1148,8 +1198,17 @@
if (qualifier == EvqUniform)
{
- mReferencedUniforms[name] = node;
- out << decorateUniform(name, node->getType());
+ if (node->getType().isInterfaceBlockMember())
+ {
+ const TString& interfaceBlockTypeName = node->getType().getInterfaceBlockType()->getTypeName();
+ mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
+ out << decorateUniform(name, node->getType());
+ }
+ else
+ {
+ mReferencedUniforms[name] = node;
+ out << decorateUniform(name, node->getType());
+ }
}
else if (qualifier == EvqAttribute)
{
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index 4e6e600..a4f8be9 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -33,6 +33,7 @@
TInfoSinkBase &getBodyStream();
const ActiveUniforms &getUniforms();
+ const ActiveInterfaceBlocks &getInterfaceBlocks() const;
TString typeString(const TType &type);
TString textureString(const TType &type);
@@ -84,6 +85,7 @@
typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
ReferencedSymbols mReferencedUniforms;
+ ReferencedSymbols mReferencedInterfaceBlocks;
ReferencedSymbols mReferencedAttributes;
ReferencedSymbols mReferencedVaryings;
@@ -163,6 +165,7 @@
TIntermSymbol *mExcessiveLoopIndex;
int mUniformRegister;
+ int mInterfaceBlockRegister;
int mSamplerRegister;
TString registerString(TIntermSymbol *operand);
@@ -178,6 +181,7 @@
static bool isVarying(TQualifier qualifier);
ActiveUniforms mActiveUniforms;
+ ActiveInterfaceBlocks mActiveInterfaceBlocks;
};
}