Skip to content

Commit

Permalink
Fixed incorrect multisample rendering when enable SAMPLE_COVERAGE on Win
Browse files Browse the repository at this point in the history
In RendererD3D::createRenderTarget, we use getNearestSamples(samples)'s
result to assign D3D11_TEXTURE2D_DESC.SampleDesc.Count. However, in
renderer11::updateState, we used the original samples to calculate mask
by GetBlendSampleMask not the supported nearest samples. It would result
that multisample rendering result was incorrect when enable
AMPLE_COVERAGE and the samples is not in the suported list but less than
max samples. At least, on Intel Win platform, we can reproduce it.
The fixing is to use same samples in these two places.

BUG=angleproject:1610
TEST=MultisampleCompatibilityTest.DrawCoverageAndResolve

Change-Id: I255b12d1032317145adfcee94e65e88ae5307113
Reviewed-on: https://chromium-review.googlesource.com/408516
Reviewed-by: Geoff Lang <[email protected]>
Commit-Queue: Geoff Lang <[email protected]>
  • Loading branch information
qjia7 authored and Commit Bot committed Nov 10, 2016
1 parent 89dd8f3 commit 4b97d50
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 4 deletions.
12 changes: 11 additions & 1 deletion src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1615,7 +1615,17 @@ gl::Error Renderer11::updateState(const gl::ContextState &data, GLenum drawMode)
mStateManager.setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());

// Applying rasterizer state to D3D11 device
int samples = framebuffer->getSamples(data);
// Since framebuffer->getSamples will return the original samples which may be different with
// the sample counts that we set in render target view, here we use renderTarget->getSamples to
// get the actual samples.
GLsizei samples = 0;
if (firstColorAttachment)
{
ASSERT(firstColorAttachment->isAttached());
RenderTarget11 *renderTarget = nullptr;
ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
samples = renderTarget->getSamples();
}
gl::RasterizerState rasterizer = glState.getRasterizerState();
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
rasterizer.multiSample = (samples != 0);
Expand Down
26 changes: 24 additions & 2 deletions src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,18 @@ gl::Error Renderer9::updateState(Context9 *context, GLenum drawMode)
setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());

// Setting blend, depth stencil, and rasterizer states
int samples = framebuffer->getSamples(data);
// Since framebuffer->getSamples will return the original samples which may be different with
// the sample counts that we set in render target view, here we use renderTarget->getSamples to
// get the actual samples.
GLsizei samples = 0;
auto firstColorAttachment = framebuffer->getFirstColorbuffer();
if (firstColorAttachment)
{
ASSERT(firstColorAttachment->isAttached());
RenderTarget9 *renderTarget = nullptr;
ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
samples = renderTarget->getSamples();
}
gl::RasterizerState rasterizer = glState.getRasterizerState();
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
rasterizer.multiSample = (samples != 0);
Expand All @@ -1030,7 +1041,18 @@ gl::Error Renderer9::setBlendDepthRasterStates(const gl::ContextState &glData, G
const auto &glState = glData.getState();
auto drawFramebuffer = glState.getDrawFramebuffer();
ASSERT(!drawFramebuffer->hasAnyDirtyBit());
int samples = drawFramebuffer->getSamples(glData);
// Since framebuffer->getSamples will return the original samples which may be different with
// the sample counts that we set in render target view, here we use renderTarget->getSamples to
// get the actual samples.
GLsizei samples = 0;
auto firstColorAttachment = drawFramebuffer->getFirstColorbuffer();
if (firstColorAttachment)
{
ASSERT(firstColorAttachment->isAttached());
RenderTarget9 *renderTarget = nullptr;
ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
samples = renderTarget->getSamples();
}
gl::RasterizerState rasterizer = glState.getRasterizerState();
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
rasterizer.multiSample = (samples != 0);
Expand Down
140 changes: 139 additions & 1 deletion src/tests/gl_tests/MultisampleCompatibilityTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//

#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "shader_utils.h"

using namespace angle;
Expand Down Expand Up @@ -296,5 +297,142 @@ TEST_P(EXTMultisampleCompatibilityTest, DrawAlphaOneAndResolve)
EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
}

ANGLE_INSTANTIATE_TEST(EXTMultisampleCompatibilityTest, ES2_OPENGL(), ES2_OPENGLES(), ES3_OPENGL());

ANGLE_INSTANTIATE_TEST(EXTMultisampleCompatibilityTest, ES2_OPENGL(), ES2_OPENGLES(), ES3_OPENGL());
class MultisampleCompatibilityTest : public ANGLETest
{

protected:
MultisampleCompatibilityTest()
{
setWindowWidth(64);
setWindowHeight(64);
setConfigRedBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}

void prepareForDraw(GLsizei numSamples)
{
// Create a sample buffer.
glGenRenderbuffers(1, &mSampleRB);
glBindRenderbuffer(GL_RENDERBUFFER, mSampleRB);
glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, numSamples, GL_RGBA8, kWidth,
kHeight);
GLint param = 0;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &param);
EXPECT_GE(param, numSamples);
glGenFramebuffers(1, &mSampleFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleRB);
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Create another FBO to resolve the multisample buffer into.
glGenTextures(1, &mResolveTex);
glBindTexture(GL_TEXTURE_2D, mResolveTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glGenFramebuffers(1, &mResolveFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mResolveFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mResolveTex, 0);
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glViewport(0, 0, kWidth, kHeight);
glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
}

void prepareForVerify()
{
// Resolve.
glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFBO);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBlitFramebufferANGLE(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mResolveFBO);

ASSERT_GL_NO_ERROR();
}

void cleanup()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &mResolveFBO);
glDeleteFramebuffers(1, &mSampleFBO);
glDeleteTextures(1, &mResolveTex);
glDeleteRenderbuffers(1, &mSampleRB);

ASSERT_GL_NO_ERROR();
}

bool isApplicable() const
{
return extensionEnabled("GL_ANGLE_framebuffer_multisample") &&
extensionEnabled("GL_OES_rgb8_rgba8");
}

GLuint mSampleFBO;
GLuint mResolveFBO;
GLuint mSampleRB;
GLuint mResolveTex;
};

// Test that enabling GL_SAMPLE_COVERAGE affects rendering.
TEST_P(MultisampleCompatibilityTest, DrawCoverageAndResolve)
{
if (!isApplicable())
return;

// TODO: Figure out why this fails on Android.
if (IsAndroid())
{
std::cout << "Test skipped on Android." << std::endl;
return;
}

const std::string &vertex =
"attribute vec4 position;\n"
"void main()\n"
"{ gl_Position = position; }";
const std::string &fragment =
"void main()\n"
"{ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }";

ANGLE_GL_PROGRAM(drawRed, vertex, fragment);

GLsizei maxSamples = 0;
glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
int iterationCount = maxSamples + 1;
for (int samples = 1; samples < iterationCount; samples++)
{
prepareForDraw(samples);
glEnable(GL_SAMPLE_COVERAGE);
glSampleCoverage(1.0, false);
drawQuad(drawRed.get(), "position", 0.5f);

prepareForVerify();
GLsizei pixelCount = kWidth * kHeight;
std::vector<GLColor> actual(pixelCount, GLColor::black);
glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
glDisable(GL_SAMPLE_COVERAGE);
cleanup();

std::vector<GLColor> expected(pixelCount, GLColor::red);
EXPECT_EQ(expected, actual);
}
}

ANGLE_INSTANTIATE_TEST(MultisampleCompatibilityTest,
ES2_D3D9(),
ES2_OPENGL(),
ES2_OPENGLES(),
ES3_D3D11(),
ES3_OPENGL(),
ES3_OPENGLES());

0 comments on commit 4b97d50

Please sign in to comment.