Commit 8ba78da0 by Lee Salzman Committed by Commit Bot

add support for EXT_blend_func_extended to D3D11

Change-Id: Id66868851a490d0a68a7e76280720825c4844a45 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1591192 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 3e62561c
......@@ -233,6 +233,7 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
const char *sourcePath,
ShShaderOutput outputType,
int numRenderTargets,
int maxDualSourceDrawBuffers,
const std::vector<Uniform> &uniforms,
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
......@@ -249,6 +250,7 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
mInsideFunction(false),
mInsideMain(false),
mNumRenderTargets(numRenderTargets),
mMaxDualSourceDrawBuffers(maxDualSourceDrawBuffers),
mCurrentFunctionMetadata(nullptr),
mWorkGroupSize(workGroupSize),
mPerfDiagnostics(perfDiagnostics)
......@@ -276,6 +278,7 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
mUsesNestedBreak = false;
mRequiresIEEEStrictCompiling = false;
mUseZeroArray = false;
mUsesSecondaryColor = false;
mUniqueIndex = 0;
......@@ -630,6 +633,8 @@ void OutputHLSL::header(TInfoSinkBase &out,
{
const bool usingMRTExtension =
IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers);
const bool usingBFEExtension =
IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_blend_func_extended);
out << "// Varyings\n";
writeReferencedVaryings(out);
......@@ -664,6 +669,23 @@ void OutputHLSL::header(TInfoSinkBase &out,
}
out << "};\n";
if (usingBFEExtension && mUsesSecondaryColor)
{
out << "static float4 gl_SecondaryColor[" << mMaxDualSourceDrawBuffers
<< "] = \n"
"{\n";
for (int i = 0; i < mMaxDualSourceDrawBuffers; i++)
{
out << " float4(0, 0, 0, 0)";
if (i + 1 != mMaxDualSourceDrawBuffers)
{
out << ",";
}
out << "\n";
}
out << "};\n";
}
}
if (mUsesFragDepth)
......@@ -781,6 +803,11 @@ void OutputHLSL::header(TInfoSinkBase &out,
{
out << "#define GL_USES_FRAG_DATA\n";
}
if (mShaderVersion < 300 && usingBFEExtension && mUsesSecondaryColor)
{
out << "#define GL_USES_SECONDARY_COLOR\n";
}
}
else if (mShaderType == GL_VERTEX_SHADER)
{
......@@ -1118,6 +1145,16 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
out << "gl_Color";
mUsesFragData = true;
}
else if (qualifier == EvqSecondaryFragColorEXT)
{
out << "gl_SecondaryColor[0]";
mUsesSecondaryColor = true;
}
else if (qualifier == EvqSecondaryFragDataEXT)
{
out << "gl_SecondaryColor";
mUsesSecondaryColor = true;
}
else if (qualifier == EvqFragCoord)
{
mUsesFragCoord = true;
......
......@@ -43,6 +43,7 @@ class OutputHLSL : public TIntermTraverser
const char *sourcePath,
ShShaderOutput outputType,
int numRenderTargets,
int maxDualSourceDrawBuffers,
const std::vector<Uniform> &uniforms,
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
......@@ -207,8 +208,10 @@ class OutputHLSL : public TIntermTraverser
bool mUsesNestedBreak;
bool mRequiresIEEEStrictCompiling;
mutable bool mUseZeroArray;
bool mUsesSecondaryColor;
int mNumRenderTargets;
int mMaxDualSourceDrawBuffers;
int mUniqueIndex; // For creating unique names
......
......@@ -42,6 +42,8 @@ void TranslatorHLSL::translate(TIntermBlock *root,
{
const ShBuiltInResources &resources = getResources();
int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
int maxDualSourceDrawBuffers =
resources.EXT_blend_func_extended ? resources.MaxDualSourceDrawBuffers : 0;
sh::AddDefaultReturnStatements(root);
......@@ -135,10 +137,10 @@ void TranslatorHLSL::translate(TIntermBlock *root,
sh::RewriteAtomicFunctionExpressions(root, &getSymbolTable(), getShaderVersion());
}
sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
getSourcePath(), getOutputType(), numRenderTargets, getUniforms(),
compileOptions, getComputeShaderLocalSize(), &getSymbolTable(),
perfDiagnostics, mShaderStorageBlocks);
sh::OutputHLSL outputHLSL(
getShaderType(), getShaderVersion(), getExtensionBehavior(), getSourcePath(),
getOutputType(), numRenderTargets, maxDualSourceDrawBuffers, getUniforms(), compileOptions,
getComputeShaderLocalSize(), &getSymbolTable(), perfDiagnostics, mShaderStorageBlocks);
outputHLSL.output(root, getInfoSink().obj);
......
......@@ -59,7 +59,7 @@ HashStream &operator<<(HashStream &stream, const ProgramBindings &bindings)
{
for (const auto &binding : bindings)
{
stream << binding.first << binding.second;
stream << binding.first << binding.second.location;
}
return stream;
}
......
......@@ -179,6 +179,11 @@ struct VariableLocation
void markUnused() { index = kUnused; }
void markIgnored() { ignored = true; }
bool operator==(const VariableLocation &other) const
{
return arrayIndex == other.arrayIndex && index == other.index;
}
// "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays.
unsigned int arrayIndex;
// "index" is an index of the variable. The variable contains the indices for other than the
......@@ -473,6 +478,16 @@ class ProgramState final : angle::NonCopyable
ActiveTextureMask mActiveImagesMask;
};
struct ProgramBinding
{
ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {}
ProgramBinding(GLuint index) : location(index), aliased(false) {}
GLuint location;
// Whether another binding was set that may potentially alias this.
bool aliased;
};
class ProgramBindings final : angle::NonCopyable
{
public:
......@@ -480,14 +495,15 @@ class ProgramBindings final : angle::NonCopyable
~ProgramBindings();
void bindLocation(GLuint index, const std::string &name);
int getBinding(const std::string &name) const;
int getBindingByName(const std::string &name) const;
int getBinding(const sh::VariableWithLocation &variable) const;
using const_iterator = std::unordered_map<std::string, GLuint>::const_iterator;
using const_iterator = std::unordered_map<std::string, ProgramBinding>::const_iterator;
const_iterator begin() const;
const_iterator end() const;
private:
std::unordered_map<std::string, GLuint> mBindings;
std::unordered_map<std::string, ProgramBinding> mBindings;
};
struct ProgramVaryingRef
......
......@@ -32,20 +32,6 @@ LinkedUniform *FindUniform(std::vector<LinkedUniform> &list, const std::string &
return nullptr;
}
int GetUniformLocationBinding(const ProgramBindings &uniformLocationBindings,
const sh::Uniform &uniform)
{
int binding = uniformLocationBindings.getBinding(uniform.name);
if (uniform.isArray() && binding == -1)
{
// Bindings for array uniforms can be set either with or without [0] in the end.
ASSERT(angle::EndsWith(uniform.name, "[0]"));
std::string nameWithoutIndex = uniform.name.substr(0u, uniform.name.length() - 3u);
return uniformLocationBindings.getBinding(nameWithoutIndex);
}
return binding;
}
template <typename VarT>
void SetActive(std::vector<VarT> *list, const std::string &name, ShaderType shaderType, bool active)
{
......@@ -664,7 +650,7 @@ bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &unifo
continue;
}
int preSetLocation = GetUniformLocationBinding(uniformLocationBindings, uniform);
int preSetLocation = uniformLocationBindings.getBinding(uniform);
int shaderLocation = uniform.location;
if (shaderLocation != -1)
......@@ -740,7 +726,7 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
continue;
}
int apiBoundLocation = GetUniformLocationBinding(uniformLocationBindings, uniform);
int apiBoundLocation = uniformLocationBindings.getBinding(uniform);
int shaderLocation = uniform.location;
if (shaderLocation != -1)
......@@ -785,7 +771,7 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
// from the shader. Other uniforms should not be assigned to those locations.
for (const auto &locationBinding : uniformLocationBindings)
{
GLuint location = locationBinding.second;
GLuint location = locationBinding.second.location;
if (reservedLocations.find(location) == reservedLocations.end())
{
ignoredLocations->insert(location);
......
......@@ -97,13 +97,14 @@ void HLSLTypeString(std::ostringstream &ostream, GLenum type)
const PixelShaderOutputVariable *FindOutputAtLocation(
const std::vector<PixelShaderOutputVariable> &outputVariables,
unsigned int location)
unsigned int location,
size_t index = 0)
{
for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
for (auto &outputVar : outputVariables)
{
if (outputVariables[variableIndex].outputIndex == location)
if (outputVar.outputLocation == location && outputVar.outputIndex == index)
{
return &outputVariables[variableIndex];
return &outputVar;
}
}
......@@ -294,7 +295,9 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(
{
numOutputs = 1u;
}
const PixelShaderOutputVariable defaultOutput(GL_FLOAT_VEC4, "dummy", "float4(0, 0, 0, 1)", 0);
const PixelShaderOutputVariable defaultOutput(GL_FLOAT_VEC4, "dummy", "float4(0, 0, 0, 1)", 0,
0);
size_t outputIndex = 0;
for (size_t layoutIndex = 0; layoutIndex < numOutputs; ++layoutIndex)
{
......@@ -303,15 +306,16 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(
if (binding != GL_NONE)
{
unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
outputIndex =
layoutIndex > 0 && binding == outputLayout[layoutIndex - 1] ? outputIndex + 1 : 0;
const PixelShaderOutputVariable *outputVariable =
outputLayout.empty() ? &defaultOutput
: FindOutputAtLocation(outputVariables, location);
: FindOutputAtLocation(outputVariables, location, outputIndex);
// OpenGL ES 3.0 spec $4.2.1
// If [...] not all user-defined output variables are written, the values of fragment
// colors
// corresponding to unwritten variables are similarly undefined.
// colors corresponding to unwritten variables are similarly undefined.
if (outputVariable)
{
declarationStream << " ";
......@@ -1204,10 +1208,26 @@ void DynamicHLSL::getPixelShaderOutputKey(const gl::State &data,
outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
outputKeyVariable.source =
broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
outputKeyVariable.outputIndex = renderTargetIndex;
outputKeyVariable.outputLocation = renderTargetIndex;
outPixelShaderKey->push_back(outputKeyVariable);
}
if (metadata.usesSecondaryColor())
{
for (unsigned int secondaryIndex = 0;
secondaryIndex < data.getExtensions().maxDualSourceDrawBuffers; secondaryIndex++)
{
PixelShaderOutputVariable outputKeyVariable;
outputKeyVariable.type = GL_FLOAT_VEC4;
outputKeyVariable.name = "gl_SecondaryColor" + Str(secondaryIndex);
outputKeyVariable.source = "gl_SecondaryColor[" + Str(secondaryIndex) + "]";
outputKeyVariable.outputLocation = secondaryIndex;
outputKeyVariable.outputIndex = 1;
outPixelShaderKey->push_back(outputKeyVariable);
}
}
}
else
{
......@@ -1238,7 +1258,39 @@ void DynamicHLSL::getPixelShaderOutputKey(const gl::State &data,
outputKeyVariable.source =
variableName +
(outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
outputKeyVariable.outputIndex = outputLocationIndex;
outputKeyVariable.outputLocation = outputLocationIndex;
outPixelShaderKey->push_back(outputKeyVariable);
}
// Now generate any secondary outputs...
for (size_t outputLocationIndex = 0u;
outputLocationIndex < programData.getSecondaryOutputLocations().size();
++outputLocationIndex)
{
const VariableLocation &outputLocation =
programData.getSecondaryOutputLocations().at(outputLocationIndex);
if (!outputLocation.used())
{
continue;
}
const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
const std::string &variableName = "out_" + outputVariable.name;
// Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6.
const std::string &elementString =
(outputVariable.isArray() ? Str(outputLocation.arrayIndex) : "");
ASSERT(outputVariable.active);
PixelShaderOutputVariable outputKeyVariable;
outputKeyVariable.type = outputVariable.type;
outputKeyVariable.name = variableName + elementString;
outputKeyVariable.source =
variableName +
(outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
outputKeyVariable.outputLocation = outputLocationIndex;
outputKeyVariable.outputIndex = 1;
outPixelShaderKey->push_back(outputKeyVariable);
}
......
......@@ -67,13 +67,19 @@ struct PixelShaderOutputVariable
PixelShaderOutputVariable(GLenum typeIn,
const std::string &nameIn,
const std::string &sourceIn,
size_t outputLocationIn,
size_t outputIndexIn)
: type(typeIn), name(nameIn), source(sourceIn), outputIndex(outputIndexIn)
: type(typeIn),
name(nameIn),
source(sourceIn),
outputLocation(outputLocationIn),
outputIndex(outputIndexIn)
{}
GLenum type = GL_NONE;
std::string name;
std::string source;
size_t outputLocation = 0;
size_t outputIndex = 0;
};
......
......@@ -67,6 +67,20 @@ void GetDefaultInputLayoutFromShader(gl::Shader *vertexShader, gl::InputLayout *
}
}
size_t GetMaxOutputIndex(const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
size_t location)
{
size_t maxIndex = 0;
for (auto &outputVar : shaderOutputVars)
{
if (outputVar.outputLocation == location)
{
maxIndex = std::max(maxIndex, outputVar.outputIndex);
}
}
return maxIndex;
}
void GetDefaultOutputLayoutFromShader(
const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
std::vector<GLenum> *outputLayoutOut)
......@@ -75,8 +89,10 @@ void GetDefaultOutputLayoutFromShader(
if (!shaderOutputVars.empty())
{
outputLayoutOut->push_back(GL_COLOR_ATTACHMENT0 +
static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
size_t location = shaderOutputVars[0].outputLocation;
size_t maxIndex = GetMaxOutputIndex(shaderOutputVars, location);
outputLayoutOut->assign(maxIndex + 1,
GL_COLOR_ATTACHMENT0 + static_cast<unsigned int>(location));
}
}
......@@ -477,6 +493,11 @@ bool ProgramD3DMetadata::usesBroadcast(const gl::State &data) const
data.getClientMajorVersion() < 3);
}
bool ProgramD3DMetadata::usesSecondaryColor() const
{
return mAttachedShaders[gl::ShaderType::Fragment]->usesSecondaryColor();
}
bool ProgramD3DMetadata::usesFragDepth() const
{
return mAttachedShaders[gl::ShaderType::Fragment]->usesFragDepth();
......@@ -1166,6 +1187,7 @@ std::unique_ptr<rx::LinkEvent> ProgramD3D::load(const gl::Context *context,
stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputLocation);
stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
}
......@@ -1449,6 +1471,7 @@ void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream
stream->writeInt(variable.type);
stream->writeString(variable.name);
stream->writeString(variable.source);
stream->writeInt(variable.outputLocation);
stream->writeInt(variable.outputIndex);
}
......@@ -3048,7 +3071,11 @@ void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
{
auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
: colorbuffer->getBinding();
mPixelShaderOutputLayoutCache.push_back(binding);
size_t maxIndex = binding != GL_NONE ? GetMaxOutputIndex(mPixelShaderKey,
binding - GL_COLOR_ATTACHMENT0)
: 0;
mPixelShaderOutputLayoutCache.insert(mPixelShaderOutputLayoutCache.end(), maxIndex + 1,
binding);
}
else
{
......
......@@ -122,6 +122,7 @@ class ProgramD3DMetadata final : angle::NonCopyable
int getRendererMajorShaderModel() const;
bool usesBroadcast(const gl::State &data) const;
bool usesSecondaryColor() const;
bool usesFragDepth() const;
bool usesPointCoord() const;
bool usesFragCoord() const;
......
......@@ -150,6 +150,7 @@ void ShaderD3D::uncompile()
mUsesMultipleRenderTargets = false;
mUsesFragColor = false;
mUsesFragData = false;
mUsesSecondaryColor = false;
mUsesFragCoord = false;
mUsesFrontFacing = false;
mUsesPointSize = false;
......@@ -272,6 +273,7 @@ std::shared_ptr<WaitableCompileEvent> ShaderD3D::compile(const gl::Context *cont
mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos;
mUsesFragColor = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
mUsesFragData = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
mUsesSecondaryColor = translatedSource.find("GL_USES_SECONDARY_COLOR") != std::string::npos;
mUsesFragCoord = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
mUsesFrontFacing = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
mUsesPointSize = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
......
......@@ -65,6 +65,7 @@ class ShaderD3D : public ShaderImpl
bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; }
bool usesFragColor() const { return mUsesFragColor; }
bool usesFragData() const { return mUsesFragData; }
bool usesSecondaryColor() const { return mUsesSecondaryColor; }
bool usesFragCoord() const { return mUsesFragCoord; }
bool usesFrontFacing() const { return mUsesFrontFacing; }
bool usesPointSize() const { return mUsesPointSize; }
......@@ -81,6 +82,7 @@ class ShaderD3D : public ShaderImpl
bool mUsesMultipleRenderTargets;
bool mUsesFragColor;
bool mUsesFragData;
bool mUsesSecondaryColor;
bool mUsesFragCoord;
bool mUsesFrontFacing;
bool mUsesPointSize;
......
......@@ -1649,6 +1649,8 @@ void GenerateCaps(ID3D11Device *device,
extensions->textureBorderClamp = true;
extensions->textureMultisample = true;
extensions->provokingVertex = true;
extensions->blendFuncExtended = true;
extensions->maxDualSourceDrawBuffers = 1;
// D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
// D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't
......@@ -1751,6 +1753,18 @@ D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
case GL_SRC_ALPHA_SATURATE:
d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;
break;
case GL_SRC1_COLOR_EXT:
d3dBlend = (isAlpha ? D3D11_BLEND_SRC1_ALPHA : D3D11_BLEND_SRC1_COLOR);
break;
case GL_SRC1_ALPHA_EXT:
d3dBlend = D3D11_BLEND_SRC1_ALPHA;
break;
case GL_ONE_MINUS_SRC1_COLOR_EXT:
d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC1_ALPHA : D3D11_BLEND_INV_SRC1_COLOR);
break;
case GL_ONE_MINUS_SRC1_ALPHA_EXT:
d3dBlend = D3D11_BLEND_INV_SRC1_ALPHA;
break;
default:
UNREACHABLE();
}
......
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