Validate that fragment shader output matches the draw buffer type.
TEST=conformance2/rendering/fs-color-type-mismatch-color-buffer-type
BUG=angleproject:1688
Change-Id: I17848baf40b6d32b5adc1458fe2369b850164da3
Reviewed-on: https://chromium-review.googlesource.com/518246
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 0bfdc24..4e5b8fe 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -718,6 +718,28 @@
return false;
}
+bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
+{
+ const Program *program = context->getGLState().getProgram();
+ const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
+
+ const auto &programOutputTypes = program->getOutputVariableTypes();
+ for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
+ {
+ GLenum outputType = programOutputTypes[drawBufferIdx];
+ GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
+ if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION,
+ "Fragment shader output type does not match the bound "
+ "framebuffer attachment type."));
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // anonymous namespace
bool ValidTextureTarget(const ValidationContext *context, GLenum target)
@@ -2713,9 +2735,10 @@
}
}
- // Detect rendering feedback loops for WebGL.
+ // Do some additonal WebGL-specific validation
if (context->getExtensions().webglCompatibility)
{
+ // Detect rendering feedback loops for WebGL.
if (framebuffer->formsRenderingFeedbackLoopWith(state))
{
context->handleError(
@@ -2723,6 +2746,12 @@
"Rendering feedback loop formed between Framebuffer and active Texture."));
return false;
}
+
+ // Detect that the color buffer types match the fragment shader output types
+ if (!ValidateFragmentShaderColorBufferTypeMatch(context))
+ {
+ return false;
+ }
}
// No-op if zero count