1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // trace_fixture.cpp:
7 // Common code for the ANGLE trace replays.
8 //
9
10 #include "trace_fixture.h"
11
12 #include "angle_trace_gl.h"
13
14 #include <string>
15
16 namespace
17 {
UpdateResourceMap(GLuint * resourceMap,GLuint id,GLsizei readBufferOffset)18 void UpdateResourceMap(GLuint *resourceMap, GLuint id, GLsizei readBufferOffset)
19 {
20 GLuint returnedID;
21 memcpy(&returnedID, &gReadBuffer[readBufferOffset], sizeof(GLuint));
22 resourceMap[id] = returnedID;
23 }
24
25 DecompressCallback gDecompressCallback;
26 std::string gBinaryDataDir = ".";
27
LoadBinaryData(const char * fileName)28 void LoadBinaryData(const char *fileName)
29 {
30 // TODO(b/179188489): Fix cross-module deallocation.
31 if (gBinaryData != nullptr)
32 {
33 delete[] gBinaryData;
34 }
35 char pathBuffer[1000] = {};
36
37 sprintf(pathBuffer, "%s/%s", gBinaryDataDir.c_str(), fileName);
38 FILE *fp = fopen(pathBuffer, "rb");
39 if (fp == 0)
40 {
41 fprintf(stderr, "Error loading binary data file: %s\n", fileName);
42 return;
43 }
44 fseek(fp, 0, SEEK_END);
45 long size = ftell(fp);
46 fseek(fp, 0, SEEK_SET);
47 if (gDecompressCallback)
48 {
49 if (!strstr(fileName, ".gz"))
50 {
51 fprintf(stderr, "Filename does not end in .gz");
52 exit(1);
53 }
54 std::vector<uint8_t> compressedData(size);
55 (void)fread(compressedData.data(), 1, size, fp);
56 gBinaryData = gDecompressCallback(compressedData);
57 }
58 else
59 {
60 if (!strstr(fileName, ".angledata"))
61 {
62 fprintf(stderr, "Filename does not end in .angledata");
63 exit(1);
64 }
65 gBinaryData = new uint8_t[size];
66 (void)fread(gBinaryData, 1, size, fp);
67 }
68 fclose(fp);
69 }
70
71 ValidateSerializedStateCallback gValidateSerializedStateCallback;
72 std::unordered_map<GLuint, std::vector<GLint>> gInternalUniformLocationsMap;
73 } // namespace
74
75 GLint **gUniformLocations;
76 BlockIndexesMap gUniformBlockIndexes;
77 GLuint gCurrentProgram = 0;
78
UpdateUniformLocation(GLuint program,const char * name,GLint location,GLint count)79 void UpdateUniformLocation(GLuint program, const char *name, GLint location, GLint count)
80 {
81 std::vector<GLint> &programLocations = gInternalUniformLocationsMap[program];
82 if (static_cast<GLint>(programLocations.size()) < location + count)
83 {
84 programLocations.resize(location + count, 0);
85 }
86 for (GLint arrayIndex = 0; arrayIndex < count; ++arrayIndex)
87 {
88 GLuint mappedProgramID = gShaderProgramMap[program];
89 programLocations[location + arrayIndex] =
90 glGetUniformLocation(mappedProgramID, name) + arrayIndex;
91 }
92 gUniformLocations[program] = programLocations.data();
93 }
94
DeleteUniformLocations(GLuint program)95 void DeleteUniformLocations(GLuint program)
96 {
97 // No-op. We leave uniform locations around so deleted current programs can still use them.
98 }
99
UpdateUniformBlockIndex(GLuint program,const char * name,GLuint index)100 void UpdateUniformBlockIndex(GLuint program, const char *name, GLuint index)
101 {
102 gUniformBlockIndexes[program][index] = glGetUniformBlockIndex(program, name);
103 }
UpdateCurrentProgram(GLuint program)104 void UpdateCurrentProgram(GLuint program)
105 {
106 gCurrentProgram = program;
107 }
108
109 uint8_t *gBinaryData;
110 uint8_t *gReadBuffer;
111 uint8_t *gClientArrays[kMaxClientArrays];
112 SyncResourceMap gSyncMap;
113 ContextMap gContextMap;
114
115 GLuint *gBufferMap;
116 GLuint *gFenceNVMap;
117 GLuint *gFramebufferMap;
118 GLuint *gMemoryObjectMap;
119 GLuint *gProgramPipelineMap;
120 GLuint *gQueryMap;
121 GLuint *gRenderbufferMap;
122 GLuint *gSamplerMap;
123 GLuint *gSemaphoreMap;
124 GLuint *gShaderProgramMap;
125 GLuint *gTextureMap;
126 GLuint *gTransformFeedbackMap;
127 GLuint *gVertexArrayMap;
128
SetBinaryDataDecompressCallback(DecompressCallback callback)129 void SetBinaryDataDecompressCallback(DecompressCallback callback)
130 {
131 gDecompressCallback = callback;
132 }
133
SetBinaryDataDir(const char * dataDir)134 void SetBinaryDataDir(const char *dataDir)
135 {
136 gBinaryDataDir = dataDir;
137 }
138
AllocateZeroedUints(size_t count)139 GLuint *AllocateZeroedUints(size_t count)
140 {
141 GLuint *mem = new GLuint[count + 1];
142 memset(mem, 0, sizeof(GLuint) * (count + 1));
143 return mem;
144 }
145
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)146 void InitializeReplay(const char *binaryDataFileName,
147 size_t maxClientArraySize,
148 size_t readBufferSize,
149 uint32_t maxBuffer,
150 uint32_t maxFenceNV,
151 uint32_t maxFramebuffer,
152 uint32_t maxMemoryObject,
153 uint32_t maxProgramPipeline,
154 uint32_t maxQuery,
155 uint32_t maxRenderbuffer,
156 uint32_t maxSampler,
157 uint32_t maxSemaphore,
158 uint32_t maxShaderProgram,
159 uint32_t maxTexture,
160 uint32_t maxTransformFeedback,
161 uint32_t maxVertexArray)
162 {
163 LoadBinaryData(binaryDataFileName);
164
165 for (uint8_t *&clientArray : gClientArrays)
166 {
167 clientArray = new uint8_t[maxClientArraySize];
168 }
169
170 gReadBuffer = new uint8_t[readBufferSize];
171
172 gBufferMap = AllocateZeroedUints(maxBuffer);
173 gFenceNVMap = AllocateZeroedUints(maxFenceNV);
174 gFramebufferMap = AllocateZeroedUints(maxFramebuffer);
175 gMemoryObjectMap = AllocateZeroedUints(maxMemoryObject);
176 gProgramPipelineMap = AllocateZeroedUints(maxProgramPipeline);
177 gQueryMap = AllocateZeroedUints(maxQuery);
178 gRenderbufferMap = AllocateZeroedUints(maxRenderbuffer);
179 gSamplerMap = AllocateZeroedUints(maxSampler);
180 gSemaphoreMap = AllocateZeroedUints(maxSemaphore);
181 gShaderProgramMap = AllocateZeroedUints(maxShaderProgram);
182 gTextureMap = AllocateZeroedUints(maxTexture);
183 gTransformFeedbackMap = AllocateZeroedUints(maxTransformFeedback);
184 gVertexArrayMap = AllocateZeroedUints(maxVertexArray);
185
186 gUniformLocations = new GLint *[maxShaderProgram + 1];
187 memset(gUniformLocations, 0, sizeof(GLint *) * (maxShaderProgram + 1));
188 }
189
FinishReplay()190 void FinishReplay()
191 {
192 for (uint8_t *&clientArray : gClientArrays)
193 {
194 delete[] clientArray;
195 }
196 delete[] gReadBuffer;
197
198 delete[] gBufferMap;
199 delete[] gRenderbufferMap;
200 delete[] gTextureMap;
201 delete[] gFramebufferMap;
202 delete[] gShaderProgramMap;
203 delete[] gFenceNVMap;
204 delete[] gMemoryObjectMap;
205 delete[] gProgramPipelineMap;
206 delete[] gQueryMap;
207 delete[] gSamplerMap;
208 delete[] gSemaphoreMap;
209 delete[] gTransformFeedbackMap;
210 delete[] gVertexArrayMap;
211 }
212
SetValidateSerializedStateCallback(ValidateSerializedStateCallback callback)213 void SetValidateSerializedStateCallback(ValidateSerializedStateCallback callback)
214 {
215 gValidateSerializedStateCallback = callback;
216 }
217
UpdateClientArrayPointer(int arrayIndex,const void * data,uint64_t size)218 void UpdateClientArrayPointer(int arrayIndex, const void *data, uint64_t size)
219 {
220 memcpy(gClientArrays[arrayIndex], data, static_cast<size_t>(size));
221 }
222 BufferHandleMap gMappedBufferData;
223
UpdateClientBufferData(GLuint bufferID,const void * source,GLsizei size)224 void UpdateClientBufferData(GLuint bufferID, const void *source, GLsizei size)
225 {
226 memcpy(gMappedBufferData[gBufferMap[bufferID]], source, size);
227 }
228
UpdateClientBufferDataWithOffset(GLuint bufferID,const void * source,GLsizei size,GLsizei offset)229 void UpdateClientBufferDataWithOffset(GLuint bufferID,
230 const void *source,
231 GLsizei size,
232 GLsizei offset)
233 {
234 uintptr_t dest = reinterpret_cast<uintptr_t>(gMappedBufferData[gBufferMap[bufferID]]) + offset;
235 memcpy(reinterpret_cast<void *>(dest), source, size);
236 }
237
UpdateBufferID(GLuint id,GLsizei readBufferOffset)238 void UpdateBufferID(GLuint id, GLsizei readBufferOffset)
239 {
240 UpdateResourceMap(gBufferMap, id, readBufferOffset);
241 }
242
UpdateFenceNVID(GLuint id,GLsizei readBufferOffset)243 void UpdateFenceNVID(GLuint id, GLsizei readBufferOffset)
244 {
245 UpdateResourceMap(gFenceNVMap, id, readBufferOffset);
246 }
247
UpdateFramebufferID(GLuint id,GLsizei readBufferOffset)248 void UpdateFramebufferID(GLuint id, GLsizei readBufferOffset)
249 {
250 UpdateResourceMap(gFramebufferMap, id, readBufferOffset);
251 }
252
UpdateMemoryObjectID(GLuint id,GLsizei readBufferOffset)253 void UpdateMemoryObjectID(GLuint id, GLsizei readBufferOffset)
254 {
255 UpdateResourceMap(gMemoryObjectMap, id, readBufferOffset);
256 }
257
UpdateProgramPipelineID(GLuint id,GLsizei readBufferOffset)258 void UpdateProgramPipelineID(GLuint id, GLsizei readBufferOffset)
259 {
260 UpdateResourceMap(gProgramPipelineMap, id, readBufferOffset);
261 }
262
UpdateQueryID(GLuint id,GLsizei readBufferOffset)263 void UpdateQueryID(GLuint id, GLsizei readBufferOffset)
264 {
265 UpdateResourceMap(gQueryMap, id, readBufferOffset);
266 }
267
UpdateRenderbufferID(GLuint id,GLsizei readBufferOffset)268 void UpdateRenderbufferID(GLuint id, GLsizei readBufferOffset)
269 {
270 UpdateResourceMap(gRenderbufferMap, id, readBufferOffset);
271 }
272
UpdateSamplerID(GLuint id,GLsizei readBufferOffset)273 void UpdateSamplerID(GLuint id, GLsizei readBufferOffset)
274 {
275 UpdateResourceMap(gSamplerMap, id, readBufferOffset);
276 }
277
UpdateSemaphoreID(GLuint id,GLsizei readBufferOffset)278 void UpdateSemaphoreID(GLuint id, GLsizei readBufferOffset)
279 {
280 UpdateResourceMap(gSemaphoreMap, id, readBufferOffset);
281 }
282
UpdateShaderProgramID(GLuint id,GLsizei readBufferOffset)283 void UpdateShaderProgramID(GLuint id, GLsizei readBufferOffset)
284 {
285 UpdateResourceMap(gShaderProgramMap, id, readBufferOffset);
286 }
287
UpdateTextureID(GLuint id,GLsizei readBufferOffset)288 void UpdateTextureID(GLuint id, GLsizei readBufferOffset)
289 {
290 UpdateResourceMap(gTextureMap, id, readBufferOffset);
291 }
292
UpdateTransformFeedbackID(GLuint id,GLsizei readBufferOffset)293 void UpdateTransformFeedbackID(GLuint id, GLsizei readBufferOffset)
294 {
295 UpdateResourceMap(gTransformFeedbackMap, id, readBufferOffset);
296 }
297
UpdateVertexArrayID(GLuint id,GLsizei readBufferOffset)298 void UpdateVertexArrayID(GLuint id, GLsizei readBufferOffset)
299 {
300 UpdateResourceMap(gVertexArrayMap, id, readBufferOffset);
301 }
302
SetResourceID(GLuint * map,GLuint id)303 void SetResourceID(GLuint *map, GLuint id)
304 {
305 if (map[id] != 0)
306 {
307 fprintf(stderr, "%s: resource ID %d is already reserved\n", __func__, id);
308 exit(1);
309 }
310 map[id] = id;
311 }
312
SetFramebufferID(GLuint id)313 void SetFramebufferID(GLuint id)
314 {
315 SetResourceID(gFramebufferMap, id);
316 }
317
SetBufferID(GLuint id)318 void SetBufferID(GLuint id)
319 {
320 SetResourceID(gBufferMap, id);
321 }
322
SetRenderbufferID(GLuint id)323 void SetRenderbufferID(GLuint id)
324 {
325 SetResourceID(gRenderbufferMap, id);
326 }
327
SetTextureID(GLuint id)328 void SetTextureID(GLuint id)
329 {
330 SetResourceID(gTextureMap, id);
331 }
332
ValidateSerializedState(const char * serializedState,const char * fileName,uint32_t line)333 void ValidateSerializedState(const char *serializedState, const char *fileName, uint32_t line)
334 {
335 if (gValidateSerializedStateCallback)
336 {
337 gValidateSerializedStateCallback(serializedState, fileName, line);
338 }
339 }
340