unplugged-system/external/angle/util/capture/trace_fixture.cpp

656 lines
20 KiB
C++
Raw Normal View History

//
// Copyright 2021 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.
//
// trace_fixture.cpp:
// Common code for the ANGLE trace replays.
//
#include "trace_fixture.h"
#include "angle_trace_gl.h"
#include <string>
namespace
{
void UpdateResourceMap(GLuint *resourceMap, GLuint id, GLsizei readBufferOffset)
{
GLuint returnedID;
memcpy(&returnedID, &gReadBuffer[readBufferOffset], sizeof(GLuint));
resourceMap[id] = returnedID;
}
DecompressCallback gDecompressCallback;
DeleteCallback gDeleteCallback;
void DeleteBinaryData()
{
if (gBinaryData)
{
if (gDeleteCallback)
{
gDeleteCallback(gBinaryData);
}
else
{
delete[] gBinaryData;
}
gBinaryData = nullptr;
}
}
void LoadBinaryData(const char *fileName)
{
DeleteBinaryData();
char pathBuffer[1000] = {};
snprintf(pathBuffer, sizeof(pathBuffer), "%s/%s", gBinaryDataDir.c_str(), fileName);
FILE *fp = fopen(pathBuffer, "rb");
if (fp == 0)
{
fprintf(stderr, "Error loading binary data file: %s\n", fileName);
return;
}
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
if (gDecompressCallback)
{
if (!strstr(fileName, ".gz"))
{
fprintf(stderr, "Filename does not end in .gz");
exit(1);
}
std::vector<uint8_t> compressedData(size);
(void)fread(compressedData.data(), 1, size, fp);
gBinaryData = gDecompressCallback(compressedData);
if (gBinaryData == nullptr)
{
// Error already printed by the callback
exit(1);
}
}
else
{
if (!strstr(fileName, ".angledata"))
{
fprintf(stderr, "Filename does not end in .angledata");
exit(1);
}
gBinaryData = new uint8_t[size];
(void)fread(gBinaryData, 1, size, fp);
}
fclose(fp);
}
EGLClientBuffer GetClientBuffer(EGLenum target, uintptr_t key)
{
switch (target)
{
case EGL_GL_TEXTURE_2D:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case EGL_GL_TEXTURE_3D:
{
uintptr_t id = static_cast<uintptr_t>(gTextureMap[key]);
return reinterpret_cast<EGLClientBuffer>(id);
}
case EGL_GL_RENDERBUFFER:
{
uintptr_t id = static_cast<uintptr_t>(gRenderbufferMap[key]);
return reinterpret_cast<EGLClientBuffer>(id);
}
default:
{
const auto &iData = gClientBufferMap.find(key);
return iData != gClientBufferMap.end() ? iData->second : nullptr;
}
}
}
ValidateSerializedStateCallback gValidateSerializedStateCallback;
std::unordered_map<GLuint, std::vector<GLint>> gInternalUniformLocationsMap;
constexpr size_t kMaxClientArrays = 16;
} // namespace
GLint **gUniformLocations;
GLuint gCurrentProgram = 0;
// TODO(jmadill): Hide from the traces. http://anglebug.com/7753
BlockIndexesMap gUniformBlockIndexes;
void UpdateUniformLocation(GLuint program, const char *name, GLint location, GLint count)
{
std::vector<GLint> &programLocations = gInternalUniformLocationsMap[program];
if (static_cast<GLint>(programLocations.size()) < location + count)
{
programLocations.resize(location + count, 0);
}
GLuint mappedProgramID = gShaderProgramMap[program];
for (GLint arrayIndex = 0; arrayIndex < count; ++arrayIndex)
{
programLocations[location + arrayIndex] =
glGetUniformLocation(mappedProgramID, name) + arrayIndex;
}
gUniformLocations[program] = programLocations.data();
}
void DeleteUniformLocations(GLuint program)
{
// No-op. We leave uniform locations around so deleted current programs can still use them.
}
void UpdateUniformBlockIndex(GLuint program, const char *name, GLuint index)
{
gUniformBlockIndexes[program][index] = glGetUniformBlockIndex(program, name);
}
void UniformBlockBinding(GLuint program, GLuint uniformblockIndex, GLuint binding)
{
glUniformBlockBinding(gShaderProgramMap[program],
gUniformBlockIndexes[gShaderProgramMap[program]][uniformblockIndex],
binding);
}
void UpdateCurrentProgram(GLuint program)
{
gCurrentProgram = program;
}
uint8_t *gBinaryData;
uint8_t *gReadBuffer;
uint8_t *gClientArrays[kMaxClientArrays];
GLuint *gResourceIDBuffer;
SyncResourceMap gSyncMap;
ContextMap gContextMap;
GLuint gShareContextId;
GLuint *gBufferMap;
GLuint *gFenceNVMap;
GLuint *gFramebufferMap;
GLuint *gMemoryObjectMap;
GLuint *gProgramPipelineMap;
GLuint *gQueryMap;
GLuint *gRenderbufferMap;
GLuint *gSamplerMap;
GLuint *gSemaphoreMap;
GLuint *gShaderProgramMap;
GLuint *gTextureMap;
GLuint *gTransformFeedbackMap;
GLuint *gVertexArrayMap;
// TODO(jmadill): Consolidate. http://anglebug.com/7753
ClientBufferMap gClientBufferMap;
EGLImageMap gEGLImageMap;
SurfaceMap gSurfaceMap;
GLeglImageOES *gEGLImageMap2;
EGLSurface *gSurfaceMap2;
EGLContext *gContextMap2;
GLsync *gSyncMap2;
EGLSync *gEGLSyncMap;
std::string gBinaryDataDir = ".";
void SetBinaryDataDecompressCallback(DecompressCallback decompressCallback,
DeleteCallback deleteCallback)
{
gDecompressCallback = decompressCallback;
gDeleteCallback = deleteCallback;
}
void SetBinaryDataDir(const char *dataDir)
{
gBinaryDataDir = dataDir;
}
template <typename T>
T *AllocateZeroedValues(size_t count)
{
T *mem = new T[count + 1];
memset(mem, 0, sizeof(T) * (count + 1));
return mem;
}
GLuint *AllocateZeroedUints(size_t count)
{
return AllocateZeroedValues<GLuint>(count);
}
void InitializeReplay4(const char *binaryDataFileName,
size_t maxClientArraySize,
size_t readBufferSize,
size_t resourceIDBufferSize,
GLuint contextId,
uint32_t maxBuffer,
uint32_t maxContext,
uint32_t maxFenceNV,
uint32_t maxFramebuffer,
uint32_t maxImage,
uint32_t maxMemoryObject,
uint32_t maxProgramPipeline,
uint32_t maxQuery,
uint32_t maxRenderbuffer,
uint32_t maxSampler,
uint32_t maxSemaphore,
uint32_t maxShaderProgram,
uint32_t maxSurface,
uint32_t maxSync,
uint32_t maxTexture,
uint32_t maxTransformFeedback,
uint32_t maxVertexArray,
GLuint maxEGLSyncID)
{
InitializeReplay3(binaryDataFileName, maxClientArraySize, readBufferSize, resourceIDBufferSize,
contextId, maxBuffer, maxContext, maxFenceNV, maxFramebuffer, maxImage,
maxMemoryObject, maxProgramPipeline, maxQuery, maxRenderbuffer, maxSampler,
maxSemaphore, maxShaderProgram, maxSurface, maxSync, maxTexture,
maxTransformFeedback, maxVertexArray);
gEGLSyncMap = AllocateZeroedValues<EGLSync>(maxEGLSyncID);
}
void InitializeReplay3(const char *binaryDataFileName,
size_t maxClientArraySize,
size_t readBufferSize,
size_t resourceIDBufferSize,
GLuint contextId,
uint32_t maxBuffer,
uint32_t maxContext,
uint32_t maxFenceNV,
uint32_t maxFramebuffer,
uint32_t maxImage,
uint32_t maxMemoryObject,
uint32_t maxProgramPipeline,
uint32_t maxQuery,
uint32_t maxRenderbuffer,
uint32_t maxSampler,
uint32_t maxSemaphore,
uint32_t maxShaderProgram,
uint32_t maxSurface,
uint32_t maxSync,
uint32_t maxTexture,
uint32_t maxTransformFeedback,
uint32_t maxVertexArray)
{
InitializeReplay2(binaryDataFileName, maxClientArraySize, readBufferSize, contextId, maxBuffer,
maxContext, maxFenceNV, maxFramebuffer, maxImage, maxMemoryObject,
maxProgramPipeline, maxQuery, maxRenderbuffer, maxSampler, maxSemaphore,
maxShaderProgram, maxSurface, maxTexture, maxTransformFeedback,
maxVertexArray);
gSyncMap2 = AllocateZeroedValues<GLsync>(maxSync);
gResourceIDBuffer = AllocateZeroedUints(resourceIDBufferSize);
}
void InitializeReplay2(const char *binaryDataFileName,
size_t maxClientArraySize,
size_t readBufferSize,
GLuint contextId,
uint32_t maxBuffer,
uint32_t maxContext,
uint32_t maxFenceNV,
uint32_t maxFramebuffer,
uint32_t maxImage,
uint32_t maxMemoryObject,
uint32_t maxProgramPipeline,
uint32_t maxQuery,
uint32_t maxRenderbuffer,
uint32_t maxSampler,
uint32_t maxSemaphore,
uint32_t maxShaderProgram,
uint32_t maxSurface,
uint32_t maxTexture,
uint32_t maxTransformFeedback,
uint32_t maxVertexArray)
{
InitializeReplay(binaryDataFileName, maxClientArraySize, readBufferSize, maxBuffer, maxFenceNV,
maxFramebuffer, maxMemoryObject, maxProgramPipeline, maxQuery, maxRenderbuffer,
maxSampler, maxSemaphore, maxShaderProgram, maxTexture, maxTransformFeedback,
maxVertexArray);
gContextMap2 = AllocateZeroedValues<EGLContext>(maxContext);
gEGLImageMap2 = AllocateZeroedValues<EGLImage>(maxImage);
gSurfaceMap2 = AllocateZeroedValues<EGLSurface>(maxSurface);
gContextMap2[0] = EGL_NO_CONTEXT;
gShareContextId = contextId;
gContextMap2[contextId] = eglGetCurrentContext();
}
void InitializeReplay(const char *binaryDataFileName,
size_t maxClientArraySize,
size_t readBufferSize,
uint32_t maxBuffer,
uint32_t maxFenceNV,
uint32_t maxFramebuffer,
uint32_t maxMemoryObject,
uint32_t maxProgramPipeline,
uint32_t maxQuery,
uint32_t maxRenderbuffer,
uint32_t maxSampler,
uint32_t maxSemaphore,
uint32_t maxShaderProgram,
uint32_t maxTexture,
uint32_t maxTransformFeedback,
uint32_t maxVertexArray)
{
LoadBinaryData(binaryDataFileName);
for (uint8_t *&clientArray : gClientArrays)
{
clientArray = new uint8_t[maxClientArraySize];
}
gReadBuffer = new uint8_t[readBufferSize];
gBufferMap = AllocateZeroedUints(maxBuffer);
gFenceNVMap = AllocateZeroedUints(maxFenceNV);
gFramebufferMap = AllocateZeroedUints(maxFramebuffer);
gMemoryObjectMap = AllocateZeroedUints(maxMemoryObject);
gProgramPipelineMap = AllocateZeroedUints(maxProgramPipeline);
gQueryMap = AllocateZeroedUints(maxQuery);
gRenderbufferMap = AllocateZeroedUints(maxRenderbuffer);
gSamplerMap = AllocateZeroedUints(maxSampler);
gSemaphoreMap = AllocateZeroedUints(maxSemaphore);
gShaderProgramMap = AllocateZeroedUints(maxShaderProgram);
gTextureMap = AllocateZeroedUints(maxTexture);
gTransformFeedbackMap = AllocateZeroedUints(maxTransformFeedback);
gVertexArrayMap = AllocateZeroedUints(maxVertexArray);
gUniformLocations = new GLint *[maxShaderProgram + 1];
memset(gUniformLocations, 0, sizeof(GLint *) * (maxShaderProgram + 1));
gContextMap[0] = EGL_NO_CONTEXT;
}
void FinishReplay()
{
for (uint8_t *&clientArray : gClientArrays)
{
delete[] clientArray;
}
delete[] gReadBuffer;
delete[] gResourceIDBuffer;
delete[] gBufferMap;
delete[] gContextMap2;
delete[] gEGLImageMap2;
delete[] gRenderbufferMap;
delete[] gTextureMap;
delete[] gFramebufferMap;
delete[] gShaderProgramMap;
delete[] gFenceNVMap;
delete[] gMemoryObjectMap;
delete[] gProgramPipelineMap;
delete[] gQueryMap;
delete[] gSamplerMap;
delete[] gSemaphoreMap;
delete[] gSurfaceMap2;
delete[] gSyncMap2;
delete[] gTransformFeedbackMap;
delete[] gVertexArrayMap;
DeleteBinaryData();
}
void SetValidateSerializedStateCallback(ValidateSerializedStateCallback callback)
{
gValidateSerializedStateCallback = callback;
}
std::vector<std::string> gTraceFiles;
std::string gTraceGzPath;
void SetTraceInfo(const std::vector<std::string> &traceFiles)
{
gTraceFiles = traceFiles;
}
void SetTraceGzPath(const std::string &traceGzPath)
{
gTraceGzPath = traceGzPath;
}
void UpdateClientArrayPointer(int arrayIndex, const void *data, uint64_t size)
{
memcpy(gClientArrays[arrayIndex], data, static_cast<size_t>(size));
}
BufferHandleMap gMappedBufferData;
void UpdateClientBufferData(GLuint bufferID, const void *source, GLsizei size)
{
memcpy(gMappedBufferData[gBufferMap[bufferID]], source, size);
}
void UpdateClientBufferDataWithOffset(GLuint bufferID,
const void *source,
GLsizei size,
GLsizei offset)
{
uintptr_t dest = reinterpret_cast<uintptr_t>(gMappedBufferData[gBufferMap[bufferID]]) + offset;
memcpy(reinterpret_cast<void *>(dest), source, size);
}
void UpdateResourceIDBuffer(int resourceIndex, GLuint id)
{
gResourceIDBuffer[resourceIndex] = id;
}
void UpdateBufferID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gBufferMap, id, readBufferOffset);
}
void UpdateFenceNVID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gFenceNVMap, id, readBufferOffset);
}
void UpdateFramebufferID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gFramebufferMap, id, readBufferOffset);
}
void UpdateMemoryObjectID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gMemoryObjectMap, id, readBufferOffset);
}
void UpdateProgramPipelineID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gProgramPipelineMap, id, readBufferOffset);
}
void UpdateQueryID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gQueryMap, id, readBufferOffset);
}
void UpdateRenderbufferID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gRenderbufferMap, id, readBufferOffset);
}
void UpdateSamplerID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gSamplerMap, id, readBufferOffset);
}
void UpdateSemaphoreID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gSemaphoreMap, id, readBufferOffset);
}
void UpdateShaderProgramID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gShaderProgramMap, id, readBufferOffset);
}
void UpdateTextureID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gTextureMap, id, readBufferOffset);
}
void UpdateTransformFeedbackID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gTransformFeedbackMap, id, readBufferOffset);
}
void UpdateVertexArrayID(GLuint id, GLsizei readBufferOffset)
{
UpdateResourceMap(gVertexArrayMap, id, readBufferOffset);
}
void SetResourceID(GLuint *map, GLuint id)
{
map[id] = id;
}
void SetFramebufferID(GLuint id)
{
SetResourceID(gFramebufferMap, id);
}
void SetBufferID(GLuint id)
{
SetResourceID(gBufferMap, id);
}
void SetRenderbufferID(GLuint id)
{
SetResourceID(gRenderbufferMap, id);
}
void SetTextureID(GLuint id)
{
SetResourceID(gTextureMap, id);
}
void ValidateSerializedState(const char *serializedState, const char *fileName, uint32_t line)
{
if (gValidateSerializedStateCallback)
{
gValidateSerializedStateCallback(serializedState, fileName, line);
}
}
void MapBufferRange(GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access,
GLuint buffer)
{
gMappedBufferData[gBufferMap[buffer]] = glMapBufferRange(target, offset, length, access);
}
void MapBufferRangeEXT(GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access,
GLuint buffer)
{
gMappedBufferData[gBufferMap[buffer]] = glMapBufferRangeEXT(target, offset, length, access);
}
void MapBufferOES(GLenum target, GLbitfield access, GLuint buffer)
{
gMappedBufferData[gBufferMap[buffer]] = glMapBufferOES(target, access);
}
void CreateShader(GLenum shaderType, GLuint shaderProgram)
{
gShaderProgramMap[shaderProgram] = glCreateShader(shaderType);
}
void CreateProgram(GLuint shaderProgram)
{
gShaderProgramMap[shaderProgram] = glCreateProgram();
}
void CreateShaderProgramv(GLenum type,
GLsizei count,
const GLchar *const *strings,
GLuint shaderProgram)
{
gShaderProgramMap[shaderProgram] = glCreateShaderProgramv(type, count, strings);
}
void FenceSync(GLenum condition, GLbitfield flags, uintptr_t fenceSync)
{
gSyncMap[fenceSync] = glFenceSync(condition, flags);
}
void FenceSync2(GLenum condition, GLbitfield flags, uintptr_t fenceSync)
{
gSyncMap2[fenceSync] = glFenceSync(condition, flags);
}
void CreateEGLImage(EGLDisplay dpy,
EGLContext ctx,
EGLenum target,
uintptr_t buffer,
const EGLAttrib *attrib_list,
GLuint imageID)
{
EGLClientBuffer clientBuffer = GetClientBuffer(target, buffer);
gEGLImageMap2[imageID] = eglCreateImage(dpy, ctx, target, clientBuffer, attrib_list);
}
void CreateEGLImageKHR(EGLDisplay dpy,
EGLContext ctx,
EGLenum target,
uintptr_t buffer,
const EGLint *attrib_list,
GLuint imageID)
{
EGLClientBuffer clientBuffer = GetClientBuffer(target, buffer);
gEGLImageMap2[imageID] = eglCreateImageKHR(dpy, ctx, target, clientBuffer, attrib_list);
}
void CreateEGLSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list, GLuint syncID)
{
gEGLSyncMap[syncID] = eglCreateSyncKHR(dpy, type, attrib_list);
}
void CreateEGLSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list, GLuint syncID)
{
gEGLSyncMap[syncID] = eglCreateSync(dpy, type, attrib_list);
}
void CreatePbufferSurface(EGLDisplay dpy,
EGLConfig config,
const EGLint *attrib_list,
GLuint surfaceID)
{
gSurfaceMap2[surfaceID] = eglCreatePbufferSurface(dpy, config, attrib_list);
}
void CreateNativeClientBufferANDROID(const EGLint *attrib_list, uintptr_t clientBuffer)
{
gClientBufferMap[clientBuffer] = eglCreateNativeClientBufferANDROID(attrib_list);
}
void CreateContext(GLuint contextID)
{
EGLContext shareContext = gContextMap2[gShareContextId];
EGLContext context = eglCreateContext(nullptr, nullptr, shareContext, nullptr);
gContextMap2[contextID] = context;
}
void SetCurrentContextID(GLuint id)
{
gContextMap2[id] = eglGetCurrentContext();
}
ANGLE_REPLAY_EXPORT PFNEGLCREATEIMAGEPROC r_eglCreateImage;
ANGLE_REPLAY_EXPORT PFNEGLCREATEIMAGEKHRPROC r_eglCreateImageKHR;
ANGLE_REPLAY_EXPORT PFNEGLDESTROYIMAGEPROC r_eglDestroyImage;
ANGLE_REPLAY_EXPORT PFNEGLDESTROYIMAGEKHRPROC r_eglDestroyImageKHR;