Re-re-land "Move sampler validation to the GL layer."
This previously was D3D-only, but is required for every draw call.
This completes the work of removing the D3D-specific Impl methods
from ProgramImpl.
Also add several regression tests to cover texture and sampler
validation.
Re-land with a fix for duplicate sampler active uniforms.
Re-re-land with a fix for a test comparison warning on Linux.
BUG=angleproject:1123
Change-Id: Iaf7b33861c07b9ceed4bd53ac2f010d35f05df45
Reviewed-on: https://chromium-review.googlesource.com/301712
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 6cb5c14..4819ca0 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -28,36 +28,6 @@
namespace
{
-GLenum GetTextureType(GLenum samplerType)
-{
- switch (samplerType)
- {
- case GL_SAMPLER_2D:
- case GL_INT_SAMPLER_2D:
- case GL_UNSIGNED_INT_SAMPLER_2D:
- case GL_SAMPLER_2D_SHADOW:
- return GL_TEXTURE_2D;
- case GL_SAMPLER_3D:
- case GL_INT_SAMPLER_3D:
- case GL_UNSIGNED_INT_SAMPLER_3D:
- return GL_TEXTURE_3D;
- case GL_SAMPLER_CUBE:
- case GL_SAMPLER_CUBE_SHADOW:
- return GL_TEXTURE_CUBE_MAP;
- case GL_INT_SAMPLER_CUBE:
- case GL_UNSIGNED_INT_SAMPLER_CUBE:
- return GL_TEXTURE_CUBE_MAP;
- case GL_SAMPLER_2D_ARRAY:
- case GL_INT_SAMPLER_2D_ARRAY:
- case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
- case GL_SAMPLER_2D_ARRAY_SHADOW:
- return GL_TEXTURE_2D_ARRAY;
- default: UNREACHABLE();
- }
-
- return GL_TEXTURE_2D;
-}
-
gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
{
gl::InputLayout defaultLayout;
@@ -338,7 +308,6 @@
mUsedVertexSamplerRange(0),
mUsedPixelSamplerRange(0),
mDirtySamplerMapping(true),
- mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits),
mShaderVersion(100),
mSerial(issueSerial())
{
@@ -486,106 +455,6 @@
}
}
-bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
-{
- // Skip cache if we're using an infolog, so we get the full error.
- // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
- if (!mDirtySamplerMapping && infoLog == nullptr && mCachedValidateSamplersResult.valid())
- {
- return mCachedValidateSamplersResult.value();
- }
-
- // if any two active samplers in a program are of different types, but refer to the same
- // texture image unit, and this is the current program, then ValidateProgram will fail, and
- // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
- updateSamplerMapping();
-
- std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
-
- for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
- {
- if (mSamplersPS[i].active)
- {
- unsigned int unit = mSamplersPS[i].logicalTextureUnit;
-
- if (unit >= caps.maxCombinedTextureImageUnits)
- {
- if (infoLog)
- {
- (*infoLog) << "Sampler uniform (" << unit
- << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
- << caps.maxCombinedTextureImageUnits << ")";
- }
-
- mCachedValidateSamplersResult = false;
- return false;
- }
-
- if (mTextureUnitTypesCache[unit] != GL_NONE)
- {
- if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit])
- {
- if (infoLog)
- {
- (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
- << unit << ").";
- }
-
- mCachedValidateSamplersResult = false;
- return false;
- }
- }
- else
- {
- mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType;
- }
- }
- }
-
- for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
- {
- if (mSamplersVS[i].active)
- {
- unsigned int unit = mSamplersVS[i].logicalTextureUnit;
-
- if (unit >= caps.maxCombinedTextureImageUnits)
- {
- if (infoLog)
- {
- (*infoLog) << "Sampler uniform (" << unit
- << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
- << caps.maxCombinedTextureImageUnits << ")";
- }
-
- mCachedValidateSamplersResult = false;
- return false;
- }
-
- if (mTextureUnitTypesCache[unit] != GL_NONE)
- {
- if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit])
- {
- if (infoLog)
- {
- (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
- << unit << ").";
- }
-
- mCachedValidateSamplersResult = false;
- return false;
- }
- }
- else
- {
- mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType;
- }
- }
- }
-
- mCachedValidateSamplersResult = true;
- return true;
-}
-
LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
{
reset();
@@ -1173,7 +1042,7 @@
initSemanticIndex();
- assignUniformRegisters();
+ defineUniformsAndAssignRegisters();
gatherTransformFeedbackVaryings(linkedVaryings);
@@ -1187,10 +1056,10 @@
return LinkResult(true, gl::Error(GL_NO_ERROR));
}
-GLboolean ProgramD3D::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
+GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
{
- applyUniforms();
- return validateSamplers(infoLog, caps);
+ // TODO(jmadill): Do something useful here?
+ return GL_TRUE;
}
void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
@@ -1475,17 +1344,19 @@
setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
}
-void ProgramD3D::assignUniformRegisters()
+void ProgramD3D::defineUniformsAndAssignRegisters()
{
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
+ D3DUniformMap uniformMap;
+
for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
{
if (vertexUniform.staticUse)
{
- assignUniformRegistersBase(vertexShaderD3D, vertexUniform);
+ defineUniformBase(vertexShaderD3D, vertexUniform, &uniformMap);
}
}
@@ -1496,19 +1367,32 @@
{
if (fragmentUniform.staticUse)
{
- assignUniformRegistersBase(fragmentShaderD3D, fragmentUniform);
+ defineUniformBase(fragmentShaderD3D, fragmentUniform, &uniformMap);
}
}
+ // Initialize the D3DUniform list to mirror the indexing of the GL layer.
+ for (const gl::LinkedUniform &glUniform : mData.getUniforms())
+ {
+ if (!glUniform.isInDefaultBlock())
+ continue;
+
+ auto mapEntry = uniformMap.find(glUniform.name);
+ ASSERT(mapEntry != uniformMap.end());
+ mD3DUniforms.push_back(mapEntry->second);
+ }
+
assignAllSamplerRegisters();
initializeUniformStorage();
}
-void ProgramD3D::assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform)
+void ProgramD3D::defineUniformBase(const ShaderD3D *shader,
+ const sh::Uniform &uniform,
+ D3DUniformMap *uniformMap)
{
if (uniform.isBuiltIn())
{
- assignUniformRegisters(shader, uniform, uniform.name, nullptr);
+ defineUniform(shader, uniform, uniform.name, nullptr, uniformMap);
return;
}
@@ -1517,7 +1401,7 @@
sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
encoder.skipRegisters(startRegister);
- assignUniformRegisters(shader, uniform, uniform.name, &encoder);
+ defineUniform(shader, uniform, uniform.name, &encoder, uniformMap);
}
D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
@@ -1533,10 +1417,11 @@
return nullptr;
}
-void ProgramD3D::assignUniformRegisters(const ShaderD3D *shader,
- const sh::ShaderVariable &uniform,
- const std::string &fullName,
- sh::HLSLBlockEncoder *encoder)
+void ProgramD3D::defineUniform(const ShaderD3D *shader,
+ const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap)
{
if (uniform.isStruct())
{
@@ -1552,7 +1437,7 @@
const sh::ShaderVariable &field = uniform.fields[fieldIndex];
const std::string &fieldFullName = (fullName + elementString + "." + field.name);
- assignUniformRegisters(shader, field, fieldFullName, encoder);
+ defineUniform(shader, field, fieldFullName, encoder, uniformMap);
}
if (encoder)
@@ -1572,27 +1457,23 @@
encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
: sh::BlockMemberInfo::getDefaultBlockInfo();
- D3DUniform *d3dUniform = getD3DUniformByName(fullName);
+ auto uniformMapEntry = uniformMap->find(fullName);
+ D3DUniform *d3dUniform = nullptr;
- if (!d3dUniform)
+ if (uniformMapEntry != uniformMap->end())
{
- // We're building the list twice, make sure we use the same indexing. Special case
- // built-ins.
- ASSERT(fullName.compare(0, 3, "gl_") == 0 ||
- mData.getUniformIndex(fullName) == static_cast<GLint>(mD3DUniforms.size()));
-
+ d3dUniform = uniformMapEntry->second;
+ }
+ else
+ {
d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
- mD3DUniforms.push_back(d3dUniform);
-
- if (encoder)
- {
- d3dUniform->registerElement =
- static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
- }
+ (*uniformMap)[fullName] = d3dUniform;
}
if (encoder)
{
+ d3dUniform->registerElement =
+ static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
unsigned int reg =
static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
if (shader->getShaderType() == GL_FRAGMENT_SHADER)
@@ -1871,7 +1752,7 @@
ASSERT(samplerIndex < outSamplers.size());
Sampler *sampler = &outSamplers[samplerIndex];
sampler->active = true;
- sampler->textureType = GetTextureType(samplerType);
+ sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
sampler->logicalTextureUnit = 0;
*outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
samplerIndex++;