Commit bdec2f4e by Jamie Madill

D3D11: Fix overlapping vertex shader signatures.

For the case of drawing with un-normalized integer vertex attributes, we need to do some dynamic conversion in the VS. However, each attribute can either be signed or unsigned, and our shader signature code would treat both as a match, giving rise to a warning in the D3D11 Debug runtime. It's unclear if this would give incorrect results, but it certainly should not produce a warning. BUG=angleproject:1329 Change-Id: I302d11b44e8a0ef981e89c181aefac5451a899b7 Reviewed-on: https://chromium-review.googlesource.com/329998 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org>
parent d8fa9215
...@@ -509,24 +509,44 @@ ProgramD3D::VertexExecutable::~VertexExecutable() ...@@ -509,24 +509,44 @@ ProgramD3D::VertexExecutable::~VertexExecutable()
} }
// static // static
ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
GLenum type)
{
switch (type)
{
case GL_INT:
return HLSLAttribType::SIGNED_INT;
case GL_UNSIGNED_INT:
return HLSLAttribType::UNSIGNED_INT;
case GL_SIGNED_NORMALIZED:
case GL_UNSIGNED_NORMALIZED:
case GL_FLOAT:
return HLSLAttribType::FLOAT;
default:
UNREACHABLE();
return HLSLAttribType::FLOAT;
}
}
// static
void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer, void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
const gl::InputLayout &inputLayout, const gl::InputLayout &inputLayout,
Signature *signatureOut) Signature *signatureOut)
{ {
signatureOut->resize(inputLayout.size()); signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
for (size_t index = 0; index < inputLayout.size(); ++index) for (size_t index = 0; index < inputLayout.size(); ++index)
{ {
gl::VertexFormatType vertexFormatType = inputLayout[index]; gl::VertexFormatType vertexFormatType = inputLayout[index];
bool converted = false; if (vertexFormatType == gl::VERTEX_FORMAT_INVALID)
if (vertexFormatType != gl::VERTEX_FORMAT_INVALID) continue;
{
VertexConversionType conversionType = VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType);
renderer->getVertexConversionType(vertexFormatType); if ((conversionType & VERTEX_CONVERT_GPU) == 0)
converted = ((conversionType & VERTEX_CONVERT_GPU) != 0); continue;
}
(*signatureOut)[index] = converted; GLenum componentType = renderer->getVertexComponentType(vertexFormatType);
(*signatureOut)[index] = GetAttribType(componentType);
} }
} }
...@@ -535,9 +555,9 @@ bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) ...@@ -535,9 +555,9 @@ bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature)
size_t limit = std::max(mSignature.size(), signature.size()); size_t limit = std::max(mSignature.size(), signature.size());
for (size_t index = 0; index < limit; ++index) for (size_t index = 0; index < limit; ++index)
{ {
// treat undefined indexes as 'not converted' // treat undefined indexes as FLOAT
bool a = index < signature.size() ? signature[index] : false; auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
bool b = index < mSignature.size() ? mSignature[index] : false; auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
if (a != b) if (a != b)
return false; return false;
} }
......
...@@ -254,7 +254,14 @@ class ProgramD3D : public ProgramImpl ...@@ -254,7 +254,14 @@ class ProgramD3D : public ProgramImpl
class VertexExecutable class VertexExecutable
{ {
public: public:
typedef std::vector<bool> Signature; enum HLSLAttribType
{
FLOAT,
UNSIGNED_INT,
SIGNED_INT,
};
typedef std::vector<HLSLAttribType> Signature;
VertexExecutable(const gl::InputLayout &inputLayout, VertexExecutable(const gl::InputLayout &inputLayout,
const Signature &signature, const Signature &signature,
...@@ -271,6 +278,8 @@ class ProgramD3D : public ProgramImpl ...@@ -271,6 +278,8 @@ class ProgramD3D : public ProgramImpl
ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
private: private:
static HLSLAttribType GetAttribType(GLenum type);
gl::InputLayout mInputs; gl::InputLayout mInputs;
Signature mSignature; Signature mSignature;
ShaderExecutableD3D *mShaderExecutable; ShaderExecutableD3D *mShaderExecutable;
......
...@@ -124,6 +124,24 @@ TEST_P(ProgramBinaryTest, FloatDynamicShaderSize) ...@@ -124,6 +124,24 @@ TEST_P(ProgramBinaryTest, FloatDynamicShaderSize)
} }
} }
// Tests that switching between signed and unsigned un-normalized data doesn't trigger a bug
// in the D3D11 back-end.
TEST_P(ProgramBinaryTest, DynamicShadersSignatureBug)
{
glUseProgram(mProgram);
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
GLint attribLocation = glGetAttribLocation(mProgram, "inputAttribute");
ASSERT_NE(-1, attribLocation);
glEnableVertexAttribArray(attribLocation);
glVertexAttribPointer(attribLocation, 2, GL_BYTE, GL_FALSE, 0, nullptr);
glDrawArrays(GL_POINTS, 0, 1);
glVertexAttribPointer(attribLocation, 2, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
glDrawArrays(GL_POINTS, 0, 1);
}
// This tests the ability to successfully save and load a program binary. // This tests the ability to successfully save and load a program binary.
TEST_P(ProgramBinaryTest, SaveAndLoadBinary) TEST_P(ProgramBinaryTest, SaveAndLoadBinary)
{ {
......
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