Commit 5f857839 by Ian Elliott Committed by Commit Bot

Improve current multisampled renderbuffer/texture support

This is split off from a change to implement multisampled textures for the Vulkan back-end, and will come before that change. The changes include: - Make a common utility rx::GetSamplePosition() function. D3D11 and Vulkan use the same standard sample positions/locations for 1, 2, 4, 8, and 16 samples. The D3D11 back-end has a utility function for this, which is being moved to a common location--for use by both the D3D11 and Vulkan back-ends. - Texture::setStorageMultisample() handles converting the "requested number of samples" to the actual number of samples used (e.g. converting 3 to 4), supported by the underlying back-end). The actual number used is stored in gl::TextureState::mImageDescs, for use by other GLES commands. - Change some end2end tests to not make assumptions about the supported number of samples, but to properly query what is supported. Bug: angleproject:3565 Bug: angleproject:4196 Change-Id: I1dc12fedd0f8fb4975f90d87486e443b069b7141 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1948535 Commit-Queue: Ian Elliott <ianelliott@google.com> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com>
parent 2719fa44
...@@ -114,6 +114,14 @@ angle::Result Renderbuffer::setStorageMultisample(const Context *context, ...@@ -114,6 +114,14 @@ angle::Result Renderbuffer::setStorageMultisample(const Context *context,
size_t height) size_t height)
{ {
ANGLE_TRY(orphanImages(context)); ANGLE_TRY(orphanImages(context));
// TODO (ianelliott): Ensure that the following spec language is correctly implemented:
//
// the resulting value for RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal to
// samples and no more than the next larger sample count supported by the implementation.
//
// For example, if 2, 4, and 8 samples are supported, and if 5 samples are requested, ANGLE
// should use 8 samples, and return 8 when GL_RENDERBUFFER_SAMPLES is queried.
// http://anglebug.com/4196
ANGLE_TRY( ANGLE_TRY(
mImplementation->setStorageMultisample(context, samples, internalformat, width, height)); mImplementation->setStorageMultisample(context, samples, internalformat, width, height));
......
...@@ -1351,6 +1351,10 @@ angle::Result Texture::setStorageMultisample(Context *context, ...@@ -1351,6 +1351,10 @@ angle::Result Texture::setStorageMultisample(Context *context,
ANGLE_TRY(releaseTexImageInternal(context)); ANGLE_TRY(releaseTexImageInternal(context));
ANGLE_TRY(orphanImages(context)); ANGLE_TRY(orphanImages(context));
// Potentially adjust "samples" to a supported value
const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
samples = formatCaps.getNearestSamples(samples);
ANGLE_TRY(mTexture->setStorageMultisample(context, type, samples, internalFormat, size, ANGLE_TRY(mTexture->setStorageMultisample(context, type, samples, internalFormat, size,
fixedSampleLocations)); fixedSampleLocations));
......
...@@ -406,7 +406,7 @@ angle::Result Framebuffer11::getSamplePosition(const gl::Context *context, ...@@ -406,7 +406,7 @@ angle::Result Framebuffer11::getSamplePosition(const gl::Context *context,
ASSERT(attachment); ASSERT(attachment);
GLsizei sampleCount = attachment->getSamples(); GLsizei sampleCount = attachment->getSamples();
d3d11_gl::GetSamplePosition(sampleCount, index, xy); rx::GetSamplePosition(sampleCount, index, xy);
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -38,20 +38,6 @@ namespace d3d11_gl ...@@ -38,20 +38,6 @@ namespace d3d11_gl
{ {
namespace namespace
{ {
// Standard D3D sample positions from
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx
using SamplePositionsArray = std::array<float, 32>;
static constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
{{{0.5f, 0.5f}},
{{0.75f, 0.75f, 0.25f, 0.25f}},
{{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
{{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
{{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f, 0.75f, 0.4375f,
0.1875f, 0.375f, 0.625f, 0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f,
0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}};
// TODO(xinghua.cao@intel.com): Get a more accurate limit. // TODO(xinghua.cao@intel.com): Get a more accurate limit.
static D3D_FEATURE_LEVEL kMinimumFeatureLevelForES31 = D3D_FEATURE_LEVEL_11_0; static D3D_FEATURE_LEVEL kMinimumFeatureLevelForES31 = D3D_FEATURE_LEVEL_11_0;
...@@ -1698,16 +1684,6 @@ void GenerateCaps(ID3D11Device *device, ...@@ -1698,16 +1684,6 @@ void GenerateCaps(ID3D11Device *device,
#endif #endif
} }
void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy)
{
size_t indexKey = static_cast<size_t>(ceil(log2(sampleCount)));
ASSERT(indexKey < kSamplePositions.size() &&
(2 * index + 1) < kSamplePositions[indexKey].size());
xy[0] = kSamplePositions[indexKey][2 * index];
xy[1] = kSamplePositions[indexKey][2 * index + 1];
}
} // namespace d3d11_gl } // namespace d3d11_gl
namespace gl_d3d11 namespace gl_d3d11
......
...@@ -81,8 +81,6 @@ void GenerateCaps(ID3D11Device *device, ...@@ -81,8 +81,6 @@ void GenerateCaps(ID3D11Device *device,
gl::Extensions *extensions, gl::Extensions *extensions,
gl::Limitations *limitations); gl::Limitations *limitations);
void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31(); D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31();
} // namespace d3d11_gl } // namespace d3d11_gl
......
...@@ -29,6 +29,25 @@ namespace rx ...@@ -29,6 +29,25 @@ namespace rx
namespace namespace
{ {
// Both D3D and Vulkan support the same set of standard sample positions for 1, 2, 4, 8, and 16
// samples. See:
//
// - https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx
//
// -
// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#primsrast-multisampling
using SamplePositionsArray = std::array<float, 32>;
constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
{{{0.5f, 0.5f}},
{{0.75f, 0.75f, 0.25f, 0.25f}},
{{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
{{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
{{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f, 0.75f, 0.4375f,
0.1875f, 0.375f, 0.625f, 0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f,
0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}};
void CopyColor(gl::ColorF *color) void CopyColor(gl::ColorF *color)
{ {
// No-op // No-op
...@@ -781,4 +800,24 @@ void OverrideFeaturesWithDisplayState(angle::FeatureSetBase *features, ...@@ -781,4 +800,24 @@ void OverrideFeaturesWithDisplayState(angle::FeatureSetBase *features,
features->overrideFeatures(state.featureOverridesEnabled, true); features->overrideFeatures(state.featureOverridesEnabled, true);
features->overrideFeatures(state.featureOverridesDisabled, false); features->overrideFeatures(state.featureOverridesDisabled, false);
} }
void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy)
{
if (sampleCount > 16)
{
// Vulkan (and D3D11) doesn't have standard sample positions for 32 and 64 samples (and no
// drivers are known to support that many samples)
xy[0] = 0.5f;
xy[1] = 0.5f;
}
else
{
size_t indexKey = static_cast<size_t>(gl::log2(sampleCount));
ASSERT(indexKey < kSamplePositions.size() &&
(2 * index + 1) < kSamplePositions[indexKey].size());
xy[0] = kSamplePositions[indexKey][2 * index];
xy[1] = kSamplePositions[indexKey][2 * index + 1];
}
}
} // namespace rx } // namespace rx
...@@ -401,6 +401,8 @@ void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, u ...@@ -401,6 +401,8 @@ void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, u
*(outIndices++) = inIndices[loopStartIndex]; *(outIndices++) = inIndices[loopStartIndex];
} }
} }
void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
} // namespace rx } // namespace rx
#endif // LIBANGLE_RENDERER_RENDERER_UTILS_H_ #endif // LIBANGLE_RENDERER_RENDERER_UTILS_H_
...@@ -889,13 +889,26 @@ TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix) ...@@ -889,13 +889,26 @@ TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
GLFramebuffer mFramebuffer; GLFramebuffer mFramebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get()); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
// Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
// sample counts for textures and renderbuffers)
GLint numSampleCounts = 0;
std::vector<GLint> sampleCounts;
GLsizei queryBufferSize = 1;
glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
queryBufferSize, &numSampleCounts);
ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
sampleCounts.resize(numSampleCounts);
queryBufferSize = numSampleCounts;
glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
sampleCounts.data());
GLTexture mTexture; GLTexture mTexture;
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get()); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true); glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
GLRenderbuffer mRenderbuffer; GLRenderbuffer mRenderbuffer;
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get()); glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 1, 1); glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
mTexture.get(), 0); mTexture.get(), 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
...@@ -915,11 +928,23 @@ TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex) ...@@ -915,11 +928,23 @@ TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
GLFramebuffer mFramebuffer; GLFramebuffer mFramebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get()); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
// Lookup the supported number of sample counts
GLint numSampleCounts = 0;
std::vector<GLint> sampleCounts;
GLsizei queryBufferSize = 1;
glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
queryBufferSize, &numSampleCounts);
ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
sampleCounts.resize(numSampleCounts);
queryBufferSize = numSampleCounts;
glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
sampleCounts.data());
GLTexture mTextures[2]; GLTexture mTextures[2];
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get()); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true); glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get()); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, true); glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
mTextures[0].get(), 0); mTextures[0].get(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
......
...@@ -74,5 +74,53 @@ TEST_P(RenderbufferMultisampleTest, IntegerInternalformat) ...@@ -74,5 +74,53 @@ TEST_P(RenderbufferMultisampleTest, IntegerInternalformat)
} }
} }
// Ensure that the following spec language is correctly implemented:
//
// the resulting value for RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal to
// samples and no more than the next larger sample count supported by the implementation.
//
// For example, if 2, 4, and 8 samples are supported, if 5 samples are requested, ANGLE will
// use 8 samples, and return 8 when GL_RENDERBUFFER_SAMPLES is queried.
TEST_P(RenderbufferMultisampleTest, OddSampleCount)
{
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
ASSERT_GL_NO_ERROR();
// Lookup the supported number of sample counts
GLint numSampleCounts = 0;
std::vector<GLint> sampleCounts;
GLsizei queryBufferSize = 1;
glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, queryBufferSize,
&numSampleCounts);
ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
sampleCounts.resize(numSampleCounts);
queryBufferSize = numSampleCounts;
glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, queryBufferSize,
sampleCounts.data());
// Look for two sample counts that are not 1 apart (e.g. 2 and 4). Request a sample count
// that's between those two samples counts (e.g. 3) and ensure that GL_RENDERBUFFER_SAMPLES
// is the higher number.
for (int i = 1; i < numSampleCounts; i++)
{
if (sampleCounts[i - 1] > (sampleCounts[i] + 1))
{
glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[i] + 1, GL_RGBA8, 64,
64);
ASSERT_GL_NO_ERROR();
GLint renderbufferSamples = 0;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
&renderbufferSamples);
ASSERT_GL_NO_ERROR();
// TODO (ianelliott): Uncomment the following line once the implementation is fixed.
// http://anglebug.com/4196
// EXPECT_EQ(renderbufferSamples, sampleCounts[i-1]);
break;
}
}
}
ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(RenderbufferMultisampleTest); ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(RenderbufferMultisampleTest);
} // namespace } // namespace
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