Files
renderdoc/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp
T

3517 lines
102 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "common/common.h"
#include "serialise/string_utils.h"
#include "../gl_driver.h"
bool WrappedOpenGL::Serialise_glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z)
{
SERIALISE_ELEMENT(uint32_t, X, num_groups_x);
SERIALISE_ELEMENT(uint32_t, Y, num_groups_y);
SERIALISE_ELEMENT(uint32_t, Z, num_groups_z);
if(m_State <= EXECUTING)
{
m_Real.glDispatchCompute(X, Y, Z);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DISPATCH_COMPUTE, desc);
string name = "glDispatchCompute(" +
ToStr::Get(X) + ", " +
ToStr::Get(Y) + ", " +
ToStr::Get(Z) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_Dispatch;
draw.dispatchDimension[0] = X;
draw.dispatchDimension[1] = Y;
draw.dispatchDimension[2] = Z;
if(X == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Num Groups X=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean X=1?");
if(Y == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Num Groups Y=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean Y=1?");
if(Z == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Num Groups Z=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean Z=1?");
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z)
{
CoherentMapImplicitBarrier();
m_Real.glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DISPATCH_COMPUTE);
Serialise_glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDispatchComputeGroupSizeARB(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z)
{
SERIALISE_ELEMENT(uint32_t, X, num_groups_x);
SERIALISE_ELEMENT(uint32_t, Y, num_groups_y);
SERIALISE_ELEMENT(uint32_t, Z, num_groups_z);
SERIALISE_ELEMENT(uint32_t, sX, group_size_x);
SERIALISE_ELEMENT(uint32_t, sY, group_size_y);
SERIALISE_ELEMENT(uint32_t, sZ, group_size_z);
if(m_State <= EXECUTING)
{
m_Real.glDispatchComputeGroupSizeARB(X, Y, Z, sX, sY, sZ);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DISPATCH_COMPUTE, desc);
string name = "glDispatchComputeGroupSizeARB(" +
ToStr::Get(X) + ", " +
ToStr::Get(Y) + ", " +
ToStr::Get(Z) + ", " +
ToStr::Get(sX) + ", " +
ToStr::Get(sY) + ", " +
ToStr::Get(sZ) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_Dispatch;
draw.dispatchDimension[0] = X;
draw.dispatchDimension[1] = Y;
draw.dispatchDimension[2] = Z;
draw.dispatchThreadsDimension[0] = sX;
draw.dispatchThreadsDimension[1] = sY;
draw.dispatchThreadsDimension[2] = sZ;
if(X == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Num Groups X=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean X=1?");
if(Y == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Num Groups Y=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean Y=1?");
if(Z == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Num Groups Z=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean Z=1?");
if(sX == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Group Size X=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean X=1?");
if(sY == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Group Size Y=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean Y=1?");
if(sZ == 0)
AddDebugMessage(eDbgCategory_Execution, eDbgSeverity_Medium, eDbgSource_IncorrectAPIUse,
"Dispatch call has Group Size Z=0. This will do nothing, which is unusual for a non-indirect Dispatch. Did you mean Z=1?");
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDispatchComputeGroupSizeARB(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z)
{
CoherentMapImplicitBarrier();
m_Real.glDispatchComputeGroupSizeARB(num_groups_x, num_groups_y, num_groups_z, group_size_x, group_size_y, group_size_z);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DISPATCH_COMPUTE_GROUP_SIZE);
Serialise_glDispatchComputeGroupSizeARB(num_groups_x, num_groups_y, num_groups_z, group_size_x, group_size_y, group_size_z);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDispatchComputeIndirect(GLintptr indirect)
{
SERIALISE_ELEMENT(uint64_t, offs, indirect);
if(m_State <= EXECUTING)
{
m_Real.glDispatchComputeIndirect((GLintptr)offs);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
uint32_t groupSizes[3];
m_Real.glGetBufferSubData(eGL_DISPATCH_INDIRECT_BUFFER, (GLintptr)offs, sizeof(uint32_t)*3, groupSizes);
AddEvent(DISPATCH_COMPUTE_INDIRECT, desc);
string name = "glDispatchComputeIndirect(<" +
ToStr::Get(groupSizes[0]) + ", " +
ToStr::Get(groupSizes[1]) + ", " +
ToStr::Get(groupSizes[2]) + ">)";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_Dispatch|eDraw_Indirect;
draw.dispatchDimension[0] = groupSizes[0];
draw.dispatchDimension[1] = groupSizes[1];
draw.dispatchDimension[2] = groupSizes[2];
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDispatchComputeIndirect(GLintptr indirect)
{
CoherentMapImplicitBarrier();
m_Real.glDispatchComputeIndirect(indirect);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DISPATCH_COMPUTE_INDIRECT);
Serialise_glDispatchComputeIndirect(indirect);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMemoryBarrier(GLbitfield barriers)
{
SERIALISE_ELEMENT(uint32_t, Barriers, barriers);
if(m_State <= EXECUTING)
{
m_Real.glMemoryBarrier(Barriers);
}
return true;
}
void WrappedOpenGL::glMemoryBarrier(GLbitfield barriers)
{
if(barriers & GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT)
{
// perform a forced flush of all persistent mapped buffers,
// coherent or not.
PersistentMapMemoryBarrier(m_PersistentMaps);
}
m_Real.glMemoryBarrier(barriers);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MEMORY_BARRIER);
Serialise_glMemoryBarrier(barriers);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMemoryBarrierByRegion(GLbitfield barriers)
{
SERIALISE_ELEMENT(uint32_t, Barriers, barriers);
if(m_State <= EXECUTING)
{
m_Real.glMemoryBarrierByRegion(Barriers);
}
return true;
}
void WrappedOpenGL::glMemoryBarrierByRegion(GLbitfield barriers)
{
if(barriers & GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT)
{
// perform a forced flush of all persistent mapped buffers,
// coherent or not.
PersistentMapMemoryBarrier(m_PersistentMaps);
}
m_Real.glMemoryBarrierByRegion(barriers);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MEMORY_BARRIER_BY_REGION);
Serialise_glMemoryBarrierByRegion(barriers);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glTextureBarrier()
{
if(m_State <= EXECUTING)
{
m_Real.glTextureBarrier();
}
return true;
}
void WrappedOpenGL::glTextureBarrier()
{
CoherentMapImplicitBarrier();
m_Real.glTextureBarrier();
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(TEXTURE_BARRIER);
Serialise_glTextureBarrier();
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawTransformFeedback(GLenum mode, GLuint id)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(ResourceId, fid, GetResourceManager()->GetID(FeedbackRes(GetCtx(), id)));
if(m_State <= EXECUTING)
{
m_Real.glDrawTransformFeedback(Mode, fid == ResourceId() ? 0 : GetResourceManager()->GetLiveResource(fid).name);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAW_FEEDBACK, desc);
string name = "glDrawTransformFeedback(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ")";
RDCUNIMPLEMENTED("Not fetching feedback object count for glDrawTransformFeedback() display");
FetchDrawcall draw;
draw.name = name;
draw.numIndices = 1;
draw.numInstances = 1;
draw.indexOffset = 0;
draw.vertexOffset = 0;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawTransformFeedback(GLenum mode, GLuint id)
{
CoherentMapImplicitBarrier();
m_Real.glDrawTransformFeedback(mode, id);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAW_FEEDBACK);
Serialise_glDrawTransformFeedback(mode, id);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawTransformFeedbackInstanced(GLenum mode, GLuint id, GLsizei instancecount)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(ResourceId, fid, GetResourceManager()->GetID(FeedbackRes(GetCtx(), id)));
SERIALISE_ELEMENT(uint32_t, Count, instancecount);
if(m_State <= EXECUTING)
{
m_Real.glDrawTransformFeedbackInstanced(Mode, fid == ResourceId() ? 0 : GetResourceManager()->GetLiveResource(fid).name, Count);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAW_FEEDBACK_INSTANCED, desc);
string name = "glDrawTransformFeedbackInstanced(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ")";
RDCUNIMPLEMENTED("Not fetching feedback object count for glDrawTransformFeedbackInstanced() display");
FetchDrawcall draw;
draw.name = name;
draw.numIndices = 1;
draw.numInstances = 1;
draw.indexOffset = 0;
draw.vertexOffset = 0;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawTransformFeedbackInstanced(GLenum mode, GLuint id, GLsizei instancecount)
{
CoherentMapImplicitBarrier();
m_Real.glDrawTransformFeedbackInstanced(mode, id, instancecount);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAW_FEEDBACK_INSTANCED);
Serialise_glDrawTransformFeedbackInstanced(mode, id, instancecount);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawTransformFeedbackStream(GLenum mode, GLuint id, GLuint stream)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(ResourceId, fid, GetResourceManager()->GetID(FeedbackRes(GetCtx(), id)));
SERIALISE_ELEMENT(uint32_t, Stream, stream);
if(m_State <= EXECUTING)
{
m_Real.glDrawTransformFeedbackStream(Mode, fid == ResourceId() ? 0 : GetResourceManager()->GetLiveResource(fid).name, Stream);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAW_FEEDBACK_STREAM, desc);
string name = "glDrawTransformFeedbackStream(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ")";
RDCUNIMPLEMENTED("Not fetching feedback object count for glDrawTransformFeedbackStream() display");
FetchDrawcall draw;
draw.name = name;
draw.numIndices = 1;
draw.numInstances = 1;
draw.indexOffset = 0;
draw.vertexOffset = 0;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawTransformFeedbackStream(GLenum mode, GLuint id, GLuint stream)
{
CoherentMapImplicitBarrier();
m_Real.glDrawTransformFeedbackStream(mode, id, stream);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAW_FEEDBACK_STREAM);
Serialise_glDrawTransformFeedbackStream(mode, id, stream);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawTransformFeedbackStreamInstanced(GLenum mode, GLuint id, GLuint stream, GLsizei instancecount)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(ResourceId, fid, GetResourceManager()->GetID(FeedbackRes(GetCtx(), id)));
SERIALISE_ELEMENT(uint32_t, Stream, stream);
SERIALISE_ELEMENT(uint32_t, Count, instancecount);
if(m_State <= EXECUTING)
{
m_Real.glDrawTransformFeedbackStreamInstanced(Mode, fid == ResourceId() ? 0 : GetResourceManager()->GetLiveResource(fid).name, Stream, Count);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAW_FEEDBACK_STREAM_INSTANCED, desc);
string name = "glDrawTransformFeedbackStreamInstanced(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ")";
RDCUNIMPLEMENTED("Not fetching feedback object count for glDrawTransformFeedbackStreamInstanced() display");
FetchDrawcall draw;
draw.name = name;
draw.numIndices = 1;
draw.numInstances = 1;
draw.indexOffset = 0;
draw.vertexOffset = 0;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawTransformFeedbackStreamInstanced(GLenum mode, GLuint id, GLuint stream, GLsizei instancecount)
{
CoherentMapImplicitBarrier();
m_Real.glDrawTransformFeedbackStreamInstanced(mode, id, stream, instancecount);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAW_FEEDBACK_STREAM_INSTANCED);
Serialise_glDrawTransformFeedbackStreamInstanced(mode, id, stream, instancecount);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(int32_t, First, first);
SERIALISE_ELEMENT(uint32_t, Count, count);
if(m_State <= EXECUTING)
{
m_Real.glDrawArrays(Mode, First, Count);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWARRAYS, desc);
string name = "glDrawArrays(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(First) + ", " +
ToStr::Get(Count) + ")";
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = 1;
draw.indexOffset = 0;
draw.vertexOffset = First;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
CoherentMapImplicitBarrier();
m_Real.glDrawArrays(mode, first, count);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWARRAYS);
Serialise_glDrawArrays(mode, first, count);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawArraysIndirect(GLenum mode, const void *indirect)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)indirect);
if(m_State <= EXECUTING)
{
m_Real.glDrawArraysIndirect(Mode, (const void *)Offset);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
DrawArraysIndirectCommand params;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, (GLintptr)Offset, sizeof(params), &params);
AddEvent(DRAWARRAYS_INDIRECT, desc);
string name = "glDrawArraysIndirect(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", <" +
ToStr::Get(params.first) + ", " +
ToStr::Get(params.count) + ", " +
ToStr::Get(params.instanceCount) + ", " +
ToStr::Get(params.baseInstance) + ">)";
FetchDrawcall draw;
draw.name = name;
draw.numIndices = params.count;
draw.numInstances = params.instanceCount;
draw.vertexOffset = params.first;
draw.instanceOffset = params.baseInstance;
draw.flags |= eDraw_Drawcall|eDraw_Instanced|eDraw_Indirect;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawArraysIndirect(GLenum mode, const void *indirect)
{
CoherentMapImplicitBarrier();
m_Real.glDrawArraysIndirect(mode, indirect);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWARRAYS_INDIRECT);
Serialise_glDrawArraysIndirect(mode, indirect);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(int32_t, First, first);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(uint32_t, InstanceCount, instancecount);
if(m_State <= EXECUTING)
{
m_Real.glDrawArraysInstanced(Mode, First, Count, InstanceCount);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWARRAYS_INSTANCED, desc);
string name = "glDrawArraysInstanced(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(First) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(InstanceCount) + ")";
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = InstanceCount;
draw.indexOffset = 0;
draw.vertexOffset = First;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall|eDraw_Instanced;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount)
{
CoherentMapImplicitBarrier();
m_Real.glDrawArraysInstanced(mode, first, count, instancecount);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWARRAYS_INSTANCED);
Serialise_glDrawArraysInstanced(mode, first, count, instancecount);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(int32_t, First, first);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(uint32_t, InstanceCount, instancecount);
SERIALISE_ELEMENT(uint32_t, BaseInstance, baseinstance);
if(m_State <= EXECUTING)
{
m_Real.glDrawArraysInstancedBaseInstance(Mode, First, Count, InstanceCount, BaseInstance);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWARRAYS_INSTANCEDBASEINSTANCE, desc);
string name = "glDrawArraysInstancedBaseInstance(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(First) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(InstanceCount) + ", " +
ToStr::Get(BaseInstance) + ")";
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = InstanceCount;
draw.indexOffset = 0;
draw.vertexOffset = First;
draw.instanceOffset = BaseInstance;
draw.flags |= eDraw_Drawcall|eDraw_Instanced;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance)
{
CoherentMapImplicitBarrier();
m_Real.glDrawArraysInstancedBaseInstance(mode, first, count, instancecount, baseinstance);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWARRAYS_INSTANCEDBASEINSTANCE);
Serialise_glDrawArraysInstancedBaseInstance(mode, first, count, instancecount, baseinstance);
m_ContextRecord->AddChunk(scope.Get());
}
}
byte *WrappedOpenGL::Common_preElements(GLsizei Count, GLenum Type, uint64_t &IdxOffset)
{
GLint idxbuf = 0;
// while writing, check to see if an index buffer is bound
if(m_State >= WRITING)
m_Real.glGetIntegerv(eGL_ELEMENT_ARRAY_BUFFER_BINDING, &idxbuf);
// serialise whether we're reading indices as memory
SERIALISE_ELEMENT(bool, IndicesFromMemory, idxbuf == 0);
if(IndicesFromMemory)
{
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
// serialise the actual data (IdxOffset is a pointer not an offset in this case)
SERIALISE_ELEMENT_BUF(byte *, idxdata, (void *)IdxOffset, size_t(IdxSize*Count));
if(m_State <= EXECUTING)
{
GLsizeiptr idxlen = GLsizeiptr(IdxSize*Count);
// resize fake index buffer if necessary
if(idxlen > m_FakeIdxSize)
{
m_Real.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, 0);
m_Real.glDeleteBuffers(1, &m_FakeIdxBuf);
m_FakeIdxSize = idxlen;
m_Real.glGenBuffers(1, &m_FakeIdxBuf);
m_Real.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, m_FakeIdxBuf);
m_Real.glNamedBufferStorageEXT(m_FakeIdxBuf, m_FakeIdxSize, NULL, GL_DYNAMIC_STORAGE_BIT);
}
// bind and update fake index buffer, to draw from the 'immediate' index data
m_Real.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, m_FakeIdxBuf);
m_Real.glNamedBufferSubDataEXT(m_FakeIdxBuf, 0, idxlen, idxdata);
// Set offset to 0 - means we read data from start of our fake index buffer
IdxOffset = 0;
// we'll delete this later (only when replaying)
return idxdata;
}
// can just return NULL, since we don't need to do any cleanup or deletion
}
return NULL;
}
void WrappedOpenGL::Common_postElements(byte *idxDelete)
{
// unbind temporary fake index buffer we used to pass 'immediate' index data
if(idxDelete)
{
m_Real.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, 0);
AddDebugMessage(eDbgCategory_Deprecated, eDbgSeverity_High, eDbgSource_IncorrectAPIUse,
"Assuming GL core profile is used then specifying indices as a raw array, "
"not as offset into element array buffer, is illegal.");
// delete serialised data
SAFE_DELETE_ARRAY(idxDelete);
}
}
bool WrappedOpenGL::Serialise_glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, IdxOffset, (uint64_t)indices);
byte *idxDelete = Common_preElements(Count, Type, IdxOffset);
if(m_State <= EXECUTING)
{
m_Real.glDrawElements(Mode, Count, Type, (const void *)IdxOffset);
Common_postElements(idxDelete);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWELEMENTS, desc);
string name = "glDrawElements(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(Type) + ", " +
ToStr::Get(IdxOffset) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = 1;
draw.indexOffset = uint32_t(IdxOffset)/IdxSize;
draw.vertexOffset = 0;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
{
CoherentMapImplicitBarrier();
m_Real.glDrawElements(mode, count, type, indices);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWELEMENTS);
Serialise_glDrawElements(mode, count, type, indices);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)indirect);
if(m_State <= EXECUTING)
{
m_Real.glDrawElementsIndirect(Mode, Type, (const void *)Offset);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
DrawElementsIndirectCommand params;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, (GLintptr)Offset, sizeof(params), &params);
AddEvent(DRAWELEMENTS_INDIRECT, desc);
string name = "glDrawElementsIndirect(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Type) + ", <" +
ToStr::Get(params.count) + ", " +
ToStr::Get(params.instanceCount) + ", " +
ToStr::Get(params.baseVertex) + ", " +
ToStr::Get(params.baseInstance) + ">)";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = params.count;
draw.numInstances = params.instanceCount;
draw.indexOffset = params.firstIndex;
draw.vertexOffset = params.baseVertex;
draw.instanceOffset = params.baseInstance;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer|eDraw_Instanced|eDraw_Indirect;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
{
CoherentMapImplicitBarrier();
m_Real.glDrawElementsIndirect(mode, type, indirect);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWELEMENTS_INDIRECT);
Serialise_glDrawElementsIndirect(mode, type, indirect);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Start, start);
SERIALISE_ELEMENT(uint32_t, End, end);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, IdxOffset, (uint64_t)indices);
byte *idxDelete = Common_preElements(Count, Type, IdxOffset);
if(m_State <= EXECUTING)
{
m_Real.glDrawRangeElements(Mode, Start, End, Count, Type, (const void *)IdxOffset);
Common_postElements(idxDelete);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWRANGEELEMENTS, desc);
string name = "glDrawRangeElements(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(Type) + ", " +
ToStr::Get(IdxOffset) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = 1;
draw.indexOffset = uint32_t(IdxOffset)/IdxSize;
draw.vertexOffset = 0;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices)
{
CoherentMapImplicitBarrier();
m_Real.glDrawRangeElements(mode, start, end, count, type, indices);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWRANGEELEMENTS);
Serialise_glDrawRangeElements(mode, start, end, count, type, indices);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Start, start);
SERIALISE_ELEMENT(uint32_t, End, end);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, IdxOffset, (uint64_t)indices);
SERIALISE_ELEMENT(uint32_t, BaseVtx, basevertex);
byte *idxDelete = Common_preElements(Count, Type, IdxOffset);
if(m_State <= EXECUTING)
{
m_Real.glDrawRangeElementsBaseVertex(Mode, Start, End, Count, Type, (const void *)IdxOffset, BaseVtx);
Common_postElements(idxDelete);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWRANGEELEMENTSBASEVERTEX, desc);
string name = "glDrawRangeElementsBaseVertex(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(Type) + ", " +
ToStr::Get(IdxOffset) + ", " +
ToStr::Get(BaseVtx) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = 1;
draw.indexOffset = uint32_t(IdxOffset)/IdxSize;
draw.vertexOffset = BaseVtx;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
{
CoherentMapImplicitBarrier();
m_Real.glDrawRangeElementsBaseVertex(mode, start, end, count, type, indices, basevertex);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWRANGEELEMENTSBASEVERTEX);
Serialise_glDrawRangeElementsBaseVertex(mode, start, end, count, type, indices, basevertex);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, IdxOffset, (uint64_t)indices);
SERIALISE_ELEMENT(int32_t, BaseVtx, basevertex);
byte *idxDelete = Common_preElements(Count, Type, IdxOffset);
if(m_State <= EXECUTING)
{
m_Real.glDrawElementsBaseVertex(Mode, Count, Type, (const void *)IdxOffset, BaseVtx);
Common_postElements(idxDelete);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWELEMENTS_BASEVERTEX, desc);
string name = "glDrawElementsBaseVertex(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(Type) + ", " +
ToStr::Get(IdxOffset) + ", " +
ToStr::Get(BaseVtx) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = 1;
draw.indexOffset = uint32_t(IdxOffset)/IdxSize;
draw.vertexOffset = BaseVtx;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
{
CoherentMapImplicitBarrier();
m_Real.glDrawElementsBaseVertex(mode, count, type, indices, basevertex);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWELEMENTS_BASEVERTEX);
Serialise_glDrawElementsBaseVertex(mode, count, type, indices, basevertex);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, IdxOffset, (uint64_t)indices);
SERIALISE_ELEMENT(uint32_t, InstCount, instancecount);
byte *idxDelete = Common_preElements(Count, Type, IdxOffset);
if(m_State <= EXECUTING)
{
m_Real.glDrawElementsInstanced(Mode, Count, Type, (const void *)IdxOffset, InstCount);
Common_postElements(idxDelete);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWELEMENTS_INSTANCED, desc);
string name = "glDrawElementsInstanced(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(Type) + ", " +
ToStr::Get(IdxOffset) + ", " +
ToStr::Get(InstCount) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = InstCount;
draw.indexOffset = uint32_t(IdxOffset)/IdxSize;
draw.vertexOffset = 0;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount)
{
CoherentMapImplicitBarrier();
m_Real.glDrawElementsInstanced(mode, count, type, indices, instancecount);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWELEMENTS_INSTANCED);
Serialise_glDrawElementsInstanced(mode, count, type, indices, instancecount);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, IdxOffset, (uint64_t)indices);
SERIALISE_ELEMENT(uint32_t, InstCount, instancecount);
SERIALISE_ELEMENT(uint32_t, BaseInstance, baseinstance);
byte *idxDelete = Common_preElements(Count, Type, IdxOffset);
if(m_State <= EXECUTING)
{
m_Real.glDrawElementsInstancedBaseInstance(Mode, Count, Type, (const void *)IdxOffset, InstCount, BaseInstance);
Common_postElements(idxDelete);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWELEMENTS_INSTANCEDBASEINSTANCE, desc);
string name = "glDrawElementsInstancedBaseInstance(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(Type) + ", " +
ToStr::Get(IdxOffset) + ", " +
ToStr::Get(InstCount) + ", " +
ToStr::Get(BaseInstance) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = InstCount;
draw.indexOffset = uint32_t(IdxOffset)/IdxSize;
draw.vertexOffset = 0;
draw.instanceOffset = BaseInstance;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance)
{
CoherentMapImplicitBarrier();
m_Real.glDrawElementsInstancedBaseInstance(mode, count, type, indices, instancecount, baseinstance);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWELEMENTS_INSTANCEDBASEINSTANCE);
Serialise_glDrawElementsInstancedBaseInstance(mode, count, type, indices, instancecount, baseinstance);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, IdxOffset, (uint64_t)indices);
SERIALISE_ELEMENT(uint32_t, InstCount, instancecount);
SERIALISE_ELEMENT(int32_t, BaseVertex, basevertex);
byte *idxDelete = Common_preElements(Count, Type, IdxOffset);
if(m_State <= EXECUTING)
{
m_Real.glDrawElementsInstancedBaseVertex(Mode, Count, Type, (const void *)IdxOffset, InstCount, BaseVertex);
Common_postElements(idxDelete);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWELEMENTS_INSTANCEDBASEVERTEX, desc);
string name = "glDrawElementsInstancedBaseVertex(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(Type) + ", " +
ToStr::Get(IdxOffset) + ", " +
ToStr::Get(InstCount) + ", " +
ToStr::Get(BaseVertex) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = InstCount;
draw.indexOffset = uint32_t(IdxOffset)/IdxSize;
draw.vertexOffset = BaseVertex;
draw.instanceOffset = 0;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
{
CoherentMapImplicitBarrier();
m_Real.glDrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWELEMENTS_INSTANCEDBASEVERTEX);
Serialise_glDrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Count, count);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, IdxOffset, (uint64_t)indices);
SERIALISE_ELEMENT(uint32_t, InstCount, instancecount);
SERIALISE_ELEMENT(int32_t, BaseVertex, basevertex);
SERIALISE_ELEMENT(uint32_t, BaseInstance, baseinstance);
byte *idxDelete = Common_preElements(Count, Type, IdxOffset);
if(m_State <= EXECUTING)
{
m_Real.glDrawElementsInstancedBaseVertexBaseInstance(Mode, Count, Type, (const void *)IdxOffset, InstCount, BaseVertex, BaseInstance);
Common_postElements(idxDelete);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(DRAWELEMENTS_INSTANCEDBASEVERTEXBASEINSTANCE, desc);
string name = "glDrawElementsInstancedBaseVertexBaseInstance(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", " +
ToStr::Get(Count) + ", " +
ToStr::Get(Type) + ", " +
ToStr::Get(IdxOffset) + ", " +
ToStr::Get(InstCount) + ", " +
ToStr::Get(BaseVertex) + ", " +
ToStr::Get(BaseInstance) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.numIndices = Count;
draw.numInstances = InstCount;
draw.indexOffset = uint32_t(IdxOffset)/IdxSize;
draw.vertexOffset = BaseVertex;
draw.instanceOffset = BaseInstance;
draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, true);
}
return true;
}
void WrappedOpenGL::glDrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance)
{
CoherentMapImplicitBarrier();
m_Real.glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, basevertex, baseinstance);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAWELEMENTS_INSTANCEDBASEVERTEXBASEINSTANCE);
Serialise_glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, basevertex, baseinstance);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMultiDrawArrays(GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint32_t, Count, drawcount);
SERIALISE_ELEMENT_ARR(int32_t, firstArray, first, Count);
SERIALISE_ELEMENT_ARR(int32_t, countArray, count, Count);
if(m_State == READING)
{
m_Real.glMultiDrawArrays(Mode, firstArray, countArray, Count);
}
else if(m_State <= EXECUTING)
{
size_t i=0;
for(; i < m_Events.size(); i++)
{
if(m_Events[i].eventID >= m_CurEventID)
break;
}
while(i > 1 && m_Events[i-1].fileOffset == m_Events[i].fileOffset) i--;
uint32_t baseEventID = m_Events[i].eventID;
if(m_LastEventID < baseEventID)
{
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
// then we'll replay up to N but not N+1, so just do nothing - we DON'T want to draw
// the first sub-draw in that range.
}
else if(m_FirstEventID <= baseEventID && m_LastEventID >= baseEventID)
{
// if we're replaying part-way into a multidraw, we can replay the first part 'easily'
// by just reducing the Count parameter to however many we want to replay. This only
// works if we're replaying from the first multidraw to the nth (n less than Count)
m_Real.glMultiDrawArrays(Mode, firstArray, countArray, RDCMIN(Count, m_LastEventID - baseEventID + 1));
}
else
{
// otherwise we do the 'hard' case, draw only one multidraw
// note we'll never be asked to do e.g. 3rd-7th of a multidraw. Only ever 0th-nth or
// a single draw.
RDCASSERT(m_LastEventID == m_FirstEventID);
uint32_t drawidx = (m_LastEventID - baseEventID);
m_Real.glDrawArrays(Mode, firstArray[drawidx], countArray[drawidx]);
}
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
string name = "glMultiDrawArrays(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + "," +
ToStr::Get(Count) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_MultiDraw;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, false);
m_DrawcallStack.push_back(&m_DrawcallStack.back()->children.back());
m_CurEventID++;
for(uint32_t i=0; i < Count; i++)
{
FetchDrawcall multidraw;
multidraw.numIndices = countArray[i];
multidraw.vertexOffset = firstArray[i];
multidraw.name = "glMultiDrawArrays[" + ToStr::Get(i) + "](" +
ToStr::Get(multidraw.numIndices) + ", " +
ToStr::Get(multidraw.vertexOffset) + ")";
multidraw.flags |= eDraw_Drawcall;
multidraw.topology = MakePrimitiveTopology(m_Real, Mode);
AddEvent(MULTI_DRAWARRAYS, desc);
AddDrawcall(multidraw, true);
m_CurEventID++;
}
m_DrawcallStack.pop_back();
}
else
{
m_CurEventID += Count+1;
}
SAFE_DELETE_ARRAY(firstArray);
SAFE_DELETE_ARRAY(countArray);
return true;
}
void WrappedOpenGL::glMultiDrawArrays(GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount)
{
CoherentMapImplicitBarrier();
m_Real.glMultiDrawArrays(mode, first, count, drawcount);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MULTI_DRAWARRAYS);
Serialise_glMultiDrawArrays(mode, first, count, drawcount);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint32_t, Count, drawcount);
SERIALISE_ELEMENT_ARR(int32_t, countArray, count, Count);
void **idxOffsArray = new void*[Count];
size_t len = Count;
// serialise pointer array as uint64s
if(m_State >= WRITING)
{
for(uint32_t i=0; i < Count; i++)
{
uint64_t ptr = (uint64_t)indices[i];
m_pSerialiser->Serialise("idxOffsArray", ptr);
}
}
else
{
for(uint32_t i=0; i < Count; i++)
{
uint64_t ptr = 0;
m_pSerialiser->Serialise("idxOffsArray", ptr);
idxOffsArray[i] = (void *)ptr;
}
}
if(m_State == READING)
{
m_Real.glMultiDrawElements(Mode, countArray, Type, idxOffsArray, Count);
}
else if(m_State <= EXECUTING)
{
size_t i=0;
for(; i < m_Events.size(); i++)
{
if(m_Events[i].eventID >= m_CurEventID)
break;
}
while(i > 1 && m_Events[i-1].fileOffset == m_Events[i].fileOffset) i--;
uint32_t baseEventID = m_Events[i].eventID;
if(m_LastEventID < baseEventID)
{
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
// then we'll replay up to N but not N+1, so just do nothing - we DON'T want to draw
// the first sub-draw in that range.
}
else if(m_FirstEventID <= baseEventID && m_LastEventID >= baseEventID)
{
// if we're replaying part-way into a multidraw, we can replay the first part 'easily'
// by just reducing the Count parameter to however many we want to replay. This only
// works if we're replaying from the first multidraw to the nth (n less than Count)
m_Real.glMultiDrawElements(Mode, countArray, Type, idxOffsArray, RDCMIN(Count, m_LastEventID - baseEventID + 1));
}
else
{
// otherwise we do the 'hard' case, draw only one multidraw
// note we'll never be asked to do e.g. 3rd-7th of a multidraw. Only ever 0th-nth or
// a single draw.
RDCASSERT(m_LastEventID == m_FirstEventID);
uint32_t drawidx = (m_LastEventID - baseEventID);
m_Real.glDrawElements(Mode, countArray[drawidx], Type, idxOffsArray[drawidx]);
}
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
string name = "glMultiDrawElements(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + "," +
ToStr::Get(Type) + "," +
ToStr::Get(Count) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_MultiDraw;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, false);
m_DrawcallStack.push_back(&m_DrawcallStack.back()->children.back());
m_CurEventID++;
for(uint32_t i=0; i < Count; i++)
{
FetchDrawcall multidraw;
multidraw.numIndices = countArray[i];
multidraw.indexOffset = (uint32_t) uint64_t(idxOffsArray[i])&0xFFFFFFFF;
multidraw.name = "glMultiDrawElements[" + ToStr::Get(i) + "](" +
ToStr::Get(multidraw.numIndices) + ", " +
ToStr::Get(multidraw.indexOffset) + ")";
multidraw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
multidraw.topology = MakePrimitiveTopology(m_Real, Mode);
AddEvent(MULTI_DRAWELEMENTS, desc);
AddDrawcall(multidraw, true);
m_CurEventID++;
}
m_DrawcallStack.pop_back();
}
else
{
m_CurEventID += Count+1;
}
SAFE_DELETE_ARRAY(countArray);
SAFE_DELETE_ARRAY(idxOffsArray);
return true;
}
void WrappedOpenGL::glMultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount)
{
CoherentMapImplicitBarrier();
m_Real.glMultiDrawElements(mode, count, type, indices, drawcount);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MULTI_DRAWELEMENTS);
Serialise_glMultiDrawElements(mode, count, type, indices, drawcount);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint32_t, Count, drawcount);
SERIALISE_ELEMENT_ARR(int32_t, countArray, count, Count);
SERIALISE_ELEMENT_ARR(int32_t, baseArray, basevertex, Count);
void **idxOffsArray = new void*[Count];
size_t len = Count;
// serialise pointer array as uint64s
if(m_State >= WRITING)
{
for(uint32_t i=0; i < Count; i++)
{
uint64_t ptr = (uint64_t)indices[i];
m_pSerialiser->Serialise("idxOffsArray", ptr);
}
}
else
{
for(uint32_t i=0; i < Count; i++)
{
uint64_t ptr = 0;
m_pSerialiser->Serialise("idxOffsArray", ptr);
idxOffsArray[i] = (void *)ptr;
}
}
if(m_State == READING)
{
m_Real.glMultiDrawElementsBaseVertex(Mode, countArray, Type, idxOffsArray, Count, baseArray);
}
else if(m_State <= EXECUTING)
{
size_t i=0;
for(; i < m_Events.size(); i++)
{
if(m_Events[i].eventID >= m_CurEventID)
break;
}
while(i > 1 && m_Events[i-1].fileOffset == m_Events[i].fileOffset) i--;
uint32_t baseEventID = m_Events[i].eventID;
if(m_LastEventID < baseEventID)
{
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
// then we'll replay up to N but not N+1, so just do nothing - we DON'T want to draw
// the first sub-draw in that range.
}
else if(m_FirstEventID <= baseEventID && m_LastEventID >= baseEventID)
{
// if we're replaying part-way into a multidraw, we can replay the first part 'easily'
// by just reducing the Count parameter to however many we want to replay. This only
// works if we're replaying from the first multidraw to the nth (n less than Count)
m_Real.glMultiDrawElementsBaseVertex(Mode, countArray, Type, idxOffsArray, RDCMIN(Count, m_LastEventID - baseEventID + 1), baseArray);
}
else
{
// otherwise we do the 'hard' case, draw only one multidraw
// note we'll never be asked to do e.g. 3rd-7th of a multidraw. Only ever 0th-nth or
// a single draw.
RDCASSERT(m_LastEventID == m_FirstEventID);
uint32_t drawidx = (m_LastEventID - baseEventID);
m_Real.glDrawElementsBaseVertex(Mode, countArray[drawidx], Type, idxOffsArray[drawidx], baseArray[drawidx]);
}
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
string name = "glMultiDrawElementsBaseVertex(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + "," +
ToStr::Get(Type) + "," +
ToStr::Get(Count) + ")";
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_MultiDraw;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, false);
m_DrawcallStack.push_back(&m_DrawcallStack.back()->children.back());
m_CurEventID++;
for(uint32_t i=0; i < Count; i++)
{
FetchDrawcall multidraw;
multidraw.numIndices = countArray[i];
multidraw.indexOffset = (uint32_t) uint64_t(idxOffsArray[i])&0xFFFFFFFF;
multidraw.vertexOffset = baseArray[i];
multidraw.name = "glMultiDrawElementsBaseVertex[" + ToStr::Get(i) + "](" +
ToStr::Get(multidraw.numIndices) + ", " +
ToStr::Get(multidraw.indexOffset) + ", " +
ToStr::Get(multidraw.vertexOffset) + ")";
multidraw.flags |= eDraw_Drawcall|eDraw_UseIBuffer;
multidraw.topology = MakePrimitiveTopology(m_Real, Mode);
multidraw.indexByteWidth = IdxSize;
AddEvent(MULTI_DRAWELEMENTSBASEVERTEX, desc);
AddDrawcall(multidraw, true);
m_CurEventID++;
}
m_DrawcallStack.pop_back();
}
else
{
m_CurEventID += Count+1;
}
SAFE_DELETE_ARRAY(countArray);
SAFE_DELETE_ARRAY(baseArray);
SAFE_DELETE_ARRAY(idxOffsArray);
return true;
}
void WrappedOpenGL::glMultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex)
{
CoherentMapImplicitBarrier();
m_Real.glMultiDrawElementsBaseVertex(mode, count, type, indices, drawcount, basevertex);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MULTI_DRAWELEMENTSBASEVERTEX);
Serialise_glMultiDrawElementsBaseVertex(mode, count, type, indices, drawcount, basevertex);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirect(GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)indirect);
SERIALISE_ELEMENT(uint32_t, Count, drawcount);
SERIALISE_ELEMENT(uint32_t, Stride, stride);
if(m_State == READING)
{
m_Real.glMultiDrawArraysIndirect(Mode, (const void *)Offset, Count, Stride);
}
else if(m_State <= EXECUTING)
{
size_t i=0;
for(; i < m_Events.size(); i++)
{
if(m_Events[i].eventID >= m_CurEventID)
break;
}
while(i > 1 && m_Events[i-1].fileOffset == m_Events[i].fileOffset) i--;
uint32_t baseEventID = m_Events[i].eventID;
if(m_LastEventID < baseEventID)
{
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
// then we'll replay up to N but not N+1, so just do nothing - we DON'T want to draw
// the first sub-draw in that range.
}
else if(m_FirstEventID <= baseEventID && m_LastEventID >= baseEventID)
{
// if we're replaying part-way into a multidraw, we can replay the first part 'easily'
// by just reducing the Count parameter to however many we want to replay. This only
// works if we're replaying from the first multidraw to the nth (n less than Count)
m_Real.glMultiDrawArraysIndirect(Mode, (const void *)Offset, RDCMIN(Count, m_LastEventID - baseEventID + 1), Stride);
}
else
{
// otherwise we do the 'hard' case, draw only one multidraw
// note we'll never be asked to do e.g. 3rd-7th of a multidraw. Only ever 0th-nth or
// a single draw.
RDCASSERT(m_LastEventID == m_FirstEventID);
uint32_t drawidx = (m_LastEventID - baseEventID);
DrawArraysIndirectCommand params;
GLintptr offs = (GLintptr)Offset;
if(Stride != 0)
offs += Stride*drawidx;
else
offs += sizeof(params)*drawidx;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, offs, sizeof(params), &params);
m_Real.glDrawArraysInstancedBaseInstance(Mode, params.first, params.count, params.instanceCount, params.baseInstance);
}
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
string name = "glMultiDrawArraysIndirect(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + "," +
ToStr::Get(Count) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_MultiDraw;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, false);
m_DrawcallStack.push_back(&m_DrawcallStack.back()->children.back());
m_CurEventID++;
GLintptr offs = (GLintptr)Offset;
for(uint32_t i=0; i < Count; i++)
{
DrawArraysIndirectCommand params;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, offs, sizeof(params), &params);
if(Stride)
offs += Stride;
else
offs += sizeof(params);
FetchDrawcall multidraw;
multidraw.numIndices = params.count;
multidraw.numInstances = params.instanceCount;
multidraw.vertexOffset = params.first;
multidraw.instanceOffset = params.baseInstance;
multidraw.name = "glMultiDrawArraysIndirect[" + ToStr::Get(i) + "](<" +
ToStr::Get(multidraw.numIndices) + ", " +
ToStr::Get(multidraw.numInstances) + ", " +
ToStr::Get(multidraw.vertexOffset) + ", " +
ToStr::Get(multidraw.instanceOffset) + ">)";
multidraw.flags |= eDraw_Drawcall|eDraw_Instanced|eDraw_Indirect;
multidraw.topology = MakePrimitiveTopology(m_Real, Mode);
AddEvent(MULTI_DRAWARRAYS_INDIRECT, desc);
AddDrawcall(multidraw, true);
m_CurEventID++;
}
m_DrawcallStack.pop_back();
}
else
{
m_CurEventID += Count+1;
}
return true;
}
void WrappedOpenGL::glMultiDrawArraysIndirect(GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride)
{
CoherentMapImplicitBarrier();
m_Real.glMultiDrawArraysIndirect(mode, indirect, drawcount, stride);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MULTI_DRAWARRAYS_INDIRECT);
Serialise_glMultiDrawArraysIndirect(mode, indirect, drawcount, stride);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirect(GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)indirect);
SERIALISE_ELEMENT(uint32_t, Count, drawcount);
SERIALISE_ELEMENT(uint32_t, Stride, stride);
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
if(m_State == READING)
{
m_Real.glMultiDrawElementsIndirect(Mode, Type, (const void *)Offset, Count, Stride);
}
else if(m_State <= EXECUTING)
{
size_t i=0;
for(; i < m_Events.size(); i++)
{
if(m_Events[i].eventID >= m_CurEventID)
break;
}
while(i > 1 && m_Events[i-1].fileOffset == m_Events[i].fileOffset) i--;
uint32_t baseEventID = m_Events[i].eventID;
if(m_LastEventID < baseEventID)
{
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
// then we'll replay up to N but not N+1, so just do nothing - we DON'T want to draw
// the first sub-draw in that range.
}
else if(m_FirstEventID <= baseEventID && m_LastEventID >= baseEventID)
{
// if we're replaying part-way into a multidraw, we can replay the first part 'easily'
// by just reducing the Count parameter to however many we want to replay. This only
// works if we're replaying from the first multidraw to the nth (n less than Count)
m_Real.glMultiDrawElementsIndirect(Mode, Type, (const void *)Offset, RDCMIN(Count, m_LastEventID - baseEventID + 1), Stride);
}
else
{
// otherwise we do the 'hard' case, draw only one multidraw
// note we'll never be asked to do e.g. 3rd-7th of a multidraw. Only ever 0th-nth or
// a single draw.
RDCASSERT(m_LastEventID == m_FirstEventID);
uint32_t drawidx = (m_LastEventID - baseEventID);
DrawElementsIndirectCommand params;
GLintptr offs = (GLintptr)Offset;
if(Stride != 0)
offs += Stride*drawidx;
else
offs += sizeof(params)*drawidx;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, offs, sizeof(params), &params);
m_Real.glDrawElementsInstancedBaseVertexBaseInstance(Mode, params.count, Type, (const void *)ptrdiff_t(params.firstIndex*IdxSize),
params.instanceCount, params.baseVertex, params.baseInstance);
}
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
string name = "glMultiDrawElementsIndirect(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + "," +
ToStr::Get(Type) + "," +
ToStr::Get(Count) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_MultiDraw;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, false);
m_DrawcallStack.push_back(&m_DrawcallStack.back()->children.back());
m_CurEventID++;
GLintptr offs = (GLintptr)Offset;
for(uint32_t i=0; i < Count; i++)
{
DrawElementsIndirectCommand params;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, offs, sizeof(params), &params);
if(Stride)
offs += Stride;
else
offs += sizeof(params);
FetchDrawcall multidraw;
multidraw.numIndices = params.count;
multidraw.numInstances = params.instanceCount;
multidraw.indexOffset = params.firstIndex;
multidraw.vertexOffset = params.baseVertex;
multidraw.instanceOffset = params.baseInstance;
multidraw.name = "glMultiDrawElementsIndirect[" + ToStr::Get(i) + "](<" +
ToStr::Get(multidraw.numIndices) + ", " +
ToStr::Get(multidraw.numInstances) + ", " +
ToStr::Get(multidraw.indexOffset) + ", " +
ToStr::Get(multidraw.instanceOffset) + ">)";
multidraw.flags |= eDraw_Drawcall|eDraw_UseIBuffer|eDraw_Instanced|eDraw_Indirect;
multidraw.topology = MakePrimitiveTopology(m_Real, Mode);
multidraw.indexByteWidth = IdxSize;
AddEvent(MULTI_DRAWELEMENTS_INDIRECT, desc);
AddDrawcall(multidraw, true);
m_CurEventID++;
}
m_DrawcallStack.pop_back();
}
else
{
m_CurEventID += Count+1;
}
return true;
}
void WrappedOpenGL::glMultiDrawElementsIndirect(GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride)
{
CoherentMapImplicitBarrier();
m_Real.glMultiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MULTI_DRAWELEMENTS_INDIRECT);
Serialise_glMultiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirectCountARB(GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)indirect);
SERIALISE_ELEMENT(uint64_t, Count, (uint64_t)drawcount);
SERIALISE_ELEMENT(uint32_t, MaxCount, maxdrawcount);
SERIALISE_ELEMENT(uint32_t, Stride, stride);
uint32_t realdrawcount = 0;
if(m_State < WRITING)
{
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, (GLintptr)Count, sizeof(realdrawcount), &realdrawcount);
realdrawcount = RDCMIN(MaxCount, realdrawcount);
}
if(m_State == READING)
{
m_Real.glMultiDrawArraysIndirectCountARB(Mode, (GLintptr)Offset, (GLintptr)Count, MaxCount, Stride);
}
else if(m_State <= EXECUTING)
{
size_t i=0;
for(; i < m_Events.size(); i++)
{
if(m_Events[i].eventID >= m_CurEventID)
break;
}
while(i > 1 && m_Events[i-1].fileOffset == m_Events[i].fileOffset) i--;
uint32_t baseEventID = m_Events[i].eventID;
if(m_LastEventID < baseEventID)
{
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
// then we'll replay up to N but not N+1, so just do nothing - we DON'T want to draw
// the first sub-draw in that range.
}
else if(m_FirstEventID <= baseEventID && m_LastEventID >= baseEventID)
{
// if we're replaying part-way into a multidraw, we can replay the first part 'easily'
// by just reducing the Count parameter to however many we want to replay. This only
// works if we're replaying from the first multidraw to the nth (n less than Count)
m_Real.glMultiDrawArraysIndirect(Mode, (const void *)Offset, RDCMIN(realdrawcount, m_LastEventID - baseEventID + 1), Stride);
}
else
{
// otherwise we do the 'hard' case, draw only one multidraw
// note we'll never be asked to do e.g. 3rd-7th of a multidraw. Only ever 0th-nth or
// a single draw.
RDCASSERT(m_LastEventID == m_FirstEventID);
uint32_t drawidx = (m_LastEventID - baseEventID);
DrawArraysIndirectCommand params;
GLintptr offs = (GLintptr)Offset;
if(Stride != 0)
offs += Stride*drawidx;
else
offs += sizeof(params)*drawidx;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, offs, sizeof(params), &params);
m_Real.glDrawArraysInstancedBaseInstance(Mode, params.first, params.count, params.instanceCount, params.baseInstance);
}
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
string name = "glMultiDrawArraysIndirectCountARB(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + ", <" +
ToStr::Get(realdrawcount) + "> " +
ToStr::Get(MaxCount) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_MultiDraw;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
AddDrawcall(draw, false);
m_DrawcallStack.push_back(&m_DrawcallStack.back()->children.back());
m_CurEventID++;
GLintptr offs = (GLintptr)Offset;
for(uint32_t i=0; i < realdrawcount; i++)
{
DrawArraysIndirectCommand params;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, offs, sizeof(params), &params);
if(Stride)
offs += Stride;
else
offs += sizeof(params);
FetchDrawcall multidraw;
multidraw.numIndices = params.count;
multidraw.numInstances = params.instanceCount;
multidraw.vertexOffset = params.first;
multidraw.instanceOffset = params.baseInstance;
multidraw.name = "glMultiDrawArraysIndirect[" + ToStr::Get(i) + "](<" +
ToStr::Get(multidraw.numIndices) + ", " +
ToStr::Get(multidraw.numInstances) + ", " +
ToStr::Get(multidraw.vertexOffset) + ", " +
ToStr::Get(multidraw.instanceOffset) + ">)";
multidraw.flags |= eDraw_Drawcall|eDraw_Instanced|eDraw_Indirect;
multidraw.topology = MakePrimitiveTopology(m_Real, Mode);
AddEvent(MULTI_DRAWARRAYS_INDIRECT, desc);
AddDrawcall(multidraw, true);
m_CurEventID++;
}
m_DrawcallStack.pop_back();
}
else
{
m_CurEventID += realdrawcount+1;
}
return true;
}
void WrappedOpenGL::glMultiDrawArraysIndirectCountARB(GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride)
{
CoherentMapImplicitBarrier();
m_Real.glMultiDrawArraysIndirectCountARB(mode, indirect, drawcount, maxdrawcount, stride);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MULTI_DRAWARRAYS_INDIRECT_COUNT);
Serialise_glMultiDrawArraysIndirectCountARB(mode, indirect, drawcount, maxdrawcount, stride);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirectCountARB(GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride)
{
SERIALISE_ELEMENT(GLenum, Mode, mode);
SERIALISE_ELEMENT(GLenum, Type, type);
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)indirect);
SERIALISE_ELEMENT(uint64_t, Count, (uint64_t)drawcount);
SERIALISE_ELEMENT(uint32_t, MaxCount, maxdrawcount);
SERIALISE_ELEMENT(uint32_t, Stride, stride);
uint32_t IdxSize =
Type == eGL_UNSIGNED_BYTE ? 1
: Type == eGL_UNSIGNED_SHORT ? 2
: /*Type == eGL_UNSIGNED_INT*/ 4;
uint32_t realdrawcount = 0;
if(m_State < WRITING)
{
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, (GLintptr)Count, sizeof(realdrawcount), &realdrawcount);
realdrawcount = RDCMIN(MaxCount, realdrawcount);
}
if(m_State == READING)
{
m_Real.glMultiDrawElementsIndirectCountARB(Mode, Type, (GLintptr)Offset, (GLintptr)Count, MaxCount, Stride);
}
else if(m_State <= EXECUTING)
{
size_t i=0;
for(; i < m_Events.size(); i++)
{
if(m_Events[i].eventID >= m_CurEventID)
break;
}
while(i > 1 && m_Events[i-1].fileOffset == m_Events[i].fileOffset) i--;
uint32_t baseEventID = m_Events[i].eventID;
if(m_LastEventID < baseEventID)
{
// To add the multidraw, we made an event N that is the 'parent' marker, then
// N+1, N+2, N+3, ... for each of the sub-draws. If the first sub-draw is selected
// then we'll replay up to N but not N+1, so just do nothing - we DON'T want to draw
// the first sub-draw in that range.
}
else if(m_FirstEventID <= baseEventID && m_LastEventID >= baseEventID)
{
// if we're replaying part-way into a multidraw, we can replay the first part 'easily'
// by just reducing the Count parameter to however many we want to replay. This only
// works if we're replaying from the first multidraw to the nth (n less than Count)
m_Real.glMultiDrawElementsIndirect(Mode, Type, (const void *)Offset, RDCMIN(realdrawcount, m_LastEventID - baseEventID + 1), Stride);
}
else
{
// otherwise we do the 'hard' case, draw only one multidraw
// note we'll never be asked to do e.g. 3rd-7th of a multidraw. Only ever 0th-nth or
// a single draw.
RDCASSERT(m_LastEventID == m_FirstEventID);
uint32_t drawidx = (m_LastEventID - baseEventID);
DrawElementsIndirectCommand params;
GLintptr offs = (GLintptr)Offset;
if(Stride != 0)
offs += Stride*drawidx;
else
offs += sizeof(params)*drawidx;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, offs, sizeof(params), &params);
m_Real.glDrawElementsInstancedBaseVertexBaseInstance(Mode, params.count, Type, (const void *)ptrdiff_t(params.firstIndex*IdxSize),
params.instanceCount, params.baseVertex, params.baseInstance);
}
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
string name = "glMultiDrawElementsIndirectCountARB(" +
( Mode == eGL_POINTS ? "GL_POINTS" : ToStr::Get(Mode) ) + "," +
ToStr::Get(Type) + ", <" +
ToStr::Get(realdrawcount) + ">, " +
ToStr::Get(MaxCount) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_MultiDraw;
draw.topology = MakePrimitiveTopology(m_Real, Mode);
draw.indexByteWidth = IdxSize;
AddDrawcall(draw, false);
m_DrawcallStack.push_back(&m_DrawcallStack.back()->children.back());
m_CurEventID++;
GLintptr offs = (GLintptr)Offset;
for(uint32_t i=0; i < realdrawcount; i++)
{
DrawElementsIndirectCommand params;
m_Real.glGetBufferSubData(eGL_DRAW_INDIRECT_BUFFER, offs, sizeof(params), &params);
if(Stride)
offs += Stride;
else
offs += sizeof(params);
FetchDrawcall multidraw;
multidraw.numIndices = params.count;
multidraw.numInstances = params.instanceCount;
multidraw.indexOffset = params.firstIndex;
multidraw.vertexOffset = params.baseVertex;
multidraw.instanceOffset = params.baseInstance;
multidraw.name = "glMultiDrawElementsIndirect[" + ToStr::Get(i) + "](" +
ToStr::Get(multidraw.numIndices) + ", " +
ToStr::Get(multidraw.numInstances) + ", " +
ToStr::Get(multidraw.indexOffset) + ", " +
ToStr::Get(multidraw.instanceOffset) + ")";
multidraw.flags |= eDraw_Drawcall|eDraw_UseIBuffer|eDraw_Instanced|eDraw_Indirect;
multidraw.topology = MakePrimitiveTopology(m_Real, Mode);
multidraw.indexByteWidth = IdxSize;
AddEvent(MULTI_DRAWELEMENTS_INDIRECT, desc);
AddDrawcall(multidraw, true);
m_CurEventID++;
}
m_DrawcallStack.pop_back();
}
else
{
m_CurEventID += realdrawcount+1;
}
return true;
}
void WrappedOpenGL::glMultiDrawElementsIndirectCountARB(GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride)
{
CoherentMapImplicitBarrier();
m_Real.glMultiDrawElementsIndirectCountARB(mode, type, indirect, drawcount, maxdrawcount, stride);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(MULTI_DRAWELEMENTS_INDIRECT_COUNT);
Serialise_glMultiDrawElementsIndirectCountARB(mode, type, indirect, drawcount, maxdrawcount, stride);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value)
{
SERIALISE_ELEMENT(ResourceId, Id, (framebuffer ? GetResourceManager()->GetID(FramebufferRes(GetCtx(), framebuffer)) : ResourceId()));
SERIALISE_ELEMENT(GLenum, buf, buffer);
SERIALISE_ELEMENT(int32_t, drawbuf, drawbuffer);
if(m_State <= EXECUTING)
{
if(Id == ResourceId())
framebuffer = m_FakeBB_FBO;
else
framebuffer = GetResourceManager()->GetLiveResource(Id).name;
}
string name;
if(buf != eGL_DEPTH)
{
Vec4f v;
if(value) v = *((Vec4f *)value);
m_pSerialiser->Serialise<4>("value", (float *)&v.x);
if(m_State == READING)
name = "glClearBufferfv(" +
ToStr::Get(buf) + ", " +
ToStr::Get(drawbuf) + ", " +
ToStr::Get(v.x) + ", " +
ToStr::Get(v.y) + ", " +
ToStr::Get(v.z) + ", " +
ToStr::Get(v.w) + ")";
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This is
// necessary since these functions can be serialised even if ARB_dsa was not used originally, and
// we need to support this case.
if(m_State <= EXECUTING)
m_Real.glClearNamedFramebufferfv(framebuffer, buf, drawbuf, &v.x);
}
else
{
SERIALISE_ELEMENT(float, val, *value);
if(m_State == READING)
name = "glClearBufferfv(" +
ToStr::Get(buf) + ", " +
ToStr::Get(drawbuf) + ", " +
ToStr::Get(val) + ")";
if(m_State <= EXECUTING)
m_Real.glClearNamedFramebufferfv(framebuffer, buf, drawbuf, &val);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(CLEARBUFFERF, desc);
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_Clear;
if(buf == eGL_COLOR)
draw.flags |= eDraw_ClearColour;
else
draw.flags |= eDraw_ClearDepthStencil;
AddDrawcall(draw, true);
GLuint attachment = 0;
GLenum attachName = buf == eGL_COLOR ? GLenum(eGL_COLOR_ATTACHMENT0 + drawbuf) : eGL_DEPTH_ATTACHMENT;
GLenum type = eGL_TEXTURE;
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, attachName, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&attachment);
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, attachName, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
if(attachment)
{
if(type == eGL_TEXTURE)
m_ResourceUses[GetResourceManager()->GetID(TextureRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
else
m_ResourceUses[GetResourceManager()->GetID(RenderbufferRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
}
}
return true;
}
void WrappedOpenGL::glClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value)
{
CoherentMapImplicitBarrier();
m_Real.glClearNamedFramebufferfv(framebuffer, buffer, drawbuffer, value);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERF);
Serialise_glClearNamedFramebufferfv(framebuffer, buffer, drawbuffer, value);
m_ContextRecord->AddChunk(scope.Get());
}
}
void WrappedOpenGL::glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
{
CoherentMapImplicitBarrier();
m_Real.glClearBufferfv(buffer, drawbuffer, value);
if(m_State == WRITING_CAPFRAME)
{
GLuint framebuffer = 0;
if(GetCtxData().m_DrawFramebufferRecord)
framebuffer = GetCtxData().m_DrawFramebufferRecord->Resource.name;
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERF);
Serialise_glClearNamedFramebufferfv(framebuffer, buffer, drawbuffer, value);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value)
{
SERIALISE_ELEMENT(ResourceId, Id, (framebuffer ? GetResourceManager()->GetID(FramebufferRes(GetCtx(), framebuffer)) : ResourceId()));
SERIALISE_ELEMENT(GLenum, buf, buffer);
SERIALISE_ELEMENT(int32_t, drawbuf, drawbuffer);
if(m_State <= EXECUTING)
{
if(Id == ResourceId())
framebuffer = m_FakeBB_FBO;
else
framebuffer = GetResourceManager()->GetLiveResource(Id).name;
}
string name;
if(buf != eGL_STENCIL)
{
int32_t v[4];
if(value) memcpy(v, value, sizeof(v));
m_pSerialiser->Serialise<4>("value", v);
if(m_State == READING)
name = "glClearBufferiv(" +
ToStr::Get(buf) + ", " +
ToStr::Get(drawbuf) + ", " +
ToStr::Get(v[0]) + ", " +
ToStr::Get(v[1]) + ", " +
ToStr::Get(v[2]) + ", " +
ToStr::Get(v[3]) + ")";
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This is
// necessary since these functions can be serialised even if ARB_dsa was not used originally, and
// we need to support this case.
if(m_State <= EXECUTING)
m_Real.glClearNamedFramebufferiv(framebuffer, buf, drawbuf, v);
}
else
{
SERIALISE_ELEMENT(int32_t, val, *value);
if(m_State == READING)
name = "glClearBufferiv(" +
ToStr::Get(buf) + ", " +
ToStr::Get(drawbuf) + ", " +
ToStr::Get(val) + ")";
if(m_State <= EXECUTING)
m_Real.glClearNamedFramebufferiv(framebuffer, buf, drawbuf, &val);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(CLEARBUFFERI, desc);
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_Clear;
if(buf == eGL_COLOR)
draw.flags |= eDraw_ClearColour;
else
draw.flags |= eDraw_ClearDepthStencil;
AddDrawcall(draw, true);
GLuint attachment = 0;
GLenum attachName = buf == eGL_COLOR ? GLenum(eGL_COLOR_ATTACHMENT0 + drawbuf) : eGL_STENCIL_ATTACHMENT;
GLenum type = eGL_TEXTURE;
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, attachName, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&attachment);
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, attachName, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
if(attachment)
{
if(type == eGL_TEXTURE)
m_ResourceUses[GetResourceManager()->GetID(TextureRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
else
m_ResourceUses[GetResourceManager()->GetID(RenderbufferRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
}
}
return true;
}
void WrappedOpenGL::glClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value)
{
CoherentMapImplicitBarrier();
m_Real.glClearNamedFramebufferiv(framebuffer, buffer, drawbuffer, value);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERI);
Serialise_glClearNamedFramebufferiv(framebuffer, buffer, drawbuffer, value);
m_ContextRecord->AddChunk(scope.Get());
}
}
void WrappedOpenGL::glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
{
CoherentMapImplicitBarrier();
m_Real.glClearBufferiv(buffer, drawbuffer, value);
if(m_State == WRITING_CAPFRAME)
{
GLuint framebuffer = 0;
if(GetCtxData().m_DrawFramebufferRecord)
framebuffer = GetCtxData().m_DrawFramebufferRecord->Resource.name;
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERI);
Serialise_glClearNamedFramebufferiv(framebuffer, buffer, drawbuffer, value);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value)
{
SERIALISE_ELEMENT(ResourceId, Id, (framebuffer ? GetResourceManager()->GetID(FramebufferRes(GetCtx(), framebuffer)) : ResourceId()));
SERIALISE_ELEMENT(GLenum, buf, buffer);
SERIALISE_ELEMENT(int32_t, drawbuf, drawbuffer);
if(m_State <= EXECUTING)
{
if(Id == ResourceId())
framebuffer = m_FakeBB_FBO;
else
framebuffer = GetResourceManager()->GetLiveResource(Id).name;
}
string name;
{
uint32_t v[4];
if(value) memcpy(v, value, sizeof(v));
m_pSerialiser->Serialise<4>("value", v);
if(m_State == READING)
name = "glClearBufferuiv(" +
ToStr::Get(buf) + ", " +
ToStr::Get(drawbuf) + ", " +
ToStr::Get(v[0]) + ", " +
ToStr::Get(v[1]) + ", " +
ToStr::Get(v[2]) + ", " +
ToStr::Get(v[3]) + ")";
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This is
// necessary since these functions can be serialised even if ARB_dsa was not used originally, and
// we need to support this case.
if(m_State <= EXECUTING)
m_Real.glClearNamedFramebufferuiv(framebuffer, buf, drawbuf, v);
}
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(CLEARBUFFERUI, desc);
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_Clear|eDraw_ClearColour;
AddDrawcall(draw, true);
GLuint attachment = 0;
GLenum attachName = GLenum(eGL_COLOR_ATTACHMENT0 + drawbuf);
GLenum type = eGL_TEXTURE;
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, attachName, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&attachment);
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, attachName, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
if(attachment)
{
if(type == eGL_TEXTURE)
m_ResourceUses[GetResourceManager()->GetID(TextureRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
else
m_ResourceUses[GetResourceManager()->GetID(RenderbufferRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
}
}
return true;
}
void WrappedOpenGL::glClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value)
{
CoherentMapImplicitBarrier();
m_Real.glClearNamedFramebufferuiv(framebuffer, buffer, drawbuffer, value);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERUI);
Serialise_glClearNamedFramebufferuiv(framebuffer, buffer, drawbuffer, value);
m_ContextRecord->AddChunk(scope.Get());
}
}
void WrappedOpenGL::glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
{
CoherentMapImplicitBarrier();
m_Real.glClearBufferuiv(buffer, drawbuffer, value);
if(m_State == WRITING_CAPFRAME)
{
GLuint framebuffer = 0;
if(GetCtxData().m_DrawFramebufferRecord)
framebuffer = GetCtxData().m_DrawFramebufferRecord->Resource.name;
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERUI);
Serialise_glClearNamedFramebufferuiv(framebuffer, buffer, drawbuffer, value);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, GLfloat depth, GLint stencil)
{
SERIALISE_ELEMENT(ResourceId, Id, (framebuffer ? GetResourceManager()->GetID(FramebufferRes(GetCtx(), framebuffer)) : ResourceId()));
SERIALISE_ELEMENT(GLenum, buf, buffer);
SERIALISE_ELEMENT(float, d, depth);
SERIALISE_ELEMENT(int32_t, s, stencil);
if(m_State <= EXECUTING)
{
if(Id == ResourceId())
framebuffer = m_FakeBB_FBO;
else
framebuffer = GetResourceManager()->GetLiveResource(Id).name;
}
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This is
// necessary since these functions can be serialised even if ARB_dsa was not used originally, and
// we need to support this case.
if(m_State <= EXECUTING)
m_Real.glClearNamedFramebufferfi(framebuffer, buf, d, s);
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(CLEARBUFFERFI, desc);
string name = "glClearBufferfi(" +
ToStr::Get(d) +
ToStr::Get(s) + ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_Clear|eDraw_ClearDepthStencil;
AddDrawcall(draw, true);
GLuint attachment = 0;
GLenum type = eGL_TEXTURE;
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&attachment);
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
if(attachment)
{
if(type == eGL_TEXTURE)
m_ResourceUses[GetResourceManager()->GetID(TextureRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
else
m_ResourceUses[GetResourceManager()->GetID(RenderbufferRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
}
attachment = 0;
type = eGL_TEXTURE;
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&attachment);
m_Real.glGetNamedFramebufferAttachmentParameterivEXT(framebuffer, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
if(attachment)
{
if(type == eGL_TEXTURE)
m_ResourceUses[GetResourceManager()->GetID(TextureRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
else
m_ResourceUses[GetResourceManager()->GetID(RenderbufferRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
}
}
return true;
}
void WrappedOpenGL::glClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, GLfloat depth, GLint stencil)
{
CoherentMapImplicitBarrier();
m_Real.glClearNamedFramebufferfi(framebuffer, buffer, depth, stencil);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERFI);
Serialise_glClearNamedFramebufferfi(framebuffer, buffer, depth, stencil);
m_ContextRecord->AddChunk(scope.Get());
}
}
void WrappedOpenGL::glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
{
CoherentMapImplicitBarrier();
m_Real.glClearBufferfi(buffer, drawbuffer, depth, stencil);
if(m_State == WRITING_CAPFRAME)
{
GLuint framebuffer = 0;
if(GetCtxData().m_DrawFramebufferRecord)
framebuffer = GetCtxData().m_DrawFramebufferRecord->Resource.name;
// drawbuffer is ignored, as it must be 0 anyway
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERFI);
Serialise_glClearNamedFramebufferfi(framebuffer, buffer, depth, stencil);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glClearNamedBufferDataEXT(GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data)
{
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)));
SERIALISE_ELEMENT(GLenum, InternalFormat, internalformat);
SERIALISE_ELEMENT(GLenum, Format, format);
SERIALISE_ELEMENT(GLenum, Type, type);
uint64_t val[4] = {0};
if(m_State >= WRITING)
{
size_t s = 1;
switch(Format)
{
default:
RDCWARN("Unexpected format %x, defaulting to single component", Format);
case eGL_RED:
case eGL_DEPTH_COMPONENT:
s = 1; break;
case eGL_RG:
case eGL_DEPTH_STENCIL:
s = 2; break;
case eGL_RGB:
case eGL_BGR:
s = 3; break;
case eGL_RGBA:
case eGL_BGRA:
s = 4; break;
}
switch(Type)
{
case eGL_UNSIGNED_BYTE:
case eGL_BYTE:
s *= 1; break;
case eGL_UNSIGNED_SHORT:
case eGL_SHORT:
s *= 2; break;
case eGL_UNSIGNED_INT:
case eGL_INT:
case eGL_FLOAT:
s *= 4; break;
default:
RDCWARN("Unexpected type %x, defaulting to 1 byte single component type", Format);
case eGL_UNSIGNED_BYTE_3_3_2:
case eGL_UNSIGNED_BYTE_2_3_3_REV:
s = 1; break;
case eGL_UNSIGNED_SHORT_5_6_5:
case eGL_UNSIGNED_SHORT_5_6_5_REV:
case eGL_UNSIGNED_SHORT_4_4_4_4:
case eGL_UNSIGNED_SHORT_4_4_4_4_REV:
case eGL_UNSIGNED_SHORT_5_5_5_1:
case eGL_UNSIGNED_SHORT_1_5_5_5_REV:
case eGL_UNSIGNED_INT_8_8_8_8:
case eGL_UNSIGNED_INT_8_8_8_8_REV:
s = 2; break;
case eGL_UNSIGNED_INT_10_10_10_2:
case eGL_UNSIGNED_INT_2_10_10_10_REV:
s = 4; break;
}
memcpy(val, data, s);
}
m_pSerialiser->Serialise<4>("data", val);
if(m_State <= EXECUTING)
{
m_Real.glClearNamedBufferDataEXT(GetResourceManager()->GetLiveResource(id).name, InternalFormat, Format, Type, (const void *)&val[0]);
}
return true;
}
void WrappedOpenGL::glClearNamedBufferDataEXT(GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data)
{
CoherentMapImplicitBarrier();
m_Real.glClearNamedBufferDataEXT(buffer, internalformat, format, type, data);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERDATA);
Serialise_glClearNamedBufferDataEXT(buffer, internalformat, format, type, data);
m_ContextRecord->AddChunk(scope.Get());
}
}
void WrappedOpenGL::glClearBufferData(GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data)
{
CoherentMapImplicitBarrier();
m_Real.glClearBufferData(target, internalformat, format, type, data);
if(m_State == WRITING_CAPFRAME)
{
GLResourceRecord *record = GetCtxData().m_BufferRecord[BufferIdx(target)];
RDCASSERT(record);
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERDATA);
Serialise_glClearNamedBufferDataEXT(record->Resource.name, internalformat, format, type, data);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glClearNamedBufferSubDataEXT(GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data)
{
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)));
SERIALISE_ELEMENT(GLenum, InternalFormat, internalformat);
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)offset);
SERIALISE_ELEMENT(uint64_t, Size, (uint64_t)size);
SERIALISE_ELEMENT(GLenum, Format, format);
SERIALISE_ELEMENT(GLenum, Type, type);
uint64_t val[4] = {0};
if(m_State >= WRITING)
{
size_t s = 1;
switch(Format)
{
default:
RDCWARN("Unexpected format %x, defaulting to single component", Format);
case eGL_RED:
case eGL_DEPTH_COMPONENT:
s = 1; break;
case eGL_RG:
case eGL_DEPTH_STENCIL:
s = 2; break;
case eGL_RGB:
case eGL_BGR:
s = 3; break;
case eGL_RGBA:
case eGL_BGRA:
s = 4; break;
}
switch(Type)
{
case eGL_UNSIGNED_BYTE:
case eGL_BYTE:
s *= 1; break;
case eGL_UNSIGNED_SHORT:
case eGL_SHORT:
s *= 2; break;
case eGL_UNSIGNED_INT:
case eGL_INT:
case eGL_FLOAT:
s *= 4; break;
default:
RDCWARN("Unexpected type %x, defaulting to 1 byte single component type", Format);
case eGL_UNSIGNED_BYTE_3_3_2:
case eGL_UNSIGNED_BYTE_2_3_3_REV:
s = 1; break;
case eGL_UNSIGNED_SHORT_5_6_5:
case eGL_UNSIGNED_SHORT_5_6_5_REV:
case eGL_UNSIGNED_SHORT_4_4_4_4:
case eGL_UNSIGNED_SHORT_4_4_4_4_REV:
case eGL_UNSIGNED_SHORT_5_5_5_1:
case eGL_UNSIGNED_SHORT_1_5_5_5_REV:
case eGL_UNSIGNED_INT_8_8_8_8:
case eGL_UNSIGNED_INT_8_8_8_8_REV:
s = 2; break;
case eGL_UNSIGNED_INT_10_10_10_2:
case eGL_UNSIGNED_INT_2_10_10_10_REV:
s = 4; break;
}
memcpy(val, data, s);
}
m_pSerialiser->Serialise<4>("data", val);
if(m_State <= EXECUTING)
{
m_Real.glClearNamedBufferSubDataEXT(GetResourceManager()->GetLiveResource(id).name, InternalFormat, (GLintptr)Offset, (GLsizeiptr)Size, Format, Type, (const void *)&val[0]);
}
return true;
}
void WrappedOpenGL::glClearNamedBufferSubDataEXT(GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data)
{
CoherentMapImplicitBarrier();
m_Real.glClearNamedBufferSubDataEXT(buffer, internalformat, offset, size, format, type, data);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERSUBDATA);
Serialise_glClearNamedBufferSubDataEXT(buffer, internalformat, offset, size, format, type, data);
m_ContextRecord->AddChunk(scope.Get());
}
}
void WrappedOpenGL::glClearNamedBufferSubData(GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data)
{
// only difference to EXT function is size parameter, so just upcast
glClearNamedBufferSubDataEXT(buffer, internalformat, offset, size, format, type, data);
}
void WrappedOpenGL::glClearBufferSubData(GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data)
{
CoherentMapImplicitBarrier();
m_Real.glClearBufferSubData(target, internalformat, offset, size, format, type, data);
if(m_State == WRITING_CAPFRAME)
{
GLResourceRecord *record = GetCtxData().m_BufferRecord[BufferIdx(target)];
RDCASSERT(record);
SCOPED_SERIALISE_CONTEXT(CLEARBUFFERSUBDATA);
Serialise_glClearNamedBufferSubDataEXT(record->Resource.name, internalformat, offset, size, format, type, data);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glClear(GLbitfield mask)
{
SERIALISE_ELEMENT(uint32_t, Mask, mask);
if(m_State <= EXECUTING)
m_Real.glClear(Mask);
const string desc = m_pSerialiser->GetDebugStr();
Serialise_DebugMessages();
if(m_State == READING)
{
AddEvent(CLEAR, desc);
string name = "glClear(";
if(Mask & GL_COLOR_BUFFER_BIT)
{
float col[4] = {0};
m_Real.glGetFloatv(eGL_COLOR_CLEAR_VALUE, &col[0]);
name += StringFormat::Fmt("Color = <%f, %f, %f, %f>, ", col[0], col[1], col[2], col[3]);
}
if(Mask & GL_DEPTH_BUFFER_BIT)
{
float depth = 0;
m_Real.glGetFloatv(eGL_DEPTH_CLEAR_VALUE, &depth);
name += StringFormat::Fmt("Depth = <%f>, ", depth);
}
if(Mask & GL_STENCIL_BUFFER_BIT)
{
GLint stencil = 0;
m_Real.glGetIntegerv(eGL_STENCIL_CLEAR_VALUE, &stencil);
name += StringFormat::Fmt("Stencil = <0x%02x>, ", stencil);
}
if(Mask & (eGL_DEPTH_BUFFER_BIT|eGL_COLOR_BUFFER_BIT|eGL_STENCIL_BUFFER_BIT))
{
name.pop_back(); // ','
name.pop_back(); // ' '
}
name += ")";
FetchDrawcall draw;
draw.name = name;
draw.flags |= eDraw_Clear;
if(Mask & GL_COLOR_BUFFER_BIT)
draw.flags |= eDraw_ClearColour;
if(Mask & (eGL_DEPTH_BUFFER_BIT|eGL_STENCIL_BUFFER_BIT))
draw.flags |= eDraw_ClearDepthStencil;
AddDrawcall(draw, true);
GLuint attachment = 0;
GLenum type = eGL_TEXTURE;
if(Mask & GL_DEPTH_BUFFER_BIT)
{
m_Real.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&attachment);
m_Real.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
if(attachment)
{
if(type == eGL_TEXTURE)
m_ResourceUses[GetResourceManager()->GetID(TextureRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
else
m_ResourceUses[GetResourceManager()->GetID(RenderbufferRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
}
}
attachment = 0;
type = eGL_TEXTURE;
if(Mask & GL_STENCIL_BUFFER_BIT)
{
m_Real.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&attachment);
m_Real.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
if(attachment)
{
if(type == eGL_TEXTURE)
m_ResourceUses[GetResourceManager()->GetID(TextureRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
else
m_ResourceUses[GetResourceManager()->GetID(RenderbufferRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
}
}
if(Mask & GL_COLOR_BUFFER_BIT)
{
GLint numCols = 8;
m_Real.glGetIntegerv(eGL_MAX_COLOR_ATTACHMENTS, &numCols);
for(int i=0; i < numCols; i++)
{
attachment = 0;
type = eGL_TEXTURE;
m_Real.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, GLenum(eGL_COLOR_ATTACHMENT0+i), eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&attachment);
m_Real.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, GLenum(eGL_COLOR_ATTACHMENT0+i), eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)&type);
if(attachment)
{
if(type == eGL_TEXTURE)
m_ResourceUses[GetResourceManager()->GetID(TextureRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
else
m_ResourceUses[GetResourceManager()->GetID(RenderbufferRes(GetCtx(), attachment))].push_back(EventUsage(m_CurEventID, eUsage_Clear));
}
}
}
}
return true;
}
void WrappedOpenGL::glClear(GLbitfield mask)
{
CoherentMapImplicitBarrier();
m_Real.glClear(mask);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEAR);
Serialise_glClear(mask);
m_ContextRecord->AddChunk(scope.Get());
}
}
bool WrappedOpenGL::Serialise_glClearTexImage(GLuint texture, GLint level, GLenum format, GLenum type, const void *data)
{
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture)));
SERIALISE_ELEMENT(int32_t, Level, level);
SERIALISE_ELEMENT(GLenum, Format, format);
SERIALISE_ELEMENT(GLenum, Type, type);
uint64_t val[4] = {0};
if(m_State >= WRITING)
{
size_t s = 1;
switch(Format)
{
default:
RDCWARN("Unexpected format %x, defaulting to single component", Format);
case eGL_RED:
case eGL_DEPTH_COMPONENT:
s = 1; break;
case eGL_RG:
case eGL_DEPTH_STENCIL:
s = 2; break;
case eGL_RGB:
case eGL_BGR:
s = 3; break;
case eGL_RGBA:
case eGL_BGRA:
s = 4; break;
}
switch(Type)
{
case eGL_UNSIGNED_BYTE:
case eGL_BYTE:
s *= 1; break;
case eGL_UNSIGNED_SHORT:
case eGL_SHORT:
s *= 2; break;
case eGL_UNSIGNED_INT:
case eGL_INT:
case eGL_FLOAT:
s *= 4; break;
default:
RDCWARN("Unexpected type %x, defaulting to 1 byte single component type", Format);
case eGL_UNSIGNED_BYTE_3_3_2:
case eGL_UNSIGNED_BYTE_2_3_3_REV:
s = 1; break;
case eGL_UNSIGNED_SHORT_5_6_5:
case eGL_UNSIGNED_SHORT_5_6_5_REV:
case eGL_UNSIGNED_SHORT_4_4_4_4:
case eGL_UNSIGNED_SHORT_4_4_4_4_REV:
case eGL_UNSIGNED_SHORT_5_5_5_1:
case eGL_UNSIGNED_SHORT_1_5_5_5_REV:
case eGL_UNSIGNED_INT_8_8_8_8:
case eGL_UNSIGNED_INT_8_8_8_8_REV:
s = 2; break;
case eGL_UNSIGNED_INT_10_10_10_2:
case eGL_UNSIGNED_INT_2_10_10_10_REV:
s = 4; break;
}
memcpy(val, data, s);
}
m_pSerialiser->Serialise<4>("data", val);
if(m_State <= EXECUTING)
{
m_Real.glClearTexImage(GetResourceManager()->GetLiveResource(id).name, Level, Format, Type, (const void *)&val[0]);
}
return true;
}
void WrappedOpenGL::glClearTexImage(GLuint texture, GLint level, GLenum format, GLenum type, const void *data)
{
CoherentMapImplicitBarrier();
m_Real.glClearTexImage(texture, level, format, type, data);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEARTEXIMAGE);
Serialise_glClearTexImage(texture, level, format, type, data);
m_ContextRecord->AddChunk(scope.Get());
}
else if(m_State == WRITING_IDLE)
{
GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture));
}
}
bool WrappedOpenGL::Serialise_glClearTexSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data)
{
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture)));
SERIALISE_ELEMENT(int32_t, Level, level);
SERIALISE_ELEMENT(int32_t, Xoffs, xoffset);
SERIALISE_ELEMENT(int32_t, Yoffs, yoffset);
SERIALISE_ELEMENT(int32_t, Zoffs, zoffset);
SERIALISE_ELEMENT(int32_t, w, width);
SERIALISE_ELEMENT(int32_t, h, height);
SERIALISE_ELEMENT(int32_t, d, depth);
SERIALISE_ELEMENT(GLenum, Format, format);
SERIALISE_ELEMENT(GLenum, Type, type);
uint64_t val[4] = {0};
if(m_State >= WRITING)
{
size_t s = 1;
switch(Format)
{
default:
RDCWARN("Unexpected format %x, defaulting to single component", Format);
case eGL_RED:
case eGL_DEPTH_COMPONENT:
s = 1; break;
case eGL_RG:
case eGL_DEPTH_STENCIL:
s = 2; break;
case eGL_RGB:
case eGL_BGR:
s = 3; break;
case eGL_RGBA:
case eGL_BGRA:
s = 4; break;
}
switch(Type)
{
case eGL_UNSIGNED_BYTE:
case eGL_BYTE:
s *= 1; break;
case eGL_UNSIGNED_SHORT:
case eGL_SHORT:
s *= 2; break;
case eGL_UNSIGNED_INT:
case eGL_INT:
case eGL_FLOAT:
s *= 4; break;
default:
RDCWARN("Unexpected type %x, defaulting to 1 byte single component type", Format);
case eGL_UNSIGNED_BYTE_3_3_2:
case eGL_UNSIGNED_BYTE_2_3_3_REV:
s = 1; break;
case eGL_UNSIGNED_SHORT_5_6_5:
case eGL_UNSIGNED_SHORT_5_6_5_REV:
case eGL_UNSIGNED_SHORT_4_4_4_4:
case eGL_UNSIGNED_SHORT_4_4_4_4_REV:
case eGL_UNSIGNED_SHORT_5_5_5_1:
case eGL_UNSIGNED_SHORT_1_5_5_5_REV:
case eGL_UNSIGNED_INT_8_8_8_8:
case eGL_UNSIGNED_INT_8_8_8_8_REV:
s = 2; break;
case eGL_UNSIGNED_INT_10_10_10_2:
case eGL_UNSIGNED_INT_2_10_10_10_REV:
s = 4; break;
}
memcpy(val, data, s);
}
m_pSerialiser->Serialise<4>("data", val);
if(m_State <= EXECUTING)
{
m_Real.glClearTexSubImage(GetResourceManager()->GetLiveResource(id).name, Level, Xoffs, Yoffs, Zoffs, w, h, d, Format, Type, (const void *)&val[0]);
}
return true;
}
void WrappedOpenGL::glClearTexSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data)
{
CoherentMapImplicitBarrier();
m_Real.glClearTexSubImage(texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(CLEARTEXSUBIMAGE);
Serialise_glClearTexSubImage(texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
m_ContextRecord->AddChunk(scope.Get());
}
else if(m_State == WRITING_IDLE)
{
GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture));
}
}