// // Copyright 2015 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // D3D11FormatTablesTest: // Tests to validate our D3D11 support tables match hardware support. // #include "libANGLE/angletypes.h" #include "libANGLE/Context.h" #include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/d3d11/Context11.h" #include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" #include "test_utils/angle_test_instantiate.h" #include "test_utils/ANGLETest.h" using namespace angle; namespace { class D3D11FormatTablesTest : public ANGLETest { }; // This test enumerates all GL formats - for each, it queries the D3D support for // using it as a texture, a render target, and sampling from it in the shader. It // checks this against our speed-optimized baked tables, and validates they would // give the same result. // TODO(jmadill): Find out why in 9_3, some format queries return an error. // The error seems to appear for formats that are not supported on 9_3. TEST_P(D3D11FormatTablesTest, TestFormatSupport) { ASSERT_EQ(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, GetParam().getRenderer()); // Hack the angle! gl::Context *context = reinterpret_cast(getEGLWindow()->getContext()); rx::Context11 *context11 = rx::GetImplAs(context); rx::Renderer11 *renderer = context11->getRenderer(); const auto &textureCaps = renderer->getNativeTextureCaps(); ID3D11Device *device = renderer->getDevice(); const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); for (GLenum internalFormat : allFormats) { const rx::d3d11::Format &formatInfo = rx::d3d11::Format::Get(internalFormat, renderer->getRenderer11DeviceCaps()); const auto &textureInfo = textureCaps.get(internalFormat); // Bits for texturing const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D; if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0) { texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE; if (GetParam().majorVersion > 2) { texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; } } UINT texSupport = 0; bool texSuccess = SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &texSupport)); bool textureable = texSuccess && ((texSupport & texSupportMask) == texSupportMask); EXPECT_EQ(textureable, textureInfo.texturable); // Bits for mipmap auto-gen. bool expectedMipGen = texSuccess && ((texSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0); auto featureLevel = renderer->getRenderer11DeviceCaps().featureLevel; const auto &dxgiSupport = rx::d3d11::GetDXGISupport(formatInfo.texFormat, featureLevel); bool actualMipGen = ((dxgiSupport.alwaysSupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0); EXPECT_EQ(0u, dxgiSupport.optionallySupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN); EXPECT_EQ(expectedMipGen, actualMipGen); // Bits for filtering UINT filterSupport = 0; bool filterSuccess = SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &filterSupport)); bool filterable = filterSuccess && ((filterSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) != 0); EXPECT_EQ(filterable, textureInfo.filterable); // Bits for renderable bool renderable = false; UINT renderSupport = 0u; DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN; if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0) { renderFormat = formatInfo.dsvFormat; bool depthSuccess = SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &renderSupport)); renderable = depthSuccess && ((renderSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0); if (renderable) { EXPECT_NE(DXGI_FORMAT_UNKNOWN, formatInfo.dsvFormat); } } else { renderFormat = formatInfo.rtvFormat; bool rtSuccess = SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &renderSupport)); renderable = rtSuccess && ((renderSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0); if (renderable) { EXPECT_NE(DXGI_FORMAT_UNKNOWN, formatInfo.rtvFormat); } } EXPECT_EQ(renderable, textureInfo.renderable); if (!textureInfo.sampleCounts.empty()) { EXPECT_TRUE(renderable); } // Multisample counts if (renderable) { if ((renderSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0) { EXPECT_TRUE(!textureInfo.sampleCounts.empty()); for (unsigned int sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2) { UINT qualityCount = 0; bool sampleSuccess = SUCCEEDED(device->CheckMultisampleQualityLevels( renderFormat, sampleCount, &qualityCount)); GLuint expectedCount = (!sampleSuccess || qualityCount == 0) ? 0 : 1; EXPECT_EQ(expectedCount, textureInfo.sampleCounts.count(sampleCount)); } } else { EXPECT_TRUE(textureInfo.sampleCounts.empty()); } } } } ANGLE_INSTANTIATE_TEST(D3D11FormatTablesTest, ES2_D3D11_FL9_3(), ES2_D3D11_FL10_0(), ES2_D3D11_FL10_1(), ES2_D3D11_FL11_0()); } // anonymous namespace