void WrappedOpenGL::glCreateProgramPipelines(GLsizei n, GLuint *pipelines) { m_Real.glCreateProgramPipelines(n, pipelines); for(GLsizei i = 0; i < n; i++) { GLResource res = ProgramPipeRes(GetCtx(), pipelines[i]); ResourceId id = GetResourceManager()->RegisterResource(res); if(m_State >= WRITING) { Chunk *chunk = NULL; { SCOPED_SERIALISE_CONTEXT(CREATE_PROGRAMPIPE); Serialise_glCreateProgramPipelines(1, pipelines + i); chunk = scope.Get(); } GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id); RDCASSERT(record); record->AddChunk(chunk); } else { GetResourceManager()->AddLiveResource(id, res); } } }
bool WrappedOpenGL::Serialise_glCreateProgramPipelines(GLsizei n, GLuint* pipelines) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), *pipelines))); if(m_State == READING) { GLuint real = 0; m_Real.glCreateProgramPipelines(1, &real); GLResource res = ProgramPipeRes(GetCtx(), real); ResourceId live = m_ResourceManager->RegisterResource(res); GetResourceManager()->AddLiveResource(id, res); } return true; }
bool WrappedOpenGL::Serialise_glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) { SERIALISE_ELEMENT(ResourceId, pipe, GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), pipeline))); SERIALISE_ELEMENT(uint32_t, Stages, stages); SERIALISE_ELEMENT(ResourceId, prog, (program ? GetResourceManager()->GetID(ProgramRes(GetCtx(), program)) : ResourceId())); if(m_State < WRITING) { if(prog != ResourceId()) { ResourceId livePipeId = GetResourceManager()->GetLiveID(pipe); ResourceId liveProgId = GetResourceManager()->GetLiveID(prog); PipelineData &pipeDetails = m_Pipelines[livePipeId]; ProgramData &progDetails = m_Programs[liveProgId]; for(size_t s=0; s < 6; s++) { if(Stages & ShaderBit(s)) { for(size_t sh=0; sh < progDetails.shaders.size(); sh++) { if(m_Shaders[ progDetails.shaders[sh] ].type == ShaderEnum(s)) { pipeDetails.stagePrograms[s] = liveProgId; pipeDetails.stageShaders[s] = progDetails.shaders[sh]; break; } } } } m_Real.glUseProgramStages(GetResourceManager()->GetLiveResource(pipe).name, Stages, GetResourceManager()->GetLiveResource(prog).name); } else { ResourceId livePipeId = GetResourceManager()->GetLiveID(pipe); PipelineData &pipeDetails = m_Pipelines[livePipeId]; for(size_t s=0; s < 6; s++) { if(Stages & ShaderBit(s)) { pipeDetails.stagePrograms[s] = ResourceId(); pipeDetails.stageShaders[s] = ResourceId(); } } m_Real.glUseProgramStages(GetResourceManager()->GetLiveResource(pipe).name, Stages, 0); } } return true; }
void WrappedOpenGL::glDeleteProgramPipelines(GLsizei n, const GLuint *pipelines) { for(GLsizei i = 0; i < n; i++) { GLResource res = ProgramPipeRes(GetCtx(), pipelines[i]); if(GetResourceManager()->HasCurrentResource(res)) { if(GetResourceManager()->HasResourceRecord(res)) GetResourceManager()->GetResourceRecord(res)->Delete(GetResourceManager()); GetResourceManager()->UnregisterResource(res); } } m_Real.glDeleteProgramPipelines(n, pipelines); }
void WrappedOpenGL::glBindProgramPipeline(GLuint pipeline) { m_Real.glBindProgramPipeline(pipeline); GetCtxData().m_ProgramPipeline = pipeline; if(m_State == WRITING_CAPFRAME) { SCOPED_SERIALISE_CONTEXT(BIND_PROGRAMPIPE); Serialise_glBindProgramPipeline(pipeline); m_ContextRecord->AddChunk(scope.Get()); GetResourceManager()->MarkResourceFrameReferenced(ProgramPipeRes(GetCtx(), pipeline), eFrameRef_Read); } }
bool WrappedOpenGL::Serialise_glBindProgramPipeline(GLuint pipeline) { SERIALISE_ELEMENT(ResourceId, id, (pipeline ? GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), pipeline)) : ResourceId())); if(m_State <= EXECUTING) { if(id == ResourceId()) { m_Real.glBindProgramPipeline(0); } else { GLuint live = GetResourceManager()->GetLiveResource(id).name; m_Real.glBindProgramPipeline(live); } } return true; }
void WrappedOpenGL::glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) { m_Real.glUseProgramStages(pipeline, stages, program); if(m_State > WRITING) { SCOPED_SERIALISE_CONTEXT(USE_PROGRAMSTAGES); Serialise_glUseProgramStages(pipeline, stages, program); GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ProgramPipeRes(GetCtx(), pipeline)); RDCASSERT(record); record->AddChunk(scope.Get()); if(program) { GLResourceRecord *progrecord = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), program)); RDCASSERT(progrecord); record->AddParent(progrecord); } } }
void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl) { GLResourceManager *rm = gl->GetResourceManager(); // TODO check GL_MAX_* m_pSerialiser->Serialise<eEnabled_Count>("GL_ENABLED", Enabled); for(size_t i=0; i < ARRAY_COUNT(Tex2D); i++) { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(TextureRes(ctx, Tex2D[i])); m_pSerialiser->Serialise("GL_TEXTURE_BINDING_2D", ID); if(state < WRITING && ID != ResourceId()) Tex2D[i] = rm->GetLiveResource(ID).name; } for(size_t i=0; i < ARRAY_COUNT(Samplers); i++) { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(SamplerRes(ctx, Samplers[i])); m_pSerialiser->Serialise("GL_SAMPLER_BINDING", ID); if(state < WRITING && ID != ResourceId()) Samplers[i] = rm->GetLiveResource(ID).name; } m_pSerialiser->Serialise("GL_ACTIVE_TEXTURE", ActiveTexture); { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(VertexArrayRes(ctx, VAO)); m_pSerialiser->Serialise("GL_VERTEX_ARRAY_BINDING", ID); if(state < WRITING && ID != ResourceId()) VAO = rm->GetLiveResource(ID).name; if(VAO == 0) VAO = gl->GetFakeVAO(); } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(FeedbackRes(ctx, FeedbackObj)); m_pSerialiser->Serialise("GL_TRANSFORM_FEEDBACK_BINDING", ID); if(state < WRITING && ID != ResourceId()) FeedbackObj = rm->GetLiveResource(ID).name; } for(size_t i=0; i < ARRAY_COUNT(GenericVertexAttribs); i++) { m_pSerialiser->Serialise<4>("GL_CURRENT_VERTEX_ATTRIB", &GenericVertexAttribs[i].x); } m_pSerialiser->Serialise("GL_POINT_FADE_THRESHOLD_SIZE", PointFadeThresholdSize); m_pSerialiser->Serialise("GL_POINT_SPRITE_COORD_ORIGIN", PointSpriteOrigin); m_pSerialiser->Serialise("GL_LINE_WIDTH", LineWidth); m_pSerialiser->Serialise("GL_POINT_SIZE", PointSize); m_pSerialiser->Serialise("GL_PRIMITIVE_RESTART_INDEX", PrimitiveRestartIndex); m_pSerialiser->Serialise("GL_CLIP_ORIGIN", ClipOrigin); m_pSerialiser->Serialise("GL_CLIP_DEPTH_MODE", ClipDepth); m_pSerialiser->Serialise("GL_PROVOKING_VERTEX", ProvokingVertex); for(size_t i=0; i < ARRAY_COUNT(BufferBindings); i++) { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(BufferRes(ctx, BufferBindings[i])); m_pSerialiser->Serialise("GL_BUFFER_BINDING", ID); if(state < WRITING && ID != ResourceId()) BufferBindings[i] = rm->GetLiveResource(ID).name; } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(ProgramRes(ctx, Program)); m_pSerialiser->Serialise("GL_CURRENT_PROGRAM", ID); if(state < WRITING && ID != ResourceId()) Program = rm->GetLiveResource(ID).name; } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(ProgramPipeRes(ctx, Pipeline)); m_pSerialiser->Serialise("GL_PROGRAM_PIPELINE_BINDING", ID); if(state < WRITING && ID != ResourceId()) Pipeline = rm->GetLiveResource(ID).name; } for(size_t s=0; s < ARRAY_COUNT(Subroutines); s++) { m_pSerialiser->Serialise("GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS", Subroutines[s].numSubroutines); m_pSerialiser->Serialise<128>("GL_SUBROUTINE_UNIFORMS", Subroutines[s].Values); } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(FramebufferRes(ctx, DrawFBO)); m_pSerialiser->Serialise("GL_DRAW_FRAMEBUFFER_BINDING", ID); if(state < WRITING && ID != ResourceId()) DrawFBO = rm->GetLiveResource(ID).name; if(DrawFBO == 0) DrawFBO = gl->GetFakeBBFBO(); } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(FramebufferRes(ctx, ReadFBO)); m_pSerialiser->Serialise("GL_READ_FRAMEBUFFER_BINDING", ID); if(state < WRITING && ID != ResourceId()) ReadFBO = rm->GetLiveResource(ID).name; if(ReadFBO == 0) ReadFBO = gl->GetFakeBBFBO(); } struct { IdxRangeBuffer *bufs; int count; } idxBufs[] = { { AtomicCounter, ARRAY_COUNT(AtomicCounter), }, { ShaderStorage, ARRAY_COUNT(ShaderStorage), }, { TransformFeedback, ARRAY_COUNT(TransformFeedback), }, { UniformBinding, ARRAY_COUNT(UniformBinding), }, }; for(size_t b=0; b < ARRAY_COUNT(idxBufs); b++) { for(int i=0; i < idxBufs[b].count; i++) { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(BufferRes(ctx, idxBufs[b].bufs[i].name)); m_pSerialiser->Serialise("BUFFER_BINDING", ID); if(state < WRITING && ID != ResourceId()) idxBufs[b].bufs[i].name = rm->GetLiveResource(ID).name; m_pSerialiser->Serialise("BUFFER_START", idxBufs[b].bufs[i].start); m_pSerialiser->Serialise("BUFFER_SIZE", idxBufs[b].bufs[i].size); } } for(size_t i=0; i < ARRAY_COUNT(Blends); i++) { m_pSerialiser->Serialise("GL_BLEND_EQUATION_RGB", Blends[i].EquationRGB); m_pSerialiser->Serialise("GL_BLEND_EQUATION_ALPHA", Blends[i].EquationAlpha); m_pSerialiser->Serialise("GL_BLEND_SRC_RGB", Blends[i].SourceRGB); m_pSerialiser->Serialise("GL_BLEND_SRC_ALPHA", Blends[i].SourceAlpha); m_pSerialiser->Serialise("GL_BLEND_DST_RGB", Blends[i].DestinationRGB); m_pSerialiser->Serialise("GL_BLEND_DST_ALPHA", Blends[i].DestinationAlpha); m_pSerialiser->Serialise("GL_BLEND", Blends[i].Enabled); } m_pSerialiser->Serialise<4>("GL_BLEND_COLOR", BlendColor); for(size_t i=0; i < ARRAY_COUNT(Viewports); i++) { m_pSerialiser->Serialise("GL_VIEWPORT.x", Viewports[i].x); m_pSerialiser->Serialise("GL_VIEWPORT.y", Viewports[i].y); m_pSerialiser->Serialise("GL_VIEWPORT.w", Viewports[i].width); m_pSerialiser->Serialise("GL_VIEWPORT.h", Viewports[i].height); } for(size_t i=0; i < ARRAY_COUNT(Scissors); i++) { m_pSerialiser->Serialise("GL_SCISSOR.x", Scissors[i].x); m_pSerialiser->Serialise("GL_SCISSOR.y", Scissors[i].y); m_pSerialiser->Serialise("GL_SCISSOR.w", Scissors[i].width); m_pSerialiser->Serialise("GL_SCISSOR.h", Scissors[i].height); m_pSerialiser->Serialise("GL_SCISSOR.enabled", Scissors[i].enabled); } m_pSerialiser->Serialise<8>("GL_DRAW_BUFFERS", DrawBuffers); m_pSerialiser->Serialise("GL_READ_BUFFER", ReadBuffer); m_pSerialiser->Serialise("GL_FRAGMENT_SHADER_DERIVATIVE_HINT", Hints.Derivatives); m_pSerialiser->Serialise("GL_LINE_SMOOTH_HINT", Hints.LineSmooth); m_pSerialiser->Serialise("GL_POLYGON_SMOOTH_HINT", Hints.PolySmooth); m_pSerialiser->Serialise("GL_TEXTURE_COMPRESSION_HINT", Hints.TexCompression); m_pSerialiser->Serialise("GL_DEPTH_WRITEMASK", DepthWriteMask); m_pSerialiser->Serialise("GL_DEPTH_CLEAR_VALUE", DepthClearValue); m_pSerialiser->Serialise("GL_DEPTH_FUNC", DepthFunc); for(size_t i=0; i < ARRAY_COUNT(DepthRanges); i++) { m_pSerialiser->Serialise("GL_DEPTH_RANGE.near", DepthRanges[i].nearZ); m_pSerialiser->Serialise("GL_DEPTH_RANGE.far", DepthRanges[i].farZ); } { m_pSerialiser->Serialise("GL_DEPTH_BOUNDS_EXT.near", DepthBounds.nearZ); m_pSerialiser->Serialise("GL_DEPTH_BOUNDS_EXT.far", DepthBounds.farZ); } { m_pSerialiser->Serialise("GL_STENCIL_FUNC", StencilFront.func); m_pSerialiser->Serialise("GL_STENCIL_BACK_FUNC", StencilBack.func); m_pSerialiser->Serialise("GL_STENCIL_REF", StencilFront.ref); m_pSerialiser->Serialise("GL_STENCIL_BACK_REF", StencilBack.ref); m_pSerialiser->Serialise("GL_STENCIL_VALUE_MASK", StencilFront.valuemask); m_pSerialiser->Serialise("GL_STENCIL_BACK_VALUE_MASK", StencilBack.valuemask); m_pSerialiser->Serialise("GL_STENCIL_WRITEMASK", StencilFront.writemask); m_pSerialiser->Serialise("GL_STENCIL_BACK_WRITEMASK", StencilBack.writemask); m_pSerialiser->Serialise("GL_STENCIL_FAIL", StencilFront.stencilFail); m_pSerialiser->Serialise("GL_STENCIL_BACK_FAIL", StencilBack.stencilFail); m_pSerialiser->Serialise("GL_STENCIL_PASS_DEPTH_FAIL", StencilFront.depthFail); m_pSerialiser->Serialise("GL_STENCIL_BACK_PASS_DEPTH_FAIL", StencilBack.depthFail); m_pSerialiser->Serialise("GL_STENCIL_PASS_DEPTH_PASS", StencilFront.pass); m_pSerialiser->Serialise("GL_STENCIL_BACK_PASS_DEPTH_PASS", StencilBack.pass); } m_pSerialiser->Serialise("GL_STENCIL_CLEAR_VALUE", StencilClearValue); for(size_t i=0; i < ARRAY_COUNT(ColorMasks); i++) m_pSerialiser->Serialise<4>("GL_COLOR_WRITEMASK", &ColorMasks[i].red); m_pSerialiser->Serialise<2>("GL_SAMPLE_MASK_VALUE", &SampleMask[0]); m_pSerialiser->Serialise("GL_SAMPLE_COVERAGE_VALUE", SampleCoverage); m_pSerialiser->Serialise("GL_SAMPLE_COVERAGE_INVERT", SampleCoverageInvert); m_pSerialiser->Serialise("GL_MIN_SAMPLE_SHADING", MinSampleShading); m_pSerialiser->Serialise("GL_RASTER_SAMPLES_EXT", RasterSamples); m_pSerialiser->Serialise("GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT", RasterFixed); m_pSerialiser->Serialise("GL_LOGIC_OP_MODE", LogicOp); m_pSerialiser->Serialise<4>("GL_COLOR_CLEAR_VALUE", &ColorClearValue.red); { m_pSerialiser->Serialise("GL_PATCH_VERTICES", PatchParams.numVerts); m_pSerialiser->Serialise<2>("GL_PATCH_DEFAULT_INNER_LEVEL", &PatchParams.defaultInnerLevel[0]); m_pSerialiser->Serialise<4>("GL_PATCH_DEFAULT_OUTER_LEVEL", &PatchParams.defaultOuterLevel[0]); } m_pSerialiser->Serialise("GL_POLYGON_MODE", PolygonMode); m_pSerialiser->Serialise("GL_POLYGON_OFFSET_FACTOR", PolygonOffset[0]); m_pSerialiser->Serialise("GL_POLYGON_OFFSET_UNITS", PolygonOffset[1]); m_pSerialiser->Serialise("GL_POLYGON_OFFSET_CLAMP_EXT", PolygonOffset[2]); m_pSerialiser->Serialise("GL_FRONT_FACE", FrontFace); m_pSerialiser->Serialise("GL_CULL_FACE_MODE", CullFace); }
void WrappedOpenGL::glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) { m_Real.glUseProgramStages(pipeline, stages, program); if(m_State > WRITING) { SCOPED_SERIALISE_CONTEXT(USE_PROGRAMSTAGES); Serialise_glUseProgramStages(pipeline, stages, program); GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ProgramPipeRes(GetCtx(), pipeline)); RDCASSERT(record); Chunk *chunk = scope.Get(); if(m_State == WRITING_CAPFRAME) { m_ContextRecord->AddChunk(chunk); } else { // USE_PROGRAMSTAGES is one of the few kinds of chunk that are // recorded to pipeline records, so we can probably find previous // uses (if it's been constantly rebound instead of once at init // time) that can be popped as redundant. // We do have to be careful though to make sure we only remove // redundant calls, not other different USE_PROGRAMSTAGES calls! struct FilterChunkClass { FilterChunkClass(uint32_t s) : stages(s) {} uint32_t stages; // this is kind of a hack, but it would be really awkward // to make a general solution just for this one case, and // we also can't really afford to drop it entirely. // we search for the marker serialised above, skip over the // pipeline id (as it will be the same in all chunks in this // record), and check if the Stages bitfield afterwards is // the same - if so we remove that chunk as replaced by // this one bool operator()(Chunk *c) const { if(c->GetChunkType() != USE_PROGRAMSTAGES) return false; byte *b = c->GetData(); byte *end = b + c->GetLength(); // 'fast' path, rather than searching byte-by-byte from // the start to be safe, check the exact difference it should // always be first. if(*(uint64_t *)(b + 6) == marker_glUseProgramStages_hack) b += 6; while(b + sizeof(uint64_t) < end) { uint64_t *marker = (uint64_t *)b; if(*marker == marker_glUseProgramStages_hack) { // increment to point to pipeline id marker++; // increment to point to stages field marker++; // now compare uint32_t *chunkStages = (uint32_t *)marker; if(*chunkStages == stages) return true; return false; } b++; } RDCERR( "Didn't find marker value! This should not happen, check " "Serialise_glUseProgramStages serialisation"); return false; } }; record->FilterChunks(FilterChunkClass(stages)); record->AddChunk(chunk); } if(program) { GLResourceRecord *progrecord = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), program)); RDCASSERT(progrecord); record->AddParent(progrecord); } } else { if(program) { ResourceId pipeID = GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), pipeline)); ResourceId progID = GetResourceManager()->GetID(ProgramRes(GetCtx(), program)); PipelineData &pipeDetails = m_Pipelines[pipeID]; ProgramData &progDetails = m_Programs[progID]; for(size_t s = 0; s < 6; s++) { if(stages & ShaderBit(s)) { for(size_t sh = 0; sh < progDetails.shaders.size(); sh++) { if(m_Shaders[progDetails.shaders[sh]].type == ShaderEnum(s)) { pipeDetails.stagePrograms[s] = progID; pipeDetails.stageShaders[s] = progDetails.shaders[sh]; break; } } } } } else { ResourceId pipeID = GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), pipeline)); PipelineData &pipeDetails = m_Pipelines[pipeID]; for(size_t s = 0; s < 6; s++) { if(stages & ShaderBit(s)) { pipeDetails.stagePrograms[s] = ResourceId(); pipeDetails.stageShaders[s] = ResourceId(); } } } } }
bool WrappedOpenGL::Serialise_glObjectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label) { ResourceId liveid; bool extvariant = false; string Label; if(m_State >= WRITING) { if(length == 0) Label = ""; else Label = string(label, label + (length > 0 ? length : strlen(label))); switch(identifier) { case eGL_TEXTURE: liveid = GetResourceManager()->GetID(TextureRes(GetCtx(), name)); break; case eGL_BUFFER_OBJECT_EXT: extvariant = true; case eGL_BUFFER: liveid = GetResourceManager()->GetID(BufferRes(GetCtx(), name)); break; case eGL_PROGRAM_OBJECT_EXT: extvariant = true; case eGL_PROGRAM: liveid = GetResourceManager()->GetID(ProgramRes(GetCtx(), name)); break; case eGL_PROGRAM_PIPELINE_OBJECT_EXT: extvariant = true; case eGL_PROGRAM_PIPELINE: liveid = GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), name)); break; case eGL_VERTEX_ARRAY_OBJECT_EXT: extvariant = true; case eGL_VERTEX_ARRAY: liveid = GetResourceManager()->GetID(VertexArrayRes(GetCtx(), name)); break; case eGL_SHADER_OBJECT_EXT: extvariant = true; case eGL_SHADER: liveid = GetResourceManager()->GetID(ShaderRes(GetCtx(), name)); break; case eGL_QUERY_OBJECT_EXT: extvariant = true; case eGL_QUERY: liveid = GetResourceManager()->GetID(QueryRes(GetCtx(), name)); break; case eGL_TRANSFORM_FEEDBACK: liveid = GetResourceManager()->GetID(FeedbackRes(GetCtx(), name)); break; case eGL_SAMPLER: liveid = GetResourceManager()->GetID(SamplerRes(GetCtx(), name)); break; case eGL_RENDERBUFFER: liveid = GetResourceManager()->GetID(RenderbufferRes(GetCtx(), name)); break; case eGL_FRAMEBUFFER: liveid = GetResourceManager()->GetID(FramebufferRes(GetCtx(), name)); break; default: RDCERR("Unhandled namespace in glObjectLabel"); } } SERIALISE_ELEMENT(GLenum, Identifier, identifier); SERIALISE_ELEMENT(ResourceId, id, liveid); SERIALISE_ELEMENT(uint32_t, Length, length); SERIALISE_ELEMENT(bool, HasLabel, label != NULL); m_pSerialiser->SerialiseString("label", Label); if(m_State == READING && GetResourceManager()->HasLiveResource(id)) { GLResource res = GetResourceManager()->GetLiveResource(id); if(extvariant && m_Real.glLabelObjectEXT) m_Real.glLabelObjectEXT(Identifier, res.name, Length, HasLabel ? Label.c_str() : NULL); else m_Real.glObjectLabel(Identifier, res.name, Length, HasLabel ? Label.c_str() : NULL); } return true; }
bool WrappedOpenGL::Serialise_glObjectLabel(SerialiserType &ser, GLenum identifier, GLuint name, GLsizei length, const GLchar *label) { GLResource Resource; std::string Label; if(ser.IsWriting()) { // we share implementations between KHR_debug and EXT_debug_label, however KHR_debug follows the // pattern elsewhere (e.g. in glShaderSource) of a length of -1 meaning indeterminate // NULL-terminated length, but EXT_debug_label takes length of 0 to mean that. GLsizei realLength = length; if(gl_CurChunk == GLChunk::glLabelObjectEXT && length == 0) realLength = -1; // if length is negative (after above twiddling), it's taken from strlen and the label must be // NULL-terminated if(realLength < 0) realLength = label ? (GLsizei)strlen(label) : 0; if(realLength == 0 || label == NULL) Label = ""; else Label = std::string(label, label + realLength); switch(identifier) { case eGL_TEXTURE: Resource = TextureRes(GetCtx(), name); break; case eGL_BUFFER_OBJECT_EXT: case eGL_BUFFER: Resource = BufferRes(GetCtx(), name); break; case eGL_PROGRAM_OBJECT_EXT: case eGL_PROGRAM: Resource = ProgramRes(GetCtx(), name); break; case eGL_PROGRAM_PIPELINE_OBJECT_EXT: case eGL_PROGRAM_PIPELINE: Resource = ProgramPipeRes(GetCtx(), name); break; case eGL_VERTEX_ARRAY_OBJECT_EXT: case eGL_VERTEX_ARRAY: Resource = VertexArrayRes(GetCtx(), name); break; case eGL_SHADER_OBJECT_EXT: case eGL_SHADER: Resource = ShaderRes(GetCtx(), name); break; case eGL_QUERY_OBJECT_EXT: case eGL_QUERY: Resource = QueryRes(GetCtx(), name); break; case eGL_TRANSFORM_FEEDBACK: Resource = FeedbackRes(GetCtx(), name); break; case eGL_SAMPLER: Resource = SamplerRes(GetCtx(), name); break; case eGL_RENDERBUFFER: Resource = RenderbufferRes(GetCtx(), name); break; case eGL_FRAMEBUFFER: Resource = FramebufferRes(GetCtx(), name); break; default: RDCERR("Unhandled namespace in glObjectLabel"); } } SERIALISE_ELEMENT(Resource); SERIALISE_ELEMENT(length); SERIALISE_ELEMENT(Label); SERIALISE_CHECK_READ_ERRORS(); if(IsReplayingAndReading() && Resource.name) { ResourceId origId = GetResourceManager()->GetOriginalID(GetResourceManager()->GetID(Resource)); GetResourceManager()->SetName(origId, Label); ResourceDescription &descr = GetReplay()->GetResourceDesc(origId); descr.SetCustomName(Label); AddResourceCurChunk(descr); } return true; }