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(ResourceMap * resourceMap,GLuint id,GLsizei readBufferOffset)18 void UpdateResourceMap(ResourceMap *resourceMap, GLuint id, GLsizei readBufferOffset)
19 {
20 GLuint returnedID;
21 memcpy(&returnedID, &gReadBuffer[readBufferOffset], sizeof(GLuint));
22 (*resourceMap)[id] = returnedID;
23 }
24
UpdateResourceMap2(GLuint * resourceMap,GLuint id,GLsizei readBufferOffset)25 void UpdateResourceMap2(GLuint *resourceMap, GLuint id, GLsizei readBufferOffset)
26 {
27 GLuint returnedID;
28 memcpy(&returnedID, &gReadBuffer[readBufferOffset], sizeof(GLuint));
29 resourceMap[id] = returnedID;
30 }
31
32 DecompressCallback gDecompressCallback;
33 std::string gBinaryDataDir = ".";
34
LoadBinaryData(const char * fileName)35 void LoadBinaryData(const char *fileName)
36 {
37 // TODO(b/179188489): Fix cross-module deallocation.
38 if (gBinaryData != nullptr)
39 {
40 delete[] gBinaryData;
41 }
42 char pathBuffer[1000] = {};
43
44 sprintf(pathBuffer, "%s/%s", gBinaryDataDir.c_str(), fileName);
45 FILE *fp = fopen(pathBuffer, "rb");
46 if (fp == 0)
47 {
48 fprintf(stderr, "Error loading binary data file: %s\n", fileName);
49 return;
50 }
51 fseek(fp, 0, SEEK_END);
52 long size = ftell(fp);
53 fseek(fp, 0, SEEK_SET);
54 if (gDecompressCallback)
55 {
56 if (!strstr(fileName, ".gz"))
57 {
58 fprintf(stderr, "Filename does not end in .gz");
59 exit(1);
60 }
61 std::vector<uint8_t> compressedData(size);
62 (void)fread(compressedData.data(), 1, size, fp);
63 gBinaryData = gDecompressCallback(compressedData);
64 }
65 else
66 {
67 if (!strstr(fileName, ".angledata"))
68 {
69 fprintf(stderr, "Filename does not end in .angledata");
70 exit(1);
71 }
72 gBinaryData = new uint8_t[size];
73 (void)fread(gBinaryData, 1, size, fp);
74 }
75 fclose(fp);
76 }
77
78 ValidateSerializedStateCallback gValidateSerializedStateCallback;
79 std::unordered_map<GLuint, std::vector<GLint>> gInternalUniformLocationsMap;
80 } // namespace
81
82 LocationsMap gUniformLocations;
83 GLint **gUniformLocations2;
84 BlockIndexesMap gUniformBlockIndexes;
85 GLuint gCurrentProgram = 0;
86
87 // TODO (http://anglebug.com/6234): Remove three parameter UpdateUniformLocation on next retrace
UpdateUniformLocation(GLuint program,const char * name,GLint location)88 void UpdateUniformLocation(GLuint program, const char *name, GLint location)
89 {
90 gUniformLocations[program][location] = glGetUniformLocation(program, name);
91 }
92
UpdateUniformLocation(GLuint program,const char * name,GLint location,GLint count)93 void UpdateUniformLocation(GLuint program, const char *name, GLint location, GLint count)
94 {
95 for (GLint i = 0; i < count; i++)
96 {
97 gUniformLocations[program][location + i] = glGetUniformLocation(program, name) + i;
98 }
99 }
100
UpdateUniformLocation2(GLuint program,const char * name,GLint location,GLint count)101 void UpdateUniformLocation2(GLuint program, const char *name, GLint location, GLint count)
102 {
103 std::vector<GLint> &programLocations = gInternalUniformLocationsMap[program];
104 if (static_cast<GLint>(programLocations.size()) < location + count)
105 {
106 programLocations.resize(location + count, 0);
107 }
108 for (GLint arrayIndex = 0; arrayIndex < count; ++arrayIndex)
109 {
110 programLocations[location + arrayIndex] = glGetUniformLocation(program, name) + arrayIndex;
111 }
112 gUniformLocations2[program] = programLocations.data();
113 }
114
DeleteUniformLocations(GLuint program)115 void DeleteUniformLocations(GLuint program)
116 {
117 gUniformLocations.erase(program);
118 }
119
DeleteUniformLocations2(GLuint program)120 void DeleteUniformLocations2(GLuint program)
121 {
122 // No-op. We leave uniform locations around so deleted current programs can still use them.
123 }
124
UpdateUniformBlockIndex(GLuint program,const char * name,GLuint index)125 void UpdateUniformBlockIndex(GLuint program, const char *name, GLuint index)
126 {
127 gUniformBlockIndexes[program][index] = glGetUniformBlockIndex(program, name);
128 }
UpdateCurrentProgram(GLuint program)129 void UpdateCurrentProgram(GLuint program)
130 {
131 gCurrentProgram = program;
132 }
133
134 uint8_t *gBinaryData;
135 uint8_t *gReadBuffer;
136 uint8_t *gClientArrays[kMaxClientArrays];
137 ResourceMap gBufferMap;
138 ResourceMap gFenceNVMap;
139 ResourceMap gFramebufferMap;
140 ResourceMap gMemoryObjectMap;
141 ResourceMap gProgramPipelineMap;
142 ResourceMap gQueryMap;
143 ResourceMap gRenderbufferMap;
144 ResourceMap gSamplerMap;
145 ResourceMap gSemaphoreMap;
146 ResourceMap gShaderProgramMap;
147 ResourceMap gTextureMap;
148 ResourceMap gTransformFeedbackMap;
149 ResourceMap gVertexArrayMap;
150 SyncResourceMap gSyncMap;
151 ContextMap gContextMap;
152
153 GLuint *gBufferMap2;
154 GLuint *gFenceNVMap2;
155 GLuint *gFramebufferMap2;
156 GLuint *gMemoryObjectMap2;
157 GLuint *gProgramPipelineMap2;
158 GLuint *gQueryMap2;
159 GLuint *gRenderbufferMap2;
160 GLuint *gSamplerMap2;
161 GLuint *gSemaphoreMap2;
162 GLuint *gShaderProgramMap2;
163 GLuint *gTextureMap2;
164 GLuint *gTransformFeedbackMap2;
165 GLuint *gVertexArrayMap2;
166
SetBinaryDataDecompressCallback(DecompressCallback callback)167 void SetBinaryDataDecompressCallback(DecompressCallback callback)
168 {
169 gDecompressCallback = callback;
170 }
171
SetBinaryDataDir(const char * dataDir)172 void SetBinaryDataDir(const char *dataDir)
173 {
174 gBinaryDataDir = dataDir;
175 }
176
InitializeReplay(const char * binaryDataFileName,size_t maxClientArraySize,size_t readBufferSize)177 void InitializeReplay(const char *binaryDataFileName,
178 size_t maxClientArraySize,
179 size_t readBufferSize)
180 {
181 LoadBinaryData(binaryDataFileName);
182
183 for (uint8_t *&clientArray : gClientArrays)
184 {
185 clientArray = new uint8_t[maxClientArraySize];
186 }
187
188 gReadBuffer = new uint8_t[readBufferSize];
189 }
190
AllocateZeroedUints(size_t count)191 GLuint *AllocateZeroedUints(size_t count)
192 {
193 GLuint *mem = new GLuint[count + 1];
194 memset(mem, 0, sizeof(GLuint) * (count + 1));
195 return mem;
196 }
197
InitializeReplay2(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)198 void InitializeReplay2(const char *binaryDataFileName,
199 size_t maxClientArraySize,
200 size_t readBufferSize,
201 uint32_t maxBuffer,
202 uint32_t maxFenceNV,
203 uint32_t maxFramebuffer,
204 uint32_t maxMemoryObject,
205 uint32_t maxProgramPipeline,
206 uint32_t maxQuery,
207 uint32_t maxRenderbuffer,
208 uint32_t maxSampler,
209 uint32_t maxSemaphore,
210 uint32_t maxShaderProgram,
211 uint32_t maxTexture,
212 uint32_t maxTransformFeedback,
213 uint32_t maxVertexArray)
214 {
215 InitializeReplay(binaryDataFileName, maxClientArraySize, readBufferSize);
216
217 gBufferMap2 = AllocateZeroedUints(maxBuffer);
218 gFenceNVMap2 = AllocateZeroedUints(maxFenceNV);
219 gFramebufferMap2 = AllocateZeroedUints(maxFramebuffer);
220 gMemoryObjectMap2 = AllocateZeroedUints(maxMemoryObject);
221 gProgramPipelineMap2 = AllocateZeroedUints(maxProgramPipeline);
222 gQueryMap2 = AllocateZeroedUints(maxQuery);
223 gRenderbufferMap2 = AllocateZeroedUints(maxRenderbuffer);
224 gSamplerMap2 = AllocateZeroedUints(maxSampler);
225 gSemaphoreMap2 = AllocateZeroedUints(maxSemaphore);
226 gShaderProgramMap2 = AllocateZeroedUints(maxShaderProgram);
227 gTextureMap2 = AllocateZeroedUints(maxTexture);
228 gTransformFeedbackMap2 = AllocateZeroedUints(maxTransformFeedback);
229 gVertexArrayMap2 = AllocateZeroedUints(maxVertexArray);
230
231 gUniformLocations2 = new GLint *[maxShaderProgram + 1];
232 memset(gUniformLocations2, 0, sizeof(GLint *) * (maxShaderProgram + 1));
233 }
234
FinishReplay()235 void FinishReplay()
236 {
237 for (uint8_t *&clientArray : gClientArrays)
238 {
239 delete[] clientArray;
240 }
241 delete[] gReadBuffer;
242
243 delete[] gBufferMap2;
244 delete[] gRenderbufferMap2;
245 delete[] gTextureMap2;
246 delete[] gFramebufferMap2;
247 delete[] gShaderProgramMap2;
248 delete[] gFenceNVMap2;
249 delete[] gMemoryObjectMap2;
250 delete[] gProgramPipelineMap2;
251 delete[] gQueryMap2;
252 delete[] gSamplerMap2;
253 delete[] gSemaphoreMap2;
254 delete[] gTransformFeedbackMap2;
255 delete[] gVertexArrayMap2;
256 }
257
SetValidateSerializedStateCallback(ValidateSerializedStateCallback callback)258 void SetValidateSerializedStateCallback(ValidateSerializedStateCallback callback)
259 {
260 gValidateSerializedStateCallback = callback;
261 }
262
UpdateClientArrayPointer(int arrayIndex,const void * data,uint64_t size)263 void UpdateClientArrayPointer(int arrayIndex, const void *data, uint64_t size)
264 {
265 memcpy(gClientArrays[arrayIndex], data, static_cast<size_t>(size));
266 }
267 BufferHandleMap gMappedBufferData;
268
UpdateClientBufferData(GLuint bufferID,const void * source,GLsizei size)269 void UpdateClientBufferData(GLuint bufferID, const void *source, GLsizei size)
270 {
271 memcpy(gMappedBufferData[gBufferMap[bufferID]], source, size);
272 }
273
UpdateClientBufferData2(GLuint bufferID,const void * source,GLsizei size)274 void UpdateClientBufferData2(GLuint bufferID, const void *source, GLsizei size)
275 {
276 memcpy(gMappedBufferData[gBufferMap2[bufferID]], source, size);
277 }
278
UpdateClientBufferData2WithOffset(GLuint bufferID,const void * source,GLsizei size,GLsizei offset)279 void UpdateClientBufferData2WithOffset(GLuint bufferID,
280 const void *source,
281 GLsizei size,
282 GLsizei offset)
283 {
284 uintptr_t dest = reinterpret_cast<uintptr_t>(gMappedBufferData[gBufferMap2[bufferID]]) + offset;
285 memcpy(reinterpret_cast<void *>(dest), source, size);
286 }
287
UpdateBufferID(GLuint id,GLsizei readBufferOffset)288 void UpdateBufferID(GLuint id, GLsizei readBufferOffset)
289 {
290 UpdateResourceMap(&gBufferMap, id, readBufferOffset);
291 }
292
UpdateFenceNVID(GLuint id,GLsizei readBufferOffset)293 void UpdateFenceNVID(GLuint id, GLsizei readBufferOffset)
294 {
295 UpdateResourceMap(&gFenceNVMap, id, readBufferOffset);
296 }
297
UpdateFramebufferID(GLuint id,GLsizei readBufferOffset)298 void UpdateFramebufferID(GLuint id, GLsizei readBufferOffset)
299 {
300 UpdateResourceMap(&gFramebufferMap, id, readBufferOffset);
301 }
302
UpdateMemoryObjectID(GLuint id,GLsizei readBufferOffset)303 void UpdateMemoryObjectID(GLuint id, GLsizei readBufferOffset)
304 {
305 UpdateResourceMap(&gMemoryObjectMap, id, readBufferOffset);
306 }
307
UpdateProgramPipelineID(GLuint id,GLsizei readBufferOffset)308 void UpdateProgramPipelineID(GLuint id, GLsizei readBufferOffset)
309 {
310 UpdateResourceMap(&gProgramPipelineMap, id, readBufferOffset);
311 }
312
UpdateQueryID(GLuint id,GLsizei readBufferOffset)313 void UpdateQueryID(GLuint id, GLsizei readBufferOffset)
314 {
315 UpdateResourceMap(&gQueryMap, id, readBufferOffset);
316 }
317
UpdateRenderbufferID(GLuint id,GLsizei readBufferOffset)318 void UpdateRenderbufferID(GLuint id, GLsizei readBufferOffset)
319 {
320 UpdateResourceMap(&gRenderbufferMap, id, readBufferOffset);
321 }
322
UpdateSamplerID(GLuint id,GLsizei readBufferOffset)323 void UpdateSamplerID(GLuint id, GLsizei readBufferOffset)
324 {
325 UpdateResourceMap(&gSamplerMap, id, readBufferOffset);
326 }
327
UpdateSemaphoreID(GLuint id,GLsizei readBufferOffset)328 void UpdateSemaphoreID(GLuint id, GLsizei readBufferOffset)
329 {
330 UpdateResourceMap(&gSemaphoreMap, id, readBufferOffset);
331 }
332
UpdateShaderProgramID(GLuint id,GLsizei readBufferOffset)333 void UpdateShaderProgramID(GLuint id, GLsizei readBufferOffset)
334 {
335 UpdateResourceMap(&gShaderProgramMap, id, readBufferOffset);
336 }
337
UpdateTextureID(GLuint id,GLsizei readBufferOffset)338 void UpdateTextureID(GLuint id, GLsizei readBufferOffset)
339 {
340 UpdateResourceMap(&gTextureMap, id, readBufferOffset);
341 }
342
UpdateTransformFeedbackID(GLuint id,GLsizei readBufferOffset)343 void UpdateTransformFeedbackID(GLuint id, GLsizei readBufferOffset)
344 {
345 UpdateResourceMap(&gTransformFeedbackMap, id, readBufferOffset);
346 }
347
UpdateVertexArrayID(GLuint id,GLsizei readBufferOffset)348 void UpdateVertexArrayID(GLuint id, GLsizei readBufferOffset)
349 {
350 UpdateResourceMap(&gVertexArrayMap, id, readBufferOffset);
351 }
352
UpdateBufferID2(GLuint id,GLsizei readBufferOffset)353 void UpdateBufferID2(GLuint id, GLsizei readBufferOffset)
354 {
355 UpdateResourceMap2(gBufferMap2, id, readBufferOffset);
356 }
357
UpdateFenceNVID2(GLuint id,GLsizei readBufferOffset)358 void UpdateFenceNVID2(GLuint id, GLsizei readBufferOffset)
359 {
360 UpdateResourceMap2(gFenceNVMap2, id, readBufferOffset);
361 }
362
UpdateFramebufferID2(GLuint id,GLsizei readBufferOffset)363 void UpdateFramebufferID2(GLuint id, GLsizei readBufferOffset)
364 {
365 UpdateResourceMap2(gFramebufferMap2, id, readBufferOffset);
366 }
367
UpdateMemoryObjectID2(GLuint id,GLsizei readBufferOffset)368 void UpdateMemoryObjectID2(GLuint id, GLsizei readBufferOffset)
369 {
370 UpdateResourceMap2(gMemoryObjectMap2, id, readBufferOffset);
371 }
372
UpdateProgramPipelineID2(GLuint id,GLsizei readBufferOffset)373 void UpdateProgramPipelineID2(GLuint id, GLsizei readBufferOffset)
374 {
375 UpdateResourceMap2(gProgramPipelineMap2, id, readBufferOffset);
376 }
377
UpdateQueryID2(GLuint id,GLsizei readBufferOffset)378 void UpdateQueryID2(GLuint id, GLsizei readBufferOffset)
379 {
380 UpdateResourceMap2(gQueryMap2, id, readBufferOffset);
381 }
382
UpdateRenderbufferID2(GLuint id,GLsizei readBufferOffset)383 void UpdateRenderbufferID2(GLuint id, GLsizei readBufferOffset)
384 {
385 UpdateResourceMap2(gRenderbufferMap2, id, readBufferOffset);
386 }
387
UpdateSamplerID2(GLuint id,GLsizei readBufferOffset)388 void UpdateSamplerID2(GLuint id, GLsizei readBufferOffset)
389 {
390 UpdateResourceMap2(gSamplerMap2, id, readBufferOffset);
391 }
392
UpdateSemaphoreID2(GLuint id,GLsizei readBufferOffset)393 void UpdateSemaphoreID2(GLuint id, GLsizei readBufferOffset)
394 {
395 UpdateResourceMap2(gSemaphoreMap2, id, readBufferOffset);
396 }
397
UpdateShaderProgramID2(GLuint id,GLsizei readBufferOffset)398 void UpdateShaderProgramID2(GLuint id, GLsizei readBufferOffset)
399 {
400 UpdateResourceMap2(gShaderProgramMap2, id, readBufferOffset);
401 }
402
UpdateTextureID2(GLuint id,GLsizei readBufferOffset)403 void UpdateTextureID2(GLuint id, GLsizei readBufferOffset)
404 {
405 UpdateResourceMap2(gTextureMap2, id, readBufferOffset);
406 }
407
UpdateTransformFeedbackID2(GLuint id,GLsizei readBufferOffset)408 void UpdateTransformFeedbackID2(GLuint id, GLsizei readBufferOffset)
409 {
410 UpdateResourceMap2(gTransformFeedbackMap2, id, readBufferOffset);
411 }
412
UpdateVertexArrayID2(GLuint id,GLsizei readBufferOffset)413 void UpdateVertexArrayID2(GLuint id, GLsizei readBufferOffset)
414 {
415 UpdateResourceMap2(gVertexArrayMap2, id, readBufferOffset);
416 }
417
SetResourceID(GLuint * map,GLuint id)418 void SetResourceID(GLuint *map, GLuint id)
419 {
420 if (map[id] != 0)
421 {
422 fprintf(stderr, "%s: resource ID %d is already reserved\n", __func__, id);
423 exit(1);
424 }
425 map[id] = id;
426 }
427
SetFramebufferID(GLuint id)428 void SetFramebufferID(GLuint id)
429 {
430 SetResourceID(gFramebufferMap2, id);
431 }
432
ValidateSerializedState(const char * serializedState,const char * fileName,uint32_t line)433 void ValidateSerializedState(const char *serializedState, const char *fileName, uint32_t line)
434 {
435 if (gValidateSerializedStateCallback)
436 {
437 gValidateSerializedStateCallback(serializedState, fileName, line);
438 }
439 }
440