void WrappedOpenGL::glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) { m_Real.glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth); if(m_State >= WRITING) { GLResourceRecord *srcrecord = GetResourceManager()->GetResourceRecord(TextureRes(srcName)); GLResourceRecord *dstrecord = GetResourceManager()->GetResourceRecord(TextureRes(dstName)); RDCASSERT(srcrecord && dstrecord); SCOPED_SERIALISE_CONTEXT(COPY_SUBIMAGE); Serialise_glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth); Chunk *chunk = scope.Get(); if(m_State == WRITING_CAPFRAME) { m_ContextRecord->AddChunk(chunk); } else { dstrecord->AddChunk(chunk); dstrecord->AddParent(srcrecord); } } }
void WrappedOpenGL::glAttachShader(GLuint program, GLuint shader) { m_Real.glAttachShader(program, shader); if(m_State >= WRITING && program != 0 && shader != 0) { GLResourceRecord *progRecord = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), program)); GLResourceRecord *shadRecord = GetResourceManager()->GetResourceRecord(ShaderRes(GetCtx(), shader)); RDCASSERT(progRecord && shadRecord); if(progRecord && shadRecord) { SCOPED_SERIALISE_CONTEXT(ATTACHSHADER); Serialise_glAttachShader(program, shader); progRecord->AddParent(shadRecord); progRecord->AddChunk(scope.Get()); } } else { ResourceId progid = GetResourceManager()->GetID(ProgramRes(GetCtx(), program)); ResourceId shadid = GetResourceManager()->GetID(ShaderRes(GetCtx(), shader)); m_Programs[progid].shaders.push_back(shadid); } }
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 WrappedOpenGL::glTextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) { m_Real.glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), texture)); GLResourceRecord *origrecord = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), origtexture)); RDCASSERT(record && origrecord); SCOPED_SERIALISE_CONTEXT(TEXTURE_VIEW); Serialise_glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers); record->AddChunk(scope.Get()); record->AddParent(origrecord); // illegal to re-type textures if(record->datatype == eGL_UNKNOWN_ENUM) record->datatype = target; else RDCASSERT(record->datatype == target); } }
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(); } } } } }