//// Created by Bradley Austin Davis on 2016/05/14// Copyright 2013-2016 High Fidelity, Inc.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//#include "GLShared.h" #include <mutex>#include <fstream> #include <QtCore/QThread> #include <gl/GLHelpers.h>#include <GPUIdent.h>#include <NumericalConstants.h>#include <shared/GlobalAppProperties.h> Q_LOGGING_CATEGORY(gpugllogging, "hifi.gpu.gl")Q_LOGGING_CATEGORY(trace_render_gpu_gl, "trace.render.gpu.gl")Q_LOGGING_CATEGORY(trace_render_gpu_gl_detail, "trace.render.gpu.gl.detail") namespace gpu { namespace gl { gpu::Size getFreeDedicatedMemory() { Size result { 0 }; auto backendApi = hifi::properties::getGraphicsAPI(); if (backendApi != hifi::properties::GraphicsAPI::GLES32) { static bool nvidiaMemorySupported { true }; static bool atiMemorySupported { true }; if (nvidiaMemorySupported) { GLint nvGpuMemory { 0 }; glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &nvGpuMemory); if (GL_NO_ERROR == glGetError()) { result = KB_TO_BYTES(nvGpuMemory); } else { nvidiaMemorySupported = false; } } else if (atiMemorySupported) { GLint atiGpuMemory[4]; // not really total memory, but close enough if called early enough in the application lifecycle glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, atiGpuMemory); if (GL_NO_ERROR == glGetError()) { result = KB_TO_BYTES(atiGpuMemory[0]); } else { atiMemorySupported = false; } } } return result;} ComparisonFunction comparisonFuncFromGL(GLenum func) { if (func == GL_NEVER) { return ComparisonFunction::NEVER; } else if (func == GL_LESS) { return ComparisonFunction::LESS; } else if (func == GL_EQUAL) { return ComparisonFunction::EQUAL; } else if (func == GL_LEQUAL) { return ComparisonFunction::LESS_EQUAL; } else if (func == GL_GREATER) { return ComparisonFunction::GREATER; } else if (func == GL_NOTEQUAL) { return ComparisonFunction::NOT_EQUAL; } else if (func == GL_GEQUAL) { return ComparisonFunction::GREATER_EQUAL; } else if (func == GL_ALWAYS) { return ComparisonFunction::ALWAYS; } return ComparisonFunction::ALWAYS;} State::StencilOp stencilOpFromGL(GLenum stencilOp) { if (stencilOp == GL_KEEP) { return State::STENCIL_OP_KEEP; } else if (stencilOp == GL_ZERO) { return State::STENCIL_OP_ZERO; } else if (stencilOp == GL_REPLACE) { return State::STENCIL_OP_REPLACE; } else if (stencilOp == GL_INCR_WRAP) { return State::STENCIL_OP_INCR_SAT; } else if (stencilOp == GL_DECR_WRAP) { return State::STENCIL_OP_DECR_SAT; } else if (stencilOp == GL_INVERT) { return State::STENCIL_OP_INVERT; } else if (stencilOp == GL_INCR) { return State::STENCIL_OP_INCR; } else if (stencilOp == GL_DECR) { return State::STENCIL_OP_DECR; } return State::STENCIL_OP_KEEP;} State::BlendOp blendOpFromGL(GLenum blendOp) { if (blendOp == GL_FUNC_ADD) { return State::BLEND_OP_ADD; } else if (blendOp == GL_FUNC_SUBTRACT) { return State::BLEND_OP_SUBTRACT; } else if (blendOp == GL_FUNC_REVERSE_SUBTRACT) { return State::BLEND_OP_REV_SUBTRACT; } else if (blendOp == GL_MIN) { return State::BLEND_OP_MIN; } else if (blendOp == GL_MAX) { return State::BLEND_OP_MAX; } return State::BLEND_OP_ADD;} State::BlendArg blendArgFromGL(GLenum blendArg) { if (blendArg == GL_ZERO) { return State::ZERO; } else if (blendArg == GL_ONE) { return State::ONE; } else if (blendArg == GL_SRC_COLOR) { return State::SRC_COLOR; } else if (blendArg == GL_ONE_MINUS_SRC_COLOR) { return State::INV_SRC_COLOR; } else if (blendArg == GL_DST_COLOR) { return State::DEST_COLOR; } else if (blendArg == GL_ONE_MINUS_DST_COLOR) { return State::INV_DEST_COLOR; } else if (blendArg == GL_SRC_ALPHA) { return State::SRC_ALPHA; } else if (blendArg == GL_ONE_MINUS_SRC_ALPHA) { return State::INV_SRC_ALPHA; } else if (blendArg == GL_DST_ALPHA) { return State::DEST_ALPHA; } else if (blendArg == GL_ONE_MINUS_DST_ALPHA) { return State::INV_DEST_ALPHA; } else if (blendArg == GL_CONSTANT_COLOR) { return State::FACTOR_COLOR; } else if (blendArg == GL_ONE_MINUS_CONSTANT_COLOR) { return State::INV_FACTOR_COLOR; } else if (blendArg == GL_CONSTANT_ALPHA) { return State::FACTOR_ALPHA; } else if (blendArg == GL_ONE_MINUS_CONSTANT_ALPHA) { return State::INV_FACTOR_ALPHA; } return State::ONE;} void getCurrentGLState(State::Data& state) { { auto backendApi = hifi::properties::getGraphicsAPI(); if (backendApi == hifi::properties::GraphicsAPI::GLES32) { state.fillMode = State::FILL_FACE; } else { GLint modes[2]; glGetIntegerv(GL_POLYGON_MODE, modes); if (modes[0] == GL_FILL) { state.fillMode = State::FILL_FACE; } else { if (modes[0] == GL_LINE) { state.fillMode = State::FILL_LINE; } else { state.fillMode = State::FILL_POINT; } } } } { if (glIsEnabled(GL_CULL_FACE)) { GLint mode; glGetIntegerv(GL_CULL_FACE_MODE, &mode); state.cullMode = (mode == GL_FRONT ? State::CULL_FRONT : State::CULL_BACK); } else { state.cullMode = State::CULL_NONE; } } { GLint winding; glGetIntegerv(GL_FRONT_FACE, &winding); state.flags.frontFaceClockwise = (winding == GL_CW); auto backendApi = hifi::properties::getGraphicsAPI(); if (backendApi == hifi::properties::GraphicsAPI::GLES32) { state.flags.multisampleEnable = glIsEnabled(GL_MULTISAMPLE_EXT); state.flags.antialisedLineEnable = false; state.flags.depthClampEnable = false; } else { state.flags.multisampleEnable = glIsEnabled(GL_MULTISAMPLE); state.flags.antialisedLineEnable = glIsEnabled(GL_LINE_SMOOTH); state.flags.depthClampEnable = glIsEnabled(GL_DEPTH_CLAMP); } state.flags.scissorEnable = glIsEnabled(GL_SCISSOR_TEST); } { if (glIsEnabled(GL_POLYGON_OFFSET_FILL)) { glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &state.depthBiasSlopeScale); glGetFloatv(GL_POLYGON_OFFSET_UNITS, &state.depthBias); } } { GLboolean isEnabled = glIsEnabled(GL_DEPTH_TEST); GLboolean writeMask; glGetBooleanv(GL_DEPTH_WRITEMASK, &writeMask); GLint func; glGetIntegerv(GL_DEPTH_FUNC, &func); state.depthTest = State::DepthTest(isEnabled, writeMask, comparisonFuncFromGL(func)); } { GLboolean isEnabled = glIsEnabled(GL_STENCIL_TEST); GLint frontWriteMask; GLint frontReadMask; GLint frontRef; GLint frontFail; GLint frontDepthFail; GLint frontPass; GLint frontFunc; glGetIntegerv(GL_STENCIL_WRITEMASK, &frontWriteMask); glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontReadMask); glGetIntegerv(GL_STENCIL_REF, &frontRef); glGetIntegerv(GL_STENCIL_FAIL, &frontFail); glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &frontDepthFail); glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &frontPass); glGetIntegerv(GL_STENCIL_FUNC, &frontFunc); GLint backWriteMask; GLint backReadMask; GLint backRef; GLint backFail; GLint backDepthFail; GLint backPass; GLint backFunc; glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &backWriteMask); glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backReadMask); glGetIntegerv(GL_STENCIL_BACK_REF, &backRef); glGetIntegerv(GL_STENCIL_BACK_FAIL, &backFail); glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &backDepthFail); glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &backPass); glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc); state.stencilActivation = State::StencilActivation(isEnabled, frontWriteMask, backWriteMask); state.stencilTestFront = State::StencilTest(frontRef, frontReadMask, comparisonFuncFromGL(frontFunc), stencilOpFromGL(frontFail), stencilOpFromGL(frontDepthFail), stencilOpFromGL(frontPass)); state.stencilTestBack = State::StencilTest(backRef, backReadMask, comparisonFuncFromGL(backFunc), stencilOpFromGL(backFail), stencilOpFromGL(backDepthFail), stencilOpFromGL(backPass)); } { GLint mask = 0xFFFFFFFF; if (glIsEnabled(GL_SAMPLE_MASK)) { glGetIntegerv(GL_SAMPLE_MASK, &mask); state.sampleMask = mask; } state.sampleMask = mask; } { state.flags.alphaToCoverageEnable = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE); } { GLboolean isEnabled = glIsEnabled(GL_BLEND); GLint srcRGB; GLint srcA; GLint dstRGB; GLint dstA; glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB); glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcA); glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB); glGetIntegerv(GL_BLEND_DST_ALPHA, &dstA); GLint opRGB; GLint opA; glGetIntegerv(GL_BLEND_EQUATION_RGB, &opRGB); glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &opA); state.blendFunction = State::BlendFunction(isEnabled, blendArgFromGL(srcRGB), blendOpFromGL(opRGB), blendArgFromGL(dstRGB), blendArgFromGL(srcA), blendOpFromGL(opA), blendArgFromGL(dstA)); } { GLboolean mask[4]; glGetBooleanv(GL_COLOR_WRITEMASK, mask); state.colorWriteMask = (State::ColorMask)((mask[0] ? State::WRITE_RED : 0) | (mask[1] ? State::WRITE_GREEN : 0) | (mask[2] ? State::WRITE_BLUE : 0) | (mask[3] ? State::WRITE_ALPHA : 0)); } (void)CHECK_GL_ERROR();} void serverWait() { auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); assert(fence); glWaitSync(fence, 0, GL_TIMEOUT_IGNORED); glDeleteSync(fence);} void clientWait() { auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); assert(fence); auto result = glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0); while (GL_TIMEOUT_EXPIRED == result || GL_WAIT_FAILED == result) { // Minimum sleep QThread::usleep(1); result = glClientWaitSync(fence, 0, 0); } glDeleteSync(fence);} } } using namespace gpu;
//
// Created by Bradley Austin Davis on 2016/05/14
// Copyright 2013-2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "GLShared.h"
#include <mutex>
#include <fstream>
#include <QtCore/QThread>
#include <gl/GLHelpers.h>
#include <GPUIdent.h>
#include <NumericalConstants.h>
#include <shared/GlobalAppProperties.h>
Q_LOGGING_CATEGORY(gpugllogging, "hifi.gpu.gl")
Q_LOGGING_CATEGORY(trace_render_gpu_gl, "trace.render.gpu.gl")
Q_LOGGING_CATEGORY(trace_render_gpu_gl_detail, "trace.render.gpu.gl.detail")
namespace gpu { namespace gl {
gpu::Size getFreeDedicatedMemory() {
Size result { 0 };
auto backendApi = hifi::properties::getGraphicsAPI();
if (backendApi != hifi::properties::GraphicsAPI::GLES32) {
static bool nvidiaMemorySupported { true };
static bool atiMemorySupported { true };
if (nvidiaMemorySupported) {
GLint nvGpuMemory { 0 };
glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &nvGpuMemory);
if (GL_NO_ERROR == glGetError()) {
result = KB_TO_BYTES(nvGpuMemory);
} else {
nvidiaMemorySupported = false;
}
} else if (atiMemorySupported) {
GLint atiGpuMemory[4];
// not really total memory, but close enough if called early enough in the application lifecycle
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, atiGpuMemory);
if (GL_NO_ERROR == glGetError()) {
result = KB_TO_BYTES(atiGpuMemory[0]);
} else {
atiMemorySupported = false;
}
}
}
return result;
}
ComparisonFunction comparisonFuncFromGL(GLenum func) {
if (func == GL_NEVER) {
return ComparisonFunction::NEVER;
} else if (func == GL_LESS) {
return ComparisonFunction::LESS;
} else if (func == GL_EQUAL) {
return ComparisonFunction::EQUAL;
} else if (func == GL_LEQUAL) {
return ComparisonFunction::LESS_EQUAL;
} else if (func == GL_GREATER) {
return ComparisonFunction::GREATER;
} else if (func == GL_NOTEQUAL) {
return ComparisonFunction::NOT_EQUAL;
} else if (func == GL_GEQUAL) {
return ComparisonFunction::GREATER_EQUAL;
} else if (func == GL_ALWAYS) {
return ComparisonFunction::ALWAYS;
}
return ComparisonFunction::ALWAYS;
}
State::StencilOp stencilOpFromGL(GLenum stencilOp) {
if (stencilOp == GL_KEEP) {
return State::STENCIL_OP_KEEP;
} else if (stencilOp == GL_ZERO) {
return State::STENCIL_OP_ZERO;
} else if (stencilOp == GL_REPLACE) {
return State::STENCIL_OP_REPLACE;
} else if (stencilOp == GL_INCR_WRAP) {
return State::STENCIL_OP_INCR_SAT;
} else if (stencilOp == GL_DECR_WRAP) {
return State::STENCIL_OP_DECR_SAT;
} else if (stencilOp == GL_INVERT) {
return State::STENCIL_OP_INVERT;
} else if (stencilOp == GL_INCR) {
return State::STENCIL_OP_INCR;
} else if (stencilOp == GL_DECR) {
return State::STENCIL_OP_DECR;
}
return State::STENCIL_OP_KEEP;
}
State::BlendOp blendOpFromGL(GLenum blendOp) {
if (blendOp == GL_FUNC_ADD) {
return State::BLEND_OP_ADD;
} else if (blendOp == GL_FUNC_SUBTRACT) {
return State::BLEND_OP_SUBTRACT;
} else if (blendOp == GL_FUNC_REVERSE_SUBTRACT) {
return State::BLEND_OP_REV_SUBTRACT;
} else if (blendOp == GL_MIN) {
return State::BLEND_OP_MIN;
} else if (blendOp == GL_MAX) {
return State::BLEND_OP_MAX;
}
return State::BLEND_OP_ADD;
}
State::BlendArg blendArgFromGL(GLenum blendArg) {
if (blendArg == GL_ZERO) {
return State::ZERO;
} else if (blendArg == GL_ONE) {
return State::ONE;
} else if (blendArg == GL_SRC_COLOR) {
return State::SRC_COLOR;
} else if (blendArg == GL_ONE_MINUS_SRC_COLOR) {
return State::INV_SRC_COLOR;
} else if (blendArg == GL_DST_COLOR) {
return State::DEST_COLOR;
} else if (blendArg == GL_ONE_MINUS_DST_COLOR) {
return State::INV_DEST_COLOR;
} else if (blendArg == GL_SRC_ALPHA) {
return State::SRC_ALPHA;
} else if (blendArg == GL_ONE_MINUS_SRC_ALPHA) {
return State::INV_SRC_ALPHA;
} else if (blendArg == GL_DST_ALPHA) {
return State::DEST_ALPHA;
} else if (blendArg == GL_ONE_MINUS_DST_ALPHA) {
return State::INV_DEST_ALPHA;
} else if (blendArg == GL_CONSTANT_COLOR) {
return State::FACTOR_COLOR;
} else if (blendArg == GL_ONE_MINUS_CONSTANT_COLOR) {
return State::INV_FACTOR_COLOR;
} else if (blendArg == GL_CONSTANT_ALPHA) {
return State::FACTOR_ALPHA;
} else if (blendArg == GL_ONE_MINUS_CONSTANT_ALPHA) {
return State::INV_FACTOR_ALPHA;
}
return State::ONE;
}
void getCurrentGLState(State::Data& state) {
{
auto backendApi = hifi::properties::getGraphicsAPI();
if (backendApi == hifi::properties::GraphicsAPI::GLES32) {
state.fillMode = State::FILL_FACE;
} else {
GLint modes[2];
glGetIntegerv(GL_POLYGON_MODE, modes);
if (modes[0] == GL_FILL) {
state.fillMode = State::FILL_FACE;
} else {
if (modes[0] == GL_LINE) {
state.fillMode = State::FILL_LINE;
} else {
state.fillMode = State::FILL_POINT;
}
}
}
}
{
if (glIsEnabled(GL_CULL_FACE)) {
GLint mode;
glGetIntegerv(GL_CULL_FACE_MODE, &mode);
state.cullMode = (mode == GL_FRONT ? State::CULL_FRONT : State::CULL_BACK);
} else {
state.cullMode = State::CULL_NONE;
}
}
{
GLint winding;
glGetIntegerv(GL_FRONT_FACE, &winding);
state.flags.frontFaceClockwise = (winding == GL_CW);
auto backendApi = hifi::properties::getGraphicsAPI();
if (backendApi == hifi::properties::GraphicsAPI::GLES32) {
state.flags.multisampleEnable = glIsEnabled(GL_MULTISAMPLE_EXT);
state.flags.antialisedLineEnable = false;
state.flags.depthClampEnable = false;
} else {
state.flags.multisampleEnable = glIsEnabled(GL_MULTISAMPLE);
state.flags.antialisedLineEnable = glIsEnabled(GL_LINE_SMOOTH);
state.flags.depthClampEnable = glIsEnabled(GL_DEPTH_CLAMP);
}
state.flags.scissorEnable = glIsEnabled(GL_SCISSOR_TEST);
}
{
if (glIsEnabled(GL_POLYGON_OFFSET_FILL)) {
glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &state.depthBiasSlopeScale);
glGetFloatv(GL_POLYGON_OFFSET_UNITS, &state.depthBias);
}
}
{
GLboolean isEnabled = glIsEnabled(GL_DEPTH_TEST);
GLboolean writeMask;
glGetBooleanv(GL_DEPTH_WRITEMASK, &writeMask);
GLint func;
glGetIntegerv(GL_DEPTH_FUNC, &func);
state.depthTest = State::DepthTest(isEnabled, writeMask, comparisonFuncFromGL(func));
}
{
GLboolean isEnabled = glIsEnabled(GL_STENCIL_TEST);
GLint frontWriteMask;
GLint frontReadMask;
GLint frontRef;
GLint frontFail;
GLint frontDepthFail;
GLint frontPass;
GLint frontFunc;
glGetIntegerv(GL_STENCIL_WRITEMASK, &frontWriteMask);
glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontReadMask);
glGetIntegerv(GL_STENCIL_REF, &frontRef);
glGetIntegerv(GL_STENCIL_FAIL, &frontFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &frontDepthFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &frontPass);
glGetIntegerv(GL_STENCIL_FUNC, &frontFunc);
GLint backWriteMask;
GLint backReadMask;
GLint backRef;
GLint backFail;
GLint backDepthFail;
GLint backPass;
GLint backFunc;
glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &backWriteMask);
glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backReadMask);
glGetIntegerv(GL_STENCIL_BACK_REF, &backRef);
glGetIntegerv(GL_STENCIL_BACK_FAIL, &backFail);
glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &backDepthFail);
glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &backPass);
glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc);
state.stencilActivation = State::StencilActivation(isEnabled, frontWriteMask, backWriteMask);
state.stencilTestFront = State::StencilTest(frontRef, frontReadMask, comparisonFuncFromGL(frontFunc), stencilOpFromGL(frontFail), stencilOpFromGL(frontDepthFail), stencilOpFromGL(frontPass));
state.stencilTestBack = State::StencilTest(backRef, backReadMask, comparisonFuncFromGL(backFunc), stencilOpFromGL(backFail), stencilOpFromGL(backDepthFail), stencilOpFromGL(backPass));
}
{
GLint mask = 0xFFFFFFFF;
if (glIsEnabled(GL_SAMPLE_MASK)) {
glGetIntegerv(GL_SAMPLE_MASK, &mask);
state.sampleMask = mask;
}
state.sampleMask = mask;
}
{
state.flags.alphaToCoverageEnable = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
{
GLboolean isEnabled = glIsEnabled(GL_BLEND);
GLint srcRGB;
GLint srcA;
GLint dstRGB;
GLint dstA;
glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB);
glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcA);
glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB);
glGetIntegerv(GL_BLEND_DST_ALPHA, &dstA);
GLint opRGB;
GLint opA;
glGetIntegerv(GL_BLEND_EQUATION_RGB, &opRGB);
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &opA);
state.blendFunction = State::BlendFunction(isEnabled,
blendArgFromGL(srcRGB), blendOpFromGL(opRGB), blendArgFromGL(dstRGB),
blendArgFromGL(srcA), blendOpFromGL(opA), blendArgFromGL(dstA));
}
{
GLboolean mask[4];
glGetBooleanv(GL_COLOR_WRITEMASK, mask);
state.colorWriteMask = (State::ColorMask)((mask[0] ? State::WRITE_RED : 0)
| (mask[1] ? State::WRITE_GREEN : 0)
| (mask[2] ? State::WRITE_BLUE : 0)
| (mask[3] ? State::WRITE_ALPHA : 0));
}
(void)CHECK_GL_ERROR();
}
void serverWait() {
auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
assert(fence);
glWaitSync(fence, 0, GL_TIMEOUT_IGNORED);
glDeleteSync(fence);
}
void clientWait() {
auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
assert(fence);
auto result = glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
while (GL_TIMEOUT_EXPIRED == result || GL_WAIT_FAILED == result) {
// Minimum sleep
QThread::usleep(1);
result = glClientWaitSync(fence, 0, 0);
}
glDeleteSync(fence);
}
} }
using namespace gpu;