Commit 99cffe5d by Tim Van Patten Committed by Commit Bot

Vulkan: Fix glCopyTexSubImage3D()

Update glCopyTexSubImage3D() to account for the requirements necessary for VK_IMAGE_TYPE_3D. Bug: angleproject:3765 Test: KHR-GLES2.texture_3d.copy_sub_image.rgba8 Test: angle_end2end_tests CopyTexImageTestES3 Change-Id: Ife3d768323d0cfe2a53e5ae4c47a0747d65981bc Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1730637Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Tim Van Patten <timvp@google.com>
parent 7e48c9eb
...@@ -395,8 +395,10 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context, ...@@ -395,8 +395,10 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
// If negative offsets are given, clippedSourceArea ensures we don't read from those offsets. // If negative offsets are given, clippedSourceArea ensures we don't read from those offsets.
// However, that changes the sourceOffset->destOffset mapping. Here, destOffset is shifted by // However, that changes the sourceOffset->destOffset mapping. Here, destOffset is shifted by
// the same amount as clipped to correct the error. // the same amount as clipped to correct the error.
VkImageType imageType = gl_vk::GetImageType(mState.getType());
int zOffset = (imageType == VK_IMAGE_TYPE_3D) ? destOffset.z : 0;
const gl::Offset modifiedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x, const gl::Offset modifiedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
destOffset.y + clippedSourceArea.y - sourceArea.y, 0); destOffset.y + clippedSourceArea.y - sourceArea.y, zOffset);
RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget(); RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
...@@ -578,6 +580,13 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, ...@@ -578,6 +580,13 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
destSubresource.mipLevel = level; destSubresource.mipLevel = level;
destSubresource.baseArrayLayer = baseLayer; destSubresource.baseArrayLayer = baseLayer;
VkImageType imageType = gl_vk::GetImageType(mState.getType());
if (imageType == VK_IMAGE_TYPE_3D)
{
destSubresource.baseArrayLayer = 0;
destSubresource.layerCount = 1;
}
vk::ImageHelper::Copy(srcImage, mImage, srcOffset, destOffset, extents, srcSubresource, vk::ImageHelper::Copy(srcImage, mImage, srcOffset, destOffset, extents, srcSubresource,
destSubresource, commandBuffer); destSubresource, commandBuffer);
} }
...@@ -610,7 +619,9 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, ...@@ -610,7 +619,9 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
srcSubresource, destSubresource, commandBuffer); srcSubresource, destSubresource, commandBuffer);
// Stage the copy for when the image storage is actually created. // Stage the copy for when the image storage is actually created.
mImage->stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset, extents); VkImageType imageType = gl_vk::GetImageType(mState.getType());
mImage->stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset, extents,
imageType);
onStagingBufferChange(); onStagingBufferChange();
} }
...@@ -705,9 +716,10 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, ...@@ -705,9 +716,10 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
} }
// Stage the copy for when the image storage is actually created. // Stage the copy for when the image storage is actually created.
mImage->stageSubresourceUpdateFromImage( VkImageType imageType = gl_vk::GetImageType(mState.getType());
stagingImage.release(), index, destOffset, mImage->stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset,
gl::Extents(sourceArea.width, sourceArea.height, 1)); gl::Extents(sourceArea.width, sourceArea.height, 1),
imageType);
onStagingBufferChange(); onStagingBufferChange();
} }
......
...@@ -2366,15 +2366,33 @@ angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer( ...@@ -2366,15 +2366,33 @@ angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer(
void ImageHelper::stageSubresourceUpdateFromImage(vk::ImageHelper *image, void ImageHelper::stageSubresourceUpdateFromImage(vk::ImageHelper *image,
const gl::ImageIndex &index, const gl::ImageIndex &index,
const gl::Offset &destOffset, const gl::Offset &destOffset,
const gl::Extents &glExtents) const gl::Extents &glExtents,
const VkImageType imageType)
{ {
VkImageCopy copyToImage = {}; VkImageCopy copyToImage = {};
copyToImage.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; copyToImage.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyToImage.srcSubresource.layerCount = index.getLayerCount(); copyToImage.srcSubresource.layerCount = index.getLayerCount();
copyToImage.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; copyToImage.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyToImage.dstSubresource.mipLevel = index.getLevelIndex(); copyToImage.dstSubresource.mipLevel = index.getLevelIndex();
if (imageType == VK_IMAGE_TYPE_3D)
{
// These values must be set explicitly to follow the Vulkan spec:
// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkImageCopy.html
// If either of the calling command’s srcImage or dstImage parameters are of VkImageType
// VK_IMAGE_TYPE_3D, the baseArrayLayer and layerCount members of the corresponding
// subresource must be 0 and 1, respectively
copyToImage.dstSubresource.baseArrayLayer = 0;
copyToImage.dstSubresource.layerCount = 1;
// Preserve the assumption that destOffset.z == "dstSubresource.baseArrayLayer"
ASSERT(destOffset.z == (index.hasLayer() ? index.getLayerIndex() : 0));
}
else
{
copyToImage.dstSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0; copyToImage.dstSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
copyToImage.dstSubresource.layerCount = index.getLayerCount(); copyToImage.dstSubresource.layerCount = index.getLayerCount();
}
gl_vk::GetOffset(destOffset, &copyToImage.dstOffset); gl_vk::GetOffset(destOffset, &copyToImage.dstOffset);
gl_vk::GetExtent(glExtents, &copyToImage.extent); gl_vk::GetExtent(glExtents, &copyToImage.extent);
......
...@@ -791,7 +791,8 @@ class ImageHelper final : public CommandGraphResource ...@@ -791,7 +791,8 @@ class ImageHelper final : public CommandGraphResource
void stageSubresourceUpdateFromImage(vk::ImageHelper *image, void stageSubresourceUpdateFromImage(vk::ImageHelper *image,
const gl::ImageIndex &index, const gl::ImageIndex &index,
const gl::Offset &destOffset, const gl::Offset &destOffset,
const gl::Extents &glExtents); const gl::Extents &glExtents,
const VkImageType imageType);
// Stage a clear operation to a clear value based on WebGL requirements. // Stage a clear operation to a clear value based on WebGL requirements.
void stageSubresourceRobustClear(const gl::ImageIndex &index, const angle::Format &format); void stageSubresourceRobustClear(const gl::ImageIndex &index, const angle::Format &format);
......
...@@ -35,8 +35,9 @@ ...@@ -35,8 +35,9 @@
// 3d texture framebuffer tests // 3d texture framebuffer tests
3188 VULKAN : KHR-GLES2.texture_3d.framebuffer_texture.rgba8 = SKIP 3188 VULKAN : KHR-GLES2.texture_3d.framebuffer_texture.rgba8 = SKIP
// Unclear what is happening here, failing to validate a 2D texture format // GL_RGBA8 is not supported in GLES2
3190 VULKAN : KHR-GLES2.texture_3d.copy_sub_image.rgba8 = SKIP // GL_OES_rgb8_rgba8 only enables GL_RGBA8 for render buffers (not textures)
3797 VULKAN : KHR-GLES2.texture_3d.copy_sub_image.rgba8 = FAIL
// Compressed texture tests on Android // Compressed texture tests on Android
3190 VULKAN PIXEL2 : KHR-GLES2.texture_3d.compressed_texture.rgba_astc_* = SKIP 3190 VULKAN PIXEL2 : KHR-GLES2.texture_3d.compressed_texture.rgba_astc_* = SKIP
......
...@@ -482,7 +482,47 @@ TEST_P(CopyTexImageTest, CopyTexSubImageToNonCubeCompleteDestination) ...@@ -482,7 +482,47 @@ TEST_P(CopyTexImageTest, CopyTexSubImageToNonCubeCompleteDestination)
// specialization of CopyTexImageTest is added so that some tests can be explicitly run with an ES3 // specialization of CopyTexImageTest is added so that some tests can be explicitly run with an ES3
// context // context
class CopyTexImageTestES3 : public CopyTexImageTest class CopyTexImageTestES3 : public CopyTexImageTest
{}; {
protected:
void initialize3DTexture(GLTexture &texture,
const GLsizei imageWidth,
const GLsizei imageHeight,
const GLsizei imageDepth,
const GLColor *textureData);
void initialize2DTexture(GLTexture &texture,
const GLsizei imageWidth,
const GLsizei imageHeight,
const GLColor *textureData);
void initialize2DTextureUShort4444(GLTexture &texture,
const GLsizei imageWidth,
const GLsizei imageHeight,
const GLColor *textureData);
void fillTexture(std::vector<GLColor> &texture, const GLColor color);
void clearTexture(GLFramebuffer &fbo, GLTexture &texture, const GLColor color);
void copyTexSubImage3D(GLTexture &subTexture2D,
const GLint xOffset,
const GLint yOffset,
const GLsizei subImageWidth,
const GLsizei subImageHeight,
const GLsizei imageDepth);
void verifyCopyTexSubImage3D(GLTexture &texture3D,
const GLint xOffset,
const GLint yOffset,
const GLColor subImageColor);
// Constants
const GLColor kSubImageColor = GLColor::yellow;
// 3D image dimensions
const GLsizei kImageWidth = getWindowWidth();
const GLsizei kImageHeight = getWindowHeight();
const GLsizei kImageDepth = 4;
// 2D sub-image dimensions
const GLsizei kSubImageWidth = getWindowWidth() / 4;
const GLsizei kSubImageHeight = getWindowHeight() / 4;
// Sub-Image Offsets
const GLint kXOffset = getWindowWidth() - kSubImageWidth;
const GLint kYOffset = getWindowHeight() - kSubImageHeight;
};
// The test verifies that glCopyTexSubImage2D generates a GL_INVALID_OPERATION error // The test verifies that glCopyTexSubImage2D generates a GL_INVALID_OPERATION error
// when the read buffer is GL_NONE. // when the read buffer is GL_NONE.
...@@ -511,6 +551,8 @@ TEST_P(CopyTexImageTestES3, 2DArraySubImage) ...@@ -511,6 +551,8 @@ TEST_P(CopyTexImageTestES3, 2DArraySubImage)
{ {
// Seems to fail on AMD OpenGL Windows. // Seems to fail on AMD OpenGL Windows.
ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() & IsWindows()); ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() & IsWindows());
// TODO(anglebug.com/3189): Need full 2D-array texture support
ANGLE_SKIP_TEST_IF(IsVulkan());
GLTexture tex; GLTexture tex;
glBindTexture(GL_TEXTURE_2D_ARRAY, tex); glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
...@@ -540,6 +582,224 @@ TEST_P(CopyTexImageTestES3, 2DArraySubImage) ...@@ -540,6 +582,224 @@ TEST_P(CopyTexImageTestES3, 2DArraySubImage)
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
// Initialize the 3D texture we will copy the subImage data into
void CopyTexImageTestES3::initialize3DTexture(GLTexture &texture,
const GLsizei imageWidth,
const GLsizei imageHeight,
const GLsizei imageDepth,
const GLColor *textureData)
{
glBindTexture(GL_TEXTURE_3D, texture);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, imageWidth, imageHeight, imageDepth, 0, GL_RGBA,
GL_UNSIGNED_BYTE, textureData);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
void CopyTexImageTestES3::initialize2DTexture(GLTexture &texture,
const GLsizei imageWidth,
const GLsizei imageHeight,
const GLColor *textureData)
{
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
textureData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
void CopyTexImageTestES3::initialize2DTextureUShort4444(GLTexture &texture,
const GLsizei imageWidth,
const GLsizei imageHeight,
const GLColor *textureData)
{
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA,
GL_UNSIGNED_SHORT_4_4_4_4, textureData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
void CopyTexImageTestES3::fillTexture(std::vector<GLColor> &texture, const GLColor color)
{
for (auto &texel : texture)
{
texel = color;
}
}
void CopyTexImageTestES3::clearTexture(GLFramebuffer &fbo, GLTexture &texture, const GLColor color)
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glClearColor(color.R, color.G, color.B, color.A);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, color);
}
void CopyTexImageTestES3::copyTexSubImage3D(GLTexture &subTexture2D,
const GLint xOffset,
const GLint yOffset,
const GLsizei subImageWidth,
const GLsizei subImageHeight,
const GLsizei imageDepth)
{
// Copy the 2D sub-image into the 3D texture
for (int currLayer = 0; currLayer < imageDepth; ++currLayer)
{
// Bind the 2D texture to GL_COLOR_ATTACHMENT0
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
subTexture2D, 0);
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glCopyTexSubImage3D(GL_TEXTURE_3D, 0, xOffset, yOffset, currLayer, 0, 0, subImageWidth,
subImageHeight);
ASSERT_GL_NO_ERROR();
}
}
void CopyTexImageTestES3::verifyCopyTexSubImage3D(GLTexture &texture3D,
const GLint xOffset,
const GLint yOffset,
const GLColor subImageColor)
{
// Bind to an FBO to check the copy was successful
for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)
{
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0, currLayer);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(xOffset, yOffset, subImageColor);
}
}
// Test glCopyTexSubImage3D with initialized texture data
TEST_P(CopyTexImageTestES3, 3DSubImageRawTextureData)
{
// Texture data
std::vector<GLColor> textureData(kImageWidth * kImageHeight * kImageDepth);
// Fill the textures with color
fillTexture(textureData, GLColor::red);
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLTexture texture3D;
initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, textureData.data());
// The 2D texture that will be the sub-image copied into the destination texture
GLTexture subTexture2D;
initialize2DTexture(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);
clearTexture(fbo, subTexture2D, kSubImageColor);
// Copy the 2D subimage into the 3D texture
copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,
kImageDepth);
// Verify the color wasn't overwritten
verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::red);
// Verify the copy succeeded
verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_3D, 0);
}
// Test glCopyTexSubImage3D with initialized texture data that was drawn to
TEST_P(CopyTexImageTestES3, 3DSubImageDrawTextureData)
{
// TODO(anglebug.com/3801)
ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// The 3D texture we will copy the sub-image into
GLTexture texture3D;
initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, nullptr);
// Draw to each layer in the 3D texture
for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)
{
ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0,
currLayer);
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0,
currLayer);
ASSERT_GL_NO_ERROR();
glUseProgram(greenProgram);
drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// The 2D texture that will be the sub-image copied into the destination texture
GLTexture subTexture2D;
initialize2DTexture(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);
clearTexture(fbo, subTexture2D, kSubImageColor);
// Copy the 2D sub-image into the 3D texture
copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,
kImageDepth);
// Verify the color wasn't overwritten
verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::green);
// Verify the copy succeeded
verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_3D, 0);
}
// Test glCopyTexSubImage3D with mismatched texture formats
TEST_P(CopyTexImageTestES3, 3DSubImageDrawMismatchedTextureTypes)
{
// TODO(anglebug.com/3801)
ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// The 3D texture we will copy the sub-image into
GLTexture texture3D;
initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, nullptr);
// Draw to each layer in the 3D texture
for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)
{
ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0, currLayer);
ASSERT_GL_NO_ERROR();
glUseProgram(greenProgram);
drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// The 2D texture that will be the sub-image copied into the destination texture
GLTexture subTexture2D;
initialize2DTextureUShort4444(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);
clearTexture(fbo, subTexture2D, kSubImageColor);
// Copy the 2D sub-image into the 3D texture
copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,
kImageDepth);
// Verify the color wasn't overwritten
verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::green);
// Verify the copy succeeded
verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_3D, 0);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(CopyTexImageTest, ANGLE_INSTANTIATE_TEST(CopyTexImageTest,
...@@ -548,7 +808,12 @@ ANGLE_INSTANTIATE_TEST(CopyTexImageTest, ...@@ -548,7 +808,12 @@ ANGLE_INSTANTIATE_TEST(CopyTexImageTest,
ES2_D3D11_PRESENT_PATH_FAST(), ES2_D3D11_PRESENT_PATH_FAST(),
ES2_OPENGL(), ES2_OPENGL(),
ES2_OPENGLES(), ES2_OPENGLES(),
ES2_VULKAN()); ES2_VULKAN(),
ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(CopyTexImageTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(CopyTexImageTestES3,
ES3_D3D11(),
ES3_OPENGL(),
ES3_OPENGLES(),
ES3_VULKAN());
} // namespace angle } // namespace angle
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