Implement most texture formats on OpenGL

The only missing one is BGRA8UnormSrgb because it doesn't exist in
OpenGL and will need further emulation.

Also suppress most tests on the Mesa Intel GL driver that fails tests
pending further debugging.

BUG=dawn:128

Change-Id: Id454a89711e25b14c7de75a36c7642f2429a0e1f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8364
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2019-08-02 09:46:58 +00:00 committed by Commit Bot service account
parent e58fbc48b8
commit d64ee1a150
5 changed files with 162 additions and 25 deletions

View File

@ -161,6 +161,7 @@ namespace dawn_native { namespace opengl {
mFunctions.Enable(GL_SCISSOR_TEST);
mFunctions.Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
mFunctions.Enable(GL_MULTISAMPLE);
mFunctions.Enable(GL_FRAMEBUFFER_SRGB);
mPCIInfo.name = reinterpret_cast<const char*>(mFunctions.GetString(GL_RENDERER));

View File

@ -636,14 +636,6 @@ namespace dawn_native { namespace opengl {
}
drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
attachmentCount = i + 1;
// TODO(kainino@chromium.org): the color clears (later in
// this function) may be undefined for non-normalized integer formats.
dawn::TextureFormat format = textureView->GetTexture()->GetFormat().format;
ASSERT(format == dawn::TextureFormat::RGBA8Unorm ||
format == dawn::TextureFormat::RG8Unorm ||
format == dawn::TextureFormat::R8Unorm ||
format == dawn::TextureFormat::BGRA8Unorm);
}
gl.DrawBuffers(attachmentCount, drawBuffers.data());
@ -673,12 +665,10 @@ namespace dawn_native { namespace opengl {
GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget();
gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, target, texture, 0);
}
}
// TODO(kainino@chromium.org): the depth/stencil clears (later in
// this function) may be undefined for other texture formats.
ASSERT(format.format == dawn::TextureFormat::Depth24PlusStencil8);
}
}
ASSERT(gl.CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
// Set defaults for dynamic state before executing clears and commands.
PersistentPipelineState persistentPipelineState;
@ -695,6 +685,10 @@ namespace dawn_native { namespace opengl {
const auto& attachmentInfo = renderPass->colorAttachments[i];
// Load op - color
// TODO(cwallez@chromium.org): Choose the clear function depending on the
// componentType: things work for now because the clear color is always a float, but
// when that's fixed will lose precision on integer formats when converting to
// float.
if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
gl.ColorMaski(i, true, true, true, true);
gl.ClearBufferfv(GL_COLOR, i, &attachmentInfo.clearColor.r);

View File

@ -19,28 +19,88 @@ namespace dawn_native { namespace opengl {
GLFormatTable BuildGLFormatTable() {
GLFormatTable table;
using Type = GLFormat::ComponentType;
auto AddFormat = [&table](dawn::TextureFormat dawnFormat, GLenum internalFormat,
GLenum format, GLenum type) {
GLenum format, GLenum type, Type componentType) {
size_t index = ComputeFormatIndex(dawnFormat);
ASSERT(index < table.size());
table[index].internalFormat = internalFormat;
table[index].format = format;
table[index].type = type;
table[index].componentType = componentType;
table[index].isSupportedOnBackend = true;
};
AddFormat(dawn::TextureFormat::RGBA8Unorm, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
AddFormat(dawn::TextureFormat::RG8Unorm, GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
AddFormat(dawn::TextureFormat::R8Unorm, GL_R8, GL_RED, GL_UNSIGNED_BYTE);
AddFormat(dawn::TextureFormat::RGBA8Uint, GL_RGBA8UI, GL_RGBA, GL_UNSIGNED_INT);
AddFormat(dawn::TextureFormat::RG8Uint, GL_RG8UI, GL_RG, GL_UNSIGNED_INT);
AddFormat(dawn::TextureFormat::R8Uint, GL_R8UI, GL_RED, GL_UNSIGNED_INT);
// This doesn't have an enum for the internal format in OpenGL, so use RGBA8.
AddFormat(dawn::TextureFormat::BGRA8Unorm, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE);
// It's dangerous to go alone, take this:
//
// [ANGLE's formatutils.cpp]
// [ANGLE's formatutilsgl.cpp]
//
// The format tables in these files are extremely complete and the best reference on GL
// format support, enums, etc.
AddFormat(dawn::TextureFormat::Depth24PlusStencil8, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL,
GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
// clang-format off
// 1 byte color formats
AddFormat(dawn::TextureFormat::R8Unorm, GL_R8, GL_RED, GL_UNSIGNED_BYTE, Type::Float);
AddFormat(dawn::TextureFormat::R8Snorm, GL_R8_SNORM, GL_RED, GL_BYTE, Type::Float);
AddFormat(dawn::TextureFormat::R8Uint, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, Type::Uint);
AddFormat(dawn::TextureFormat::R8Sint, GL_R8I, GL_RED_INTEGER, GL_BYTE, Type::Int);
// 2 bytes color formats
AddFormat(dawn::TextureFormat::R16Unorm, GL_R16, GL_RED, GL_UNSIGNED_SHORT, Type::Float);
AddFormat(dawn::TextureFormat::R16Snorm, GL_R16_SNORM, GL_RED, GL_SHORT, Type::Float);
AddFormat(dawn::TextureFormat::R16Uint, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, Type::Uint);
AddFormat(dawn::TextureFormat::R16Sint, GL_R16I, GL_RED_INTEGER, GL_SHORT, Type::Int);
AddFormat(dawn::TextureFormat::R16Float, GL_R16F, GL_RED, GL_HALF_FLOAT, Type::Float);
AddFormat(dawn::TextureFormat::RG8Unorm, GL_RG8, GL_RG, GL_UNSIGNED_BYTE, Type::Float);
AddFormat(dawn::TextureFormat::RG8Snorm, GL_RG8_SNORM, GL_RG, GL_BYTE, Type::Float);
AddFormat(dawn::TextureFormat::RG8Uint, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE, Type::Uint);
AddFormat(dawn::TextureFormat::RG8Sint, GL_RG8I, GL_RG_INTEGER, GL_BYTE, Type::Int);
// 4 bytes color formats
AddFormat(dawn::TextureFormat::R32Uint, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, Type::Uint);
AddFormat(dawn::TextureFormat::R32Sint, GL_R32I, GL_RED_INTEGER, GL_INT, Type::Int);
AddFormat(dawn::TextureFormat::R32Float, GL_R32F, GL_RED, GL_FLOAT, Type::Float);
AddFormat(dawn::TextureFormat::RG16Unorm, GL_RG16, GL_RG, GL_UNSIGNED_SHORT, Type::Float);
AddFormat(dawn::TextureFormat::RG16Snorm, GL_RG16_SNORM, GL_RG, GL_SHORT, Type::Float);
AddFormat(dawn::TextureFormat::RG16Uint, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, Type::Uint);
AddFormat(dawn::TextureFormat::RG16Sint, GL_RG16I, GL_RG_INTEGER, GL_SHORT, Type::Int);
AddFormat(dawn::TextureFormat::RG16Float, GL_RG16F, GL_RG, GL_HALF_FLOAT, Type::Float);
AddFormat(dawn::TextureFormat::RGBA8Unorm, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
AddFormat(dawn::TextureFormat::RGBA8UnormSrgb, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
AddFormat(dawn::TextureFormat::RGBA8Snorm, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE, Type::Float);
AddFormat(dawn::TextureFormat::RGBA8Uint, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, Type::Uint);
AddFormat(dawn::TextureFormat::RGBA8Sint, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, Type::Int);
// This doesn't have an enum for the internal format in OpenGL, so use RGBA8.
AddFormat(dawn::TextureFormat::BGRA8Unorm, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, Type::Float);
AddFormat(dawn::TextureFormat::RGB10A2Unorm, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, Type::Float);
AddFormat(dawn::TextureFormat::RG11B10Float, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, Type::Float);
// 8 bytes color formats
AddFormat(dawn::TextureFormat::RG32Uint, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, Type::Uint);
AddFormat(dawn::TextureFormat::RG32Sint, GL_RG32I, GL_RG_INTEGER, GL_INT, Type::Int);
AddFormat(dawn::TextureFormat::RG32Float, GL_RG32F, GL_RG, GL_FLOAT, Type::Float);
AddFormat(dawn::TextureFormat::RGBA16Unorm, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, Type::Float);
AddFormat(dawn::TextureFormat::RGBA16Snorm, GL_RGBA16_SNORM, GL_RGBA, GL_SHORT, Type::Float);
AddFormat(dawn::TextureFormat::RGBA16Uint, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, Type::Uint);
AddFormat(dawn::TextureFormat::RGBA16Sint, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT, Type::Int);
AddFormat(dawn::TextureFormat::RGBA16Float, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, Type::Float);
// 16 bytes color formats
AddFormat(dawn::TextureFormat::RGBA32Uint, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, Type::Uint);
AddFormat(dawn::TextureFormat::RGBA32Sint, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT, Type::Int);
AddFormat(dawn::TextureFormat::RGBA32Float, GL_RGBA32F, GL_RGBA, GL_FLOAT, Type::Float);
// Depth stencil formats
AddFormat(dawn::TextureFormat::Depth32Float, GL_DEPTH_COMPONENT32F, GL_DEPTH, GL_FLOAT, Type::DepthStencil);
AddFormat(dawn::TextureFormat::Depth24Plus, GL_DEPTH_COMPONENT32F, GL_DEPTH, GL_FLOAT, Type::DepthStencil);
AddFormat(dawn::TextureFormat::Depth24PlusStencil8, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, Type::DepthStencil);
// clang-format on
return table;
}

View File

@ -27,6 +27,11 @@ namespace dawn_native { namespace opengl {
GLenum format = 0;
GLenum type = 0;
bool isSupportedOnBackend = false;
// OpenGL has different functions depending on the format component type, for example
// glClearBufferfv is only valid on formats with the Float ComponentType
enum ComponentType { Float, Int, Uint, DepthStencil };
ComponentType componentType;
};
using GLFormatTable = std::array<GLFormat, kKnownFormatCount>;

View File

@ -438,7 +438,8 @@ class TextureFormatTest : public DawnTest {
1.0e29f, NAN, INFINITY, -INFINITY};
DoFloatFormatSamplingTest(formatInfo, textureData, textureData);
DoFormatRenderingTest(formatInfo, textureData, textureData);
DoFormatRenderingTest(formatInfo, textureData, textureData,
new ExpectFloatWithTolerance(textureData, 0.0f));
}
void DoFloat16Test(FormatTestInfo formatInfo) {
@ -506,121 +507,193 @@ TEST_P(TextureFormatTest, BGRA8Unorm) {
// Test the R8Snorm format
TEST_P(TextureFormatTest, R8Snorm) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSnormTest<int8_t>({dawn::TextureFormat::R8Snorm, 1, Float, 1});
}
// Test the RG8Snorm format
TEST_P(TextureFormatTest, RG8Snorm) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSnormTest<int8_t>({dawn::TextureFormat::RG8Snorm, 2, Float, 2});
}
// Test the RGBA8Snorm format
TEST_P(TextureFormatTest, RGBA8Snorm) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSnormTest<int8_t>({dawn::TextureFormat::RGBA8Snorm, 4, Float, 4});
}
// Test the R16Snorm format
TEST_P(TextureFormatTest, R16Snorm) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSnormTest<int16_t>({dawn::TextureFormat::R16Snorm, 2, Float, 1});
}
// Test the RG16Snorm format
TEST_P(TextureFormatTest, RG16Snorm) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSnormTest<int16_t>({dawn::TextureFormat::RG16Snorm, 4, Float, 2});
}
// Test the RGBA16Snorm format
TEST_P(TextureFormatTest, RGBA16Snorm) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSnormTest<int16_t>({dawn::TextureFormat::RGBA16Snorm, 8, Float, 4});
}
// Test the R8Uint format
TEST_P(TextureFormatTest, R8Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint8_t>({dawn::TextureFormat::R8Uint, 1, Uint, 1});
}
// Test the RG8Uint format
TEST_P(TextureFormatTest, RG8Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint8_t>({dawn::TextureFormat::RG8Uint, 2, Uint, 2});
}
// Test the RGBA8Uint format
TEST_P(TextureFormatTest, RGBA8Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint8_t>({dawn::TextureFormat::RGBA8Uint, 4, Uint, 4});
}
// Test the R16Uint format
TEST_P(TextureFormatTest, R16Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint16_t>({dawn::TextureFormat::R16Uint, 2, Uint, 1});
}
// Test the RG16Uint format
TEST_P(TextureFormatTest, RG16Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint16_t>({dawn::TextureFormat::RG16Uint, 4, Uint, 2});
}
// Test the RGBA16Uint format
TEST_P(TextureFormatTest, RGBA16Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint16_t>({dawn::TextureFormat::RGBA16Uint, 8, Uint, 4});
}
// Test the R32Uint format
TEST_P(TextureFormatTest, R32Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint32_t>({dawn::TextureFormat::R32Uint, 4, Uint, 1});
}
// Test the RG32Uint format
TEST_P(TextureFormatTest, RG32Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint32_t>({dawn::TextureFormat::RG32Uint, 8, Uint, 2});
}
// Test the RGBA32Uint format
TEST_P(TextureFormatTest, RGBA32Uint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoUintTest<uint32_t>({dawn::TextureFormat::RGBA32Uint, 16, Uint, 4});
}
// Test the R8Sint format
TEST_P(TextureFormatTest, R8Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int8_t>({dawn::TextureFormat::R8Sint, 1, Sint, 1});
}
// Test the RG8Sint format
TEST_P(TextureFormatTest, RG8Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int8_t>({dawn::TextureFormat::RG8Sint, 2, Sint, 2});
}
// Test the RGBA8Sint format
TEST_P(TextureFormatTest, RGBA8Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int8_t>({dawn::TextureFormat::RGBA8Sint, 4, Sint, 4});
}
// Test the R16Sint format
TEST_P(TextureFormatTest, R16Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int16_t>({dawn::TextureFormat::R16Sint, 2, Sint, 1});
}
// Test the RG16Sint format
TEST_P(TextureFormatTest, RG16Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int16_t>({dawn::TextureFormat::RG16Sint, 4, Sint, 2});
}
// Test the RGBA16Sint format
TEST_P(TextureFormatTest, RGBA16Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int16_t>({dawn::TextureFormat::RGBA16Sint, 8, Sint, 4});
}
// Test the R32Sint format
TEST_P(TextureFormatTest, R32Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int32_t>({dawn::TextureFormat::R32Sint, 4, Sint, 1});
}
// Test the RG32Sint format
TEST_P(TextureFormatTest, RG32Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int32_t>({dawn::TextureFormat::RG32Sint, 8, Sint, 2});
}
// Test the RGBA32Sint format
TEST_P(TextureFormatTest, RGBA32Sint) {
// TODO(cwallez@chromium.org): This fails on the Mesa Intel GL driver, understand why.
DAWN_SKIP_TEST_IF(IsOpenGL() && IsLinux() && IsIntel());
DoSintTest<int32_t>({dawn::TextureFormat::RGBA32Sint, 16, Sint, 4});
}
@ -676,6 +749,10 @@ TEST_P(TextureFormatTest, RGBA8UnormSrgb) {
// Test the BGRA8UnormSrgb format
TEST_P(TextureFormatTest, BGRA8UnormSrgb) {
// TODO(cwallez@chromium.org): This format doesn't exist in OpenGL, emulate it using
// RGBA8UnormSrgb and swizzling / shader twiddling
DAWN_SKIP_TEST_IF(IsOpenGL());
uint8_t maxValue = std::numeric_limits<uint8_t>::max();
std::vector<uint8_t> textureData = {0, 1, maxValue, 64, 35, 68, 152, 168};
@ -769,4 +846,4 @@ TEST_P(TextureFormatTest, RG11B10Float) {
// TODO(cwallez@chromium.org): Add tests for depth-stencil formats when we know if they are copyable
// in WebGPU.
DAWN_INSTANTIATE_TEST(TextureFormatTest, D3D12Backend, MetalBackend, VulkanBackend);
DAWN_INSTANTIATE_TEST(TextureFormatTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);