Commit 900c7e87 by Manh Nguyen Committed by Commit Bot

Serialize d/s buffers + use color buffers' impl format for readPixels

Adds serialization of depth/stencil buffer contents Currently, readPixels on color buffers uses the gles front-end format, which can be different from the implementation format used in the backend. This can cause seg fault crashes when the number of bytes in a pixel differs between the two format. Changes so that readPixels for color buffers always use the backend format. Bug: angleproject:4817 Change-Id: I62d5deb1320ea38ee46143b2aa97f372ba01baeb Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2284451Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Manh Nguyen <nguyenmh@google.com>
parent 514c8f64
...@@ -17,16 +17,22 @@ namespace angle ...@@ -17,16 +17,22 @@ namespace angle
// MemoryBuffer implementation. // MemoryBuffer implementation.
MemoryBuffer::~MemoryBuffer() MemoryBuffer::~MemoryBuffer()
{ {
free(mData); if (mData)
mData = nullptr; {
free(mData);
mData = nullptr;
}
} }
bool MemoryBuffer::resize(size_t size) bool MemoryBuffer::resize(size_t size)
{ {
if (size == 0) if (size == 0)
{ {
free(mData); if (mData)
mData = nullptr; {
free(mData);
mData = nullptr;
}
mSize = 0; mSize = 0;
return true; return true;
} }
......
...@@ -930,8 +930,7 @@ void WriteCppReplayIndexFiles(bool compression, ...@@ -930,8 +930,7 @@ void WriteCppReplayIndexFiles(bool compression,
if (serializeStateEnabled) if (serializeStateEnabled)
{ {
gl::BinaryOutputStream serializedContextData{}; gl::BinaryOutputStream serializedContextData{};
if (SerializeContext(&serializedContextData, const_cast<gl::Context *>(context)) != if (SerializeContext(&serializedContextData, context) != Result::Continue)
Result::Continue)
{ {
return; return;
} }
......
...@@ -14,28 +14,41 @@ ...@@ -14,28 +14,41 @@
#include "libANGLE/BinaryStream.h" #include "libANGLE/BinaryStream.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/renderer/FramebufferImpl.h"
namespace angle namespace angle
{ {
Result ReadPixelsFromAttachment(gl::Context *context, bool IsValidColorAttachmentBinding(GLenum binding, size_t colorAttachmentsCount)
{
return binding == GL_BACK || (binding >= GL_COLOR_ATTACHMENT0 &&
(binding - GL_COLOR_ATTACHMENT0) < colorAttachmentsCount);
}
Result ReadPixelsFromAttachment(const gl::Context *context,
gl::Framebuffer *framebuffer, gl::Framebuffer *framebuffer,
const gl::FramebufferAttachment &framebufferAttachment, const gl::FramebufferAttachment &framebufferAttachment,
ScratchBuffer *scratchBuffer, ScratchBuffer *scratchBuffer,
MemoryBuffer **pixels) MemoryBuffer **pixels)
{ {
gl::Extents extents = framebufferAttachment.getSize(); gl::Extents extents = framebufferAttachment.getSize();
gl::Format format = framebufferAttachment.getFormat(); GLenum binding = framebufferAttachment.getBinding();
ANGLE_CHECK_GL_ALLOC( gl::InternalFormat format = *framebufferAttachment.getFormat().info;
context, if (IsValidColorAttachmentBinding(binding,
scratchBuffer->get(format.info->pixelBytes * extents.width * extents.height, pixels)); framebuffer->getState().getColorAttachments().size()))
{
format = framebuffer->getImplementation()->getImplementationColorReadFormat(context);
}
ANGLE_CHECK_GL_ALLOC(const_cast<gl::Context *>(context),
scratchBuffer->getInitialized(
format.pixelBytes * extents.width * extents.height, pixels, 0));
ANGLE_TRY(framebuffer->readPixels(context, gl::Rectangle{0, 0, extents.width, extents.height}, ANGLE_TRY(framebuffer->readPixels(context, gl::Rectangle{0, 0, extents.width, extents.height},
format.info->format, format.info->type, gl::PixelPackState{}, format.format, format.type, gl::PixelPackState{}, nullptr,
nullptr, (*pixels)->data())); (*pixels)->data()));
return Result::Continue; return Result::Continue;
} }
Result SerializeContext(gl::BinaryOutputStream *bos, gl::Context *context) Result SerializeContext(gl::BinaryOutputStream *bos, const gl::Context *context)
{ {
const gl::FramebufferManager &framebufferManager = const gl::FramebufferManager &framebufferManager =
context->getState().getFramebufferManagerForCapture(); context->getState().getFramebufferManagerForCapture();
...@@ -47,14 +60,14 @@ Result SerializeContext(gl::BinaryOutputStream *bos, gl::Context *context) ...@@ -47,14 +60,14 @@ Result SerializeContext(gl::BinaryOutputStream *bos, gl::Context *context)
return Result::Continue; return Result::Continue;
} }
Result SerializeFramebuffer(gl::Context *context, Result SerializeFramebuffer(const gl::Context *context,
gl::BinaryOutputStream *bos, gl::BinaryOutputStream *bos,
gl::Framebuffer *framebuffer) gl::Framebuffer *framebuffer)
{ {
return SerializeFramebufferState(context, bos, framebuffer, framebuffer->getState()); return SerializeFramebufferState(context, bos, framebuffer, framebuffer->getState());
} }
Result SerializeFramebufferState(gl::Context *context, Result SerializeFramebufferState(const gl::Context *context,
gl::BinaryOutputStream *bos, gl::BinaryOutputStream *bos,
gl::Framebuffer *framebuffer, gl::Framebuffer *framebuffer,
const gl::FramebufferState &framebufferState) const gl::FramebufferState &framebufferState)
...@@ -69,9 +82,6 @@ Result SerializeFramebufferState(gl::Context *context, ...@@ -69,9 +82,6 @@ Result SerializeFramebufferState(gl::Context *context,
bos->writeInt(framebufferState.getDefaultFixedSampleLocations()); bos->writeInt(framebufferState.getDefaultFixedSampleLocations());
bos->writeInt(framebufferState.getDefaultLayers()); bos->writeInt(framebufferState.getDefaultLayers());
context->bindFramebuffer(GL_FRAMEBUFFER, framebufferState.id());
ANGLE_TRY(framebuffer->syncState(context, GL_FRAMEBUFFER));
const std::vector<gl::FramebufferAttachment> &colorAttachments = const std::vector<gl::FramebufferAttachment> &colorAttachments =
framebufferState.getColorAttachments(); framebufferState.getColorAttachments();
ScratchBuffer scratchBuffer(1); ScratchBuffer scratchBuffer(1);
...@@ -83,11 +93,29 @@ Result SerializeFramebufferState(gl::Context *context, ...@@ -83,11 +93,29 @@ Result SerializeFramebufferState(gl::Context *context,
colorAttachment)); colorAttachment));
} }
} }
if (framebuffer->getDepthStencilAttachment())
{
ANGLE_TRY(SerializeFramebufferAttachment(context, bos, &scratchBuffer, framebuffer,
*framebuffer->getDepthStencilAttachment()));
}
else
{
if (framebuffer->getDepthAttachment())
{
ANGLE_TRY(SerializeFramebufferAttachment(context, bos, &scratchBuffer, framebuffer,
*framebuffer->getDepthAttachment()));
}
if (framebuffer->getStencilAttachment())
{
ANGLE_TRY(SerializeFramebufferAttachment(context, bos, &scratchBuffer, framebuffer,
*framebuffer->getStencilAttachment()));
}
}
scratchBuffer.clear(); scratchBuffer.clear();
return Result::Continue; return Result::Continue;
} }
Result SerializeFramebufferAttachment(gl::Context *context, Result SerializeFramebufferAttachment(const gl::Context *context,
gl::BinaryOutputStream *bos, gl::BinaryOutputStream *bos,
ScratchBuffer *scratchBuffer, ScratchBuffer *scratchBuffer,
gl::Framebuffer *framebuffer, gl::Framebuffer *framebuffer,
...@@ -100,17 +128,25 @@ Result SerializeFramebufferAttachment(gl::Context *context, ...@@ -100,17 +128,25 @@ Result SerializeFramebufferAttachment(gl::Context *context,
{ {
SerializeImageIndex(bos, framebufferAttachment.getTextureImageIndex()); SerializeImageIndex(bos, framebufferAttachment.getTextureImageIndex());
} }
bos->writeInt(framebufferAttachment.getNumViews()); bos->writeInt(framebufferAttachment.getNumViews());
bos->writeInt(framebufferAttachment.isMultiview()); bos->writeInt(framebufferAttachment.isMultiview());
bos->writeInt(framebufferAttachment.getBaseViewIndex()); bos->writeInt(framebufferAttachment.getBaseViewIndex());
bos->writeInt(framebufferAttachment.getRenderToTextureSamples()); bos->writeInt(framebufferAttachment.getRenderToTextureSamples());
GLenum prevReadBufferState = framebuffer->getReadBufferState();
GLenum binding = framebufferAttachment.getBinding();
if (IsValidColorAttachmentBinding(binding,
framebuffer->getState().getColorAttachments().size()))
{
framebuffer->setReadBuffer(framebufferAttachment.getBinding());
ANGLE_TRY(framebuffer->syncState(context, GL_FRAMEBUFFER));
}
MemoryBuffer *pixelsPtr = nullptr; MemoryBuffer *pixelsPtr = nullptr;
context->readBuffer(framebufferAttachment.getBinding());
ANGLE_TRY(framebuffer->syncState(context, GL_FRAMEBUFFER));
ANGLE_TRY(ReadPixelsFromAttachment(context, framebuffer, framebufferAttachment, scratchBuffer, ANGLE_TRY(ReadPixelsFromAttachment(context, framebuffer, framebufferAttachment, scratchBuffer,
&pixelsPtr)); &pixelsPtr));
bos->writeBytes(pixelsPtr->data(), pixelsPtr->size()); bos->writeBytes(pixelsPtr->data(), pixelsPtr->size());
// Reset framebuffer state
framebuffer->setReadBuffer(prevReadBufferState);
return Result::Continue; return Result::Continue;
} }
......
...@@ -30,18 +30,18 @@ namespace angle ...@@ -30,18 +30,18 @@ namespace angle
class MemoryBuffer; class MemoryBuffer;
class ScratchBuffer; class ScratchBuffer;
Result SerializeContext(gl::BinaryOutputStream *bos, gl::Context *context); Result SerializeContext(gl::BinaryOutputStream *bos, const gl::Context *context);
Result SerializeFramebuffer(gl::Context *context, Result SerializeFramebuffer(const gl::Context *context,
gl::BinaryOutputStream *bos, gl::BinaryOutputStream *bos,
gl::Framebuffer *framebuffer); gl::Framebuffer *framebuffer);
Result SerializeFramebufferState(gl::Context *context, Result SerializeFramebufferState(const gl::Context *context,
gl::BinaryOutputStream *bos, gl::BinaryOutputStream *bos,
gl::Framebuffer *framebuffer, gl::Framebuffer *framebuffer,
const gl::FramebufferState &framebufferState); const gl::FramebufferState &framebufferState);
Result SerializeFramebufferAttachment(gl::Context *context, Result SerializeFramebufferAttachment(const gl::Context *context,
gl::BinaryOutputStream *bos, gl::BinaryOutputStream *bos,
ScratchBuffer *scratchBuffer, ScratchBuffer *scratchBuffer,
gl::Framebuffer *framebuffer, gl::Framebuffer *framebuffer,
......
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