Commit 943fe34e by Courtney Goeltzenleuchter Committed by Commit Bot

Vulkan: Upload packed depth-stencil

Bug: angleproject:3437 Test: angle_end2end_tests --gtest_filter=DepthStencilFormatsTest.VerifyStencilData/* Change-Id: Iffab48eaea6aa35888560859e9f502a4f814b833 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1674663Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com>
parent 375ddfc5
......@@ -1266,6 +1266,32 @@ void LoadD32FS8X24ToD24S8(size_t width,
}
}
void LoadX24S8ToS8(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch)
{
for (size_t z = 0; z < depth; z++)
{
for (size_t y = 0; y < height; y++)
{
const uint32_t *source = reinterpret_cast<const uint32_t *>(
input + (y * inputRowPitch) + (z * inputDepthPitch));
uint8_t *destStencil =
reinterpret_cast<uint8_t *>(output + (y * outputRowPitch) + (z * outputDepthPitch));
for (size_t x = 0; x < width; x++)
{
destStencil[x] = (source[x] & 0xFF);
}
}
}
}
void LoadD32FS8X24ToD32FS8X24(size_t width,
size_t height,
size_t depth,
......
......@@ -415,6 +415,16 @@ void LoadD32FS8X24ToD24S8(size_t width,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadX24S8ToS8(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadD32FS8X24ToD32FS8X24(size_t width,
size_t height,
size_t depth,
......
......@@ -9,6 +9,7 @@
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "common/utilities.h"
#include "image_util/loadimage.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/renderer_utils.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
......@@ -2081,6 +2082,7 @@ angle::Result ImageHelper::stageSubresourceUpdate(ContextVk *contextVk,
size_t outputRowPitch;
size_t outputDepthPitch;
size_t stencilAllocationSize = 0;
uint32_t bufferRowLength;
uint32_t bufferImageHeight;
......@@ -2119,13 +2121,23 @@ angle::Result ImageHelper::stageSubresourceUpdate(ContextVk *contextVk,
bufferRowLength = extents.width;
bufferImageHeight = extents.height;
// Note: because the LoadImageFunctionInfo functions are limited to copying a single
// component, we have to special case packed depth/stencil use and send the stencil as a
// separate chunk.
if (storageFormat.depthBits > 0 && storageFormat.stencilBits > 0 &&
formatInfo.depthBits > 0 && formatInfo.stencilBits > 0)
{
// Note: Stencil is always one byte
stencilAllocationSize = extents.width * extents.height * extents.depth;
}
}
VkBuffer bufferHandle = VK_NULL_HANDLE;
uint8_t *stagingPointer = nullptr;
VkDeviceSize stagingOffset = 0;
size_t allocationSize = outputDepthPitch * extents.depth;
size_t allocationSize = outputDepthPitch * extents.depth + stencilAllocationSize;
ANGLE_TRY(mStagingBuffer.allocate(contextVk, allocationSize, &stagingPointer, &bufferHandle,
&stagingOffset, nullptr));
......@@ -2149,14 +2161,55 @@ angle::Result ImageHelper::stageSubresourceUpdate(ContextVk *contextVk,
gl_vk::GetOffset(offset, &copy.imageOffset);
gl_vk::GetExtent(extents, &copy.imageExtent);
// TODO: http://anglebug.com/3437 - need to split packed depth_stencil into
// staging buffers for upload.
// Ignore stencil for now.
if (aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT)
if (stencilAllocationSize > 0)
{
// Note: Stencil is always one byte
ASSERT((aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) != 0);
// Skip over depth data.
stagingPointer += outputDepthPitch * extents.depth;
stagingOffset += outputDepthPitch * extents.depth;
// recompute pitch for stencil data
outputRowPitch = extents.width;
outputDepthPitch = outputRowPitch * extents.height;
angle::LoadX24S8ToS8(extents.width, extents.height, extents.depth, source, inputRowPitch,
inputDepthPitch, stagingPointer, outputRowPitch, outputDepthPitch);
VkBufferImageCopy stencilCopy = {};
stencilCopy.bufferOffset = stagingOffset;
stencilCopy.bufferRowLength = bufferRowLength;
stencilCopy.bufferImageHeight = bufferImageHeight;
stencilCopy.imageSubresource.mipLevel = index.getLevelIndex();
stencilCopy.imageSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
stencilCopy.imageSubresource.layerCount = index.getLayerCount();
gl_vk::GetOffset(offset, &stencilCopy.imageOffset);
gl_vk::GetExtent(extents, &stencilCopy.imageExtent);
stencilCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
mSubresourceUpdates.emplace_back(bufferHandle, stencilCopy);
aspectFlags &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
}
if (IsMaskFlagSet(aspectFlags, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_STENCIL_BIT |
VK_IMAGE_ASPECT_DEPTH_BIT)))
{
// We still have both depth and stencil aspect bits set. That means we have a destination
// buffer that is packed depth stencil and that the application is only loading one aspect.
// Figure out which aspect the user is touching and remove the unused aspect bit.
if (formatInfo.stencilBits > 0)
{
aspectFlags &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
}
else
{
aspectFlags &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
}
}
if (aspectFlags)
{
copy.imageSubresource.aspectMask = aspectFlags;
......
......@@ -547,7 +547,7 @@ TEST_P(DepthStencilFormatsTest, DepthBuffer24)
}
}
TEST_P(DepthStencilFormatsTestES3, DrawWithDepthStencil)
TEST_P(DepthStencilFormatsTestES3, DrawWithDepth16)
{
GLushort data[16];
for (unsigned int i = 0; i < 16; i++)
......@@ -635,6 +635,106 @@ TEST_P(DepthStencilFormatsTestES3, DrawWithLargeViewport)
}
}
// Verify that stencil component of depth texture is uploaded
TEST_P(DepthStencilFormatsTest, VerifyDepthStencilUploadData)
{
// http://anglebug.com/3683
// When bug is resolved we can remove this skip.
ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
// http://anglebug.com/3689
ANGLE_SKIP_TEST_IF(IsWindows() && IsVulkan() && IsAMD());
bool shouldHaveTextureSupport = (IsGLExtensionEnabled("GL_OES_packed_depth_stencil") &&
IsGLExtensionEnabled("GL_OES_depth_texture")) ||
(getClientMajorVersion() >= 3);
ANGLE_SKIP_TEST_IF(!shouldHaveTextureSupport ||
!checkTexImageFormatSupport(GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES));
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
glEnable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glViewport(0, 0, getWindowWidth(), getWindowHeight());
glClearColor(0, 0, 0, 1);
// Create offscreen fbo and its color attachment and depth stencil attachment.
GLTexture framebufferColorTexture;
glBindTexture(GL_TEXTURE_2D, framebufferColorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
ASSERT_GL_NO_ERROR();
// drawQuad's depth range is -1.0 to 1.0, so a depth value of 0.5 (0x7fffff) matches a drawQuad
// depth of 0.0.
std::vector<GLuint> depthStencilData(getWindowWidth() * getWindowHeight(), 0x7fffffA9);
GLTexture framebufferStencilTexture;
glBindTexture(GL_TEXTURE_2D, framebufferStencilTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, getWindowWidth(), getWindowHeight(), 0,
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8_OES, depthStencilData.data());
ASSERT_GL_NO_ERROR();
GLFramebuffer fb;
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
framebufferColorTexture, 0);
if (getClientMajorVersion() >= 3)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
framebufferStencilTexture, 0);
ASSERT_GL_NO_ERROR();
}
else
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
framebufferStencilTexture, 0);
ASSERT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
framebufferStencilTexture, 0);
ASSERT_GL_NO_ERROR();
}
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
GLint kStencilRef = 0xA9;
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, kStencilRef, 0xFF);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
glClear(GL_COLOR_BUFFER_BIT);
drawQuad(program.get(), essl1_shaders::PositionAttrib(), 1.0f);
ASSERT_GL_NO_ERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
ASSERT_GL_NO_ERROR();
// Check Z values
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
drawQuad(program.get(), essl1_shaders::PositionAttrib(), -0.1f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
glClear(GL_COLOR_BUFFER_BIT);
drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.1f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::black);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(DepthStencilFormatsTest,
......
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