56 if (VuoGlPool[type][size].size())
58 name = VuoGlPool[type][size].back();
59 VuoGlPool[type][size].pop_back();
64 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
66 if (type == VuoGlPool_ArrayBuffer || type == VuoGlPool_ElementArrayBuffer)
68 glGenBuffers(1, &name);
69 GLenum bufferType = type == VuoGlPool_ArrayBuffer ? GL_ARRAY_BUFFER : GL_ELEMENT_ARRAY_BUFFER;
70 glBindBuffer(bufferType, name);
71 glBufferData(bufferType, size, NULL, GL_STREAM_DRAW);
72 glBindBuffer(bufferType, 0);
77 VUserLog(
"Unknown pool type %d.", type);
138 if (glBufferName == 0)
143 VuoGlPoolReferenceCounts::iterator it = VuoGlPool_referenceCounts.find(glBufferName);
144 if (it == VuoGlPool_referenceCounts.end())
145 VuoLog(
VuoLog_moduleName, file, linenumber, func,
"Error: VuoGlPool_release() was called with OpenGL Buffer Object %d, which was never retained.", glBufferName);
148 if (--VuoGlPool_referenceCounts[glBufferName] == 0)
245 if (format == GL_LUMINANCE
246 || format == GL_LUMINANCE8
247 || format == GL_LUMINANCE16F_ARB
248 || format == GL_LUMINANCE32F_ARB
249 || format == GL_DEPTH_COMPONENT)
251 else if (format == GL_YCBCR_422_APPLE
252 || format == GL_LUMINANCE_ALPHA
253 || format == GL_LUMINANCE_ALPHA16F_ARB
254 || format == GL_LUMINANCE_ALPHA32F_ARB)
256 else if (format == GL_RGB
257 || format == GL_RGB16F_ARB
258 || format == GL_RGB32F_ARB
259 || format == GL_BGR_EXT)
261 else if (format == GL_RGBA
262 || format == GL_RGBA8
263 || format == GL_RGBA16F_ARB
264 || format == GL_RGBA32F_ARB
265 || format == GL_BGRA)
269 VUserLog(
"Unknown format %s", formatString);
280 if (internalformat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
282 if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT
283 || internalformat == GL_COMPRESSED_RED_RGTC1)
287 if (internalformat == GL_RGB
288 || internalformat == GL_RGBA
289 || internalformat == GL_RGBA8
290 || internalformat == GL_LUMINANCE8
291 || internalformat == GL_LUMINANCE8_ALPHA8)
293 else if (internalformat == GL_RGB16F_ARB
294 || internalformat == GL_RGBA16F_ARB
295 || internalformat == GL_DEPTH_COMPONENT
296 || internalformat == GL_LUMINANCE16F_ARB
297 || internalformat == GL_LUMINANCE_ALPHA16F_ARB)
299 else if (internalformat == GL_RGB32F_ARB
300 || internalformat == GL_RGBA32F_ARB
301 || internalformat == GL_LUMINANCE32F_ARB
302 || internalformat == GL_LUMINANCE_ALPHA32F_ARB)
316 if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT
317 || internalformat == GL_COMPRESSED_RED_RGTC1)
319 if (internalformat == GL_LUMINANCE8
320 || internalformat == GL_LUMINANCE
321 || internalformat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
323 if (internalformat == GL_LUMINANCE8_ALPHA8
324 || internalformat == GL_LUMINANCE16F_ARB
325 || internalformat == GL_DEPTH_COMPONENT)
327 if (internalformat == GL_RGB
328 || internalformat == GL_BGR)
330 if (internalformat == GL_RGBA
331 || internalformat == GL_RGBA8
332 || internalformat == GL_BGRA
333 || internalformat == GL_LUMINANCE_ALPHA16F_ARB
334 || internalformat == GL_LUMINANCE32F_ARB)
336 if (internalformat == GL_RGB16F_ARB)
338 if (internalformat == GL_RGBA16F_ARB
339 || internalformat == GL_LUMINANCE_ALPHA32F_ARB)
341 if (internalformat == GL_RGB32F_ARB)
343 if (internalformat == GL_RGBA32F_ARB)
347 VUserLog(
"Unknown internalformat %s", formatString);
379#pragma clang diagnostic push
380#pragma clang diagnostic ignored "-Wdeprecated-declarations"
381 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
382 static unsigned long maximumTextureBytes = 0;
383 static dispatch_once_t maximumTextureBytesQuery = 0;
384 dispatch_once(&maximumTextureBytesQuery, ^{
385 GLint contextRendererID;
386 CGLGetParameter(cgl_ctx, kCGLCPCurrentRendererID, &contextRendererID);
392 CGLRendererInfoObj ri;
393 GLint rendererCount = 0;
394 CGLQueryRendererInfo(-1, &ri, &rendererCount);
395 for (
int i = 0; i < rendererCount; ++i)
398 CGLDescribeRenderer(ri, i, kCGLRPRendererID, &rendererID);
399 if (rendererID == contextRendererID)
401 GLint textureMegabytes = 0;
402 if (CGLDescribeRenderer(ri, i, kCGLRPTextureMemoryMegabytes, &textureMegabytes) == kCGLNoError)
408 if ((rendererID & kCGLRendererIDMatchingMask) == kCGLRendererIntelHD4000ID)
412 maximumTextureBytes = (textureMegabytes - 85) * 1048576UL * fudge;
413 VUserLog(
"%ld MB", maximumTextureBytes / 1024 / 1024);
418 CGLDestroyRendererInfo(ri);
420 return maximumTextureBytes;
421#pragma clang diagnostic pop
477 if (allocation == VuoGlTexturePool_AllocateIOSurface
478 && target != GL_TEXTURE_RECTANGLE_ARB)
480 VUserLog(
"Error: To use VuoGlTexturePool_AllocateIOSurface, target must be GL_TEXTURE_RECTANGLE_ARB.");
485 unsigned long requiredBytes = width * height * bytesPerPixel;
490 if (allocation != VuoGlTexturePool_AllocateIOSurface)
496 name = it->second.first.front();
497 it->second.first.pop();
505 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
511 if (maximumTextureBytes > 0)
513 if (requiredBytes > maximumTextureBytes)
516 VUserLog(
"Not enough graphics memory for a %dx%d (%d bytes/pixel) texture. Requires %lu MB, have %lu MB.", width, height, bytesPerPixel, requiredBytes/1024/1024, maximumTextureBytes/1024/1024);
523 if (width > maxDimension || height > maxDimension)
526 VUserLog(
"This GPU doesn't support textures of size %dx%d (GPU's limit is %dx%d).", width, height, maxDimension, maxDimension);
530 glGenTextures(1, &name);
532 glBindTexture(target, name);
533 if (allocation == VuoGlTexturePool_Allocate)
535 glTexImage2D(target, 0, internalformat, width, height, 0, format,
VuoGlTexture_getType(format), NULL);
538 else if (allocation == VuoGlTexturePool_AllocateIOSurface)
540#pragma clang diagnostic push
541#pragma clang diagnostic ignored "-Wdeprecated-declarations"
542 CGLError err = CGLTexImageIOSurface2D(cgl_ctx, GL_TEXTURE_RECTANGLE_ARB, internalformat, width, height, format,
VuoGlTexture_getType(format), (IOSurfaceRef)ioSurfaceRef, 0);
543 if (err != kCGLNoError)
548 VUserLog(
"Error in CGLTexImageIOSurface2D(context, GL_TEXTURE_RECTANGLE_ARB, %s, %hu, %hu, %s, %s, iosurface, 0): %s",
549 internalFormatString, width, height, formatString, typeString, CGLErrorString(err));
550 free(internalFormatString);
556#pragma clang diagnostic pop
561 glBindTexture(target, name);
564 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
565 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
567 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
568 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
570 glBindTexture(target, 0);
587 if (internalformat == 0)
589 VUserLog(
"Error: Can't recycle texture %d since we don't know its internalformat. Deleting.", name);
591 glDeleteTextures(1, &name);
597 if (allocation == VuoGlTexturePool_AllocateIOSurface)
600 glDeleteTextures(1, &name);
610 auto it = &(*VuoGlTexturePool)[descriptor];
611 it->first.push(name);
675 if (glTextureName == 0)
682 VUserLog(
"Error: VuoGlTexture_release() was called with OpenGL Texture Object %d, which was never retained.", glTextureName);
685 VuoGlTexture t = (*VuoGlTexture_referenceCounts)[glTextureName];
686 if (--t.referenceCount == 0)
691 struct _VuoImage i = (
struct _VuoImage){glTextureName, internalformat, glTextureTarget, width, height, 1, t.freeCallbackContext, NULL, NULL, NULL};
809 unsigned long totalTextureCount = 0;
810 static unsigned long totalTextureCountMax = 0;
812 vector<GLuint> texturesToDelete;
813 vector<VuoIoSurfacePoolEntryType> iosurfaceTexturesToDisuse;
820 unsigned long textureCount = poolItem->second.first.size();
821 double timeSinceLastUsed = now - poolItem->second.second;
828 while (!poolItem->second.first.empty())
830 GLuint textureName = poolItem->second.first.front();
831 poolItem->second.first.pop();
832 texturesToDelete.push_back(textureName);
841 totalTextureCount += textureCount;
848 if (totalTextureCount > totalTextureCountMax)
849 totalTextureCountMax = totalTextureCount;
852 unsigned long totalIOSurfaceCount = 0;
853 static unsigned long totalIOSurfaceCountMax = 0;
860 for (deque<VuoIoSurfacePoolEntryType>::iterator quarantinedIoSurfaceEntry = quarantinedQueue->second.begin(); quarantinedIoSurfaceEntry != quarantinedQueue->second.end();)
868 (*VuoIoSurfacePool)[quarantinedQueue->first].push_back(e);
869 quarantinedIoSurfaceEntry = quarantinedQueue->second.erase(quarantinedIoSurfaceEntry);
875 ++totalIOSurfaceCount;
876 ++quarantinedIoSurfaceEntry;
885 for (deque<VuoIoSurfacePoolEntryType>::iterator poolIoSurfaceEntry = poolQueue->second.begin(); poolIoSurfaceEntry != poolQueue->second.end();)
892 CFRelease(e.ioSurface);
893 iosurfaceTexturesToDisuse.push_back(e);
894 poolIoSurfaceEntry = poolQueue->second.erase(poolIoSurfaceEntry);
898 ++totalIOSurfaceCount;
899 ++poolIoSurfaceEntry;
906 if (totalIOSurfaceCount > totalIOSurfaceCountMax)
907 totalIOSurfaceCountMax = totalIOSurfaceCount;
911 if (texturesToDelete.size())
913 for (vector<GLuint>::const_iterator i = texturesToDelete.begin(); i != texturesToDelete.end(); ++i)
916 glDeleteTextures(1, &t);
920 for (
auto e : iosurfaceTexturesToDisuse)
921 VuoGlTexturePool_disuse(VuoGlTexturePool_AllocateIOSurface, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, e.pixelsWide, e.pixelsHigh, e.texture);
926 static unsigned long cleanupCount = 0;
930 || totalTextureCount > 0 || totalTextureCountMax > 0
931 || totalIOSurfaceCount > 0 || totalIOSurfaceCountMax > 0))
933 __block
unsigned long maximumTextureBytes;
938 if (maximumTextureBytes > 0)
939 VUserLog(
"VRAM used: %5lu MB (%5lu MB max, %3lu%%). Textures in pool: %3lu (%3lu max). IOSurfaces in pool: %3lu (%3lu max).",
943 totalTextureCount, totalTextureCountMax,
944 totalIOSurfaceCount, totalIOSurfaceCountMax);
946 VUserLog(
"VRAM used: %5lu MB (%5lu MB max). Textures in pool: %3lu (%3lu max). IOSurfaces in pool: %3lu (%3lu max).",
949 totalTextureCount, totalTextureCountMax,
950 totalIOSurfaceCount, totalIOSurfaceCountMax);
1005 *outputTexture = e.texture;
1006 (*VuoIoSurfacePool)[dimensions].pop_front();
1014 CFMutableDictionaryRef properties = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
1016#pragma clang diagnostic push
1017#pragma clang diagnostic ignored "-Wdeprecated-declarations"
1020 CFDictionaryAddValue(properties, kIOSurfaceIsGlobal, kCFBooleanTrue);
1021#pragma clang diagnostic pop
1023 long long pixelsWideLL = pixelsWide;
1024 CFNumberRef pixelsWideCF = CFNumberCreate(NULL, kCFNumberLongLongType, &pixelsWideLL);
1025 CFDictionaryAddValue(properties, kIOSurfaceWidth, pixelsWideCF);
1027 long long pixelsHighLL = pixelsHigh;
1028 CFNumberRef pixelsHighCF = CFNumberCreate(NULL, kCFNumberLongLongType, &pixelsHighLL);
1029 CFDictionaryAddValue(properties, kIOSurfaceHeight, pixelsHighCF);
1031 long long bytesPerElement = 4;
1032 CFNumberRef bytesPerElementCF = CFNumberCreate(NULL, kCFNumberLongLongType, &bytesPerElement);
1033 CFDictionaryAddValue(properties, kIOSurfaceBytesPerElement, bytesPerElementCF);
1035 uint32_t pixelFormat =
'BGRA';
1036 CFNumberRef pixelFormatCF = CFNumberCreate(NULL, kCFNumberSInt32Type, &pixelFormat);
1037 CFDictionaryAddValue(properties, kIOSurfacePixelFormat, pixelFormatCF);
1039 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1043 e->ioSurface = IOSurfaceCreate(properties);
1044 e->pixelsWide = pixelsWide;
1045 e->pixelsHigh = pixelsHigh;
1046 e->lastUsedTime = -1;
1047 CFRelease(pixelsWideCF);
1048 CFRelease(pixelsHighCF);
1049 CFRelease(bytesPerElementCF);
1050 CFRelease(properties);
1052 *outputTexture =
VuoGlTexturePool_use(cgl_ctx, VuoGlTexturePool_AllocateIOSurface, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, pixelsWide, pixelsHigh, GL_BGRA, e->ioSurface);
1053 e->texture = *outputTexture;
1156 int infologLength = 0;
1157 glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
1158 if (infologLength > 0)
1160 char *infoLog = (
char *)malloc(infologLength);
1161 int charsWritten = 0;
1162 glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
1166 istringstream iss(infoLog);
1168 while (getline(iss, ln))
1171 char *message = (
char *)malloc(ln.length() + 1);
1172 char *quotation = (
char *)malloc(ln.length() + 1);
1173 if (sscanf(ln.c_str(),
"ERROR: 0:%d: '' : %[^\n]", &lineNumber, message) == 2)
1174 outIssues->
addIssue(stage, lineNumber, message);
1175 else if (sscanf(ln.c_str(),
"ERROR: 0:%d: '%[^']' : syntax error: %[^\n]", &lineNumber, quotation, message) == 3)
1176 outIssues->
addIssue(stage, lineNumber, message +
string(
": '") + quotation +
"'");
1177 else if (sscanf(ln.c_str(),
"ERROR: 0:%d: %[^\n]", &lineNumber, message) == 2)
1178 outIssues->
addIssue(stage, lineNumber, message);
1179 else if (sscanf(ln.c_str(),
"WARNING: 0:%d: %[^\n]", &lineNumber, message) == 2)
1180 outIssues->
addIssue(stage, lineNumber, message);
1183 VUserLog(
"Warning: Couldn't parse GLSL log message: \"%s\"", ln.c_str());
1223 userModulesPath =
"";
1226 systemModulesPath =
"";
1228 set<string> includedFiles;
1232 const string includeKeyword =
"#include";
1234 size_t includeStart = source.find(includeKeyword);
1235 if (includeStart == string::npos)
1238 size_t offset = includeStart + includeKeyword.length();
1240 while (source[offset] ==
' ')
1243 if (source[offset] !=
'"'
1244 && source[offset] !=
'<')
1250 VUserLog(
"Error: Syntax error in #include statement. Expected syntax: #include \"filename.glsl\"");
1255 size_t filenameStart = offset;
1257 while (source[offset] !=
'"'
1258 && source[offset] !=
'>')
1261 size_t filenameEnd = offset;
1263 string filename = source.substr(filenameStart, filenameEnd - filenameStart);
1265 vector<string> pathsToTest;
1266 if (strcmp(cwd,
"/") != 0)
1267 pathsToTest.push_back(cwd +
string(
"/") + filename);
1268 if (!vuoFrameworkPath.empty())
1269 pathsToTest.push_back(vuoFrameworkPath +
"/Resources/shaders/" + filename);
1270 if (!vuoRunnerFrameworkPath.empty())
1271 pathsToTest.push_back(vuoRunnerFrameworkPath +
"/Resources/shaders/" + filename);
1272 if (!userModulesPath.empty())
1273 pathsToTest.push_back(userModulesPath +
"/" + filename);
1274 if (!systemModulesPath.empty())
1275 pathsToTest.push_back(systemModulesPath +
"/" + filename);
1277 for (vector<string>::iterator i = pathsToTest.begin(); i != pathsToTest.end(); ++i)
1283 source.erase(includeStart, offset - includeStart + 1);
1286 if (includedFiles.count(*i))
1288 source.insert(includeStart,
1290 "// ============================================================\n"
1291 "// Skipped including file \"" + *i +
"\" since it was already included.\n"
1292 "// ============================================================\n"
1297 includedFiles.insert(*i);
1299 source.insert(includeStart,
1301 "// ============================================================\n"
1302 "// Begin included file \"" + *i +
"\"\n"
1305 "// End included file \"" + *i +
"\"\n"
1306 "// ============================================================\n"
1319 VUserLog(
"Error: Couldn't find include file \"%s\".", filename.c_str());
1352 if (!outIssues && VuoGlShaderPool[type].find(hash) != VuoGlShaderPool[type].end())
1353 shader = VuoGlShaderPool[type][hash];
1356 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1358 string combinedSource = source;
1361 VuoShaderFile::Stage stage;
1362 if (type == GL_VERTEX_SHADER)
1363 stage = VuoShaderFile::Vertex;
1364 else if (type == GL_GEOMETRY_SHADER_EXT)
1365 stage = VuoShaderFile::Geometry;
1367 stage = VuoShaderFile::Fragment;
1377 shader = glCreateShader(type);
1378 GLint length = combinedSource.length();
1379 const GLchar *combinedSourceCString = combinedSource.c_str();
1380 glShaderSource(shader, 1, (
const GLchar**)&combinedSourceCString, &length);
1381 glCompileShader(shader);
1384 GLint status = GL_FALSE;
1385 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
1386 if (status == GL_FALSE)
1388 glDeleteShader(shader);
1393 VuoGlShaderPool[type][hash] = shader;
1435 VuoGlProgramDescriptorType e(vertexShaderName, std::make_pair(geometryShaderName, std::make_pair(fragmentShaderName, std::make_pair(assemblyMethod, expectedOutputPrimitiveCount))));
1439 program = it->second;
1442 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1444 GLuint programName = glCreateProgram();
1445 glAttachShader(programName, vertexShaderName);
1446 if (geometryShaderName)
1447 glAttachShader(programName, geometryShaderName);
1448 if (fragmentShaderName)
1449 glAttachShader(programName, fragmentShaderName);
1451 bool transformFeedback =
false;
1453 if (!fragmentShaderName)
1454 transformFeedback =
true;
1457 glBindAttribLocation(programName, 0,
"position");
1459 if (geometryShaderName)
1461 GLuint inputPrimitiveGlMode = GL_TRIANGLES;
1464 inputPrimitiveGlMode = GL_LINES;
1466 inputPrimitiveGlMode = GL_POINTS;
1467 glProgramParameteriEXT(programName, GL_GEOMETRY_INPUT_TYPE_EXT, inputPrimitiveGlMode);
1469 GLuint outputPrimitiveGlMode = GL_TRIANGLE_STRIP;
1470 if (transformFeedback)
1475 outputPrimitiveGlMode = GL_LINE_STRIP;
1477 outputPrimitiveGlMode = GL_POINTS;
1479 glProgramParameteriEXT(programName, GL_GEOMETRY_OUTPUT_TYPE_EXT, outputPrimitiveGlMode);
1481 unsigned int expectedVertexCount = expectedOutputPrimitiveCount;
1482 if (outputPrimitiveGlMode == GL_TRIANGLE_STRIP)
1483 expectedVertexCount *= 3;
1484 else if (outputPrimitiveGlMode == GL_LINE_STRIP)
1485 expectedVertexCount *= 2;
1486 glProgramParameteriEXT(programName, GL_GEOMETRY_VERTICES_OUT_EXT, expectedVertexCount);
1489 if (transformFeedback)
1491 const GLchar *varyings[] = {
"outPosition",
"outNormal",
"outTextureCoordinate",
"outVertexColor" };
1492 glTransformFeedbackVaryingsEXT(programName, 4, varyings, GL_SEPARATE_ATTRIBS_EXT);
1495 glLinkProgram(programName);
1498 int infologLength = 0;
1499 glGetProgramiv(programName, GL_INFO_LOG_LENGTH, &infologLength);
1500 if (infologLength > 0)
1502 char *infoLog = (
char *)malloc(infologLength);
1503 int charsWritten = 0;
1504 glGetProgramInfoLog(programName, infologLength, &charsWritten, infoLog);
1510 istringstream iss(infoLog);
1512 while (getline(iss, ln))
1521 VUserLog(
"Warning: Couldn't parse GLSL log message: \"%s\"", ln.c_str());
1527 VUserLog(
"%s: %s", description, infoLog);
1534 glGetProgramiv(programName, GL_LINK_STATUS, &linkStatus);
1535 if (linkStatus == GL_FALSE)
1537 glDeleteProgram(programName);
1542 program.programName = programName;
1545 glGetProgramiv(programName, GL_ACTIVE_UNIFORMS, &uniformCount);
1547 GLint maxNameLength;
1548 glGetProgramiv(programName, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
1549 char *name = (
char *)malloc(maxNameLength + 1);
1552 program.uniforms = (
void *)uniforms;
1554 for (GLuint i = 0; i < uniformCount; ++i)
1557 glGetActiveUniform(programName, i, maxNameLength+1, NULL, &size, NULL, name);
1560 size_t nameLen = strlen(name);
1562 (*uniforms)[hash] = glGetUniformLocation(programName, name);
1568 if (name[nameLen-2] ==
'0' && name[nameLen-1] ==
']')
1570 name[nameLen-2] = 0;
1571 for (
int i = 1; i < size; ++i)
1573 std::stringstream ss;
1574 ss << name << i <<
"]";
1575 string sss = ss.str();
1577 (*uniforms)[sHash] = glGetUniformLocation(programName, sss.c_str());
1617 return strdup(
"(GL_ZERO or GL_POINTS)");
1619 return strdup(
"(GL_ONE or GL_LINES)");