mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-23 16:01:38 +00:00
2469 lines
67 KiB
C++
2469 lines
67 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"
|
|
|
|
#pragma region Buffers
|
|
|
|
bool WrappedOpenGL::Serialise_glGenBuffers(GLsizei n, GLuint* textures)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), *textures)));
|
|
|
|
if(m_State == READING)
|
|
{
|
|
GLuint real = 0;
|
|
m_Real.glGenBuffers(1, &real);
|
|
|
|
GLResource res = BufferRes(GetCtx(), real);
|
|
|
|
ResourceId live = m_ResourceManager->RegisterResource(res);
|
|
GetResourceManager()->AddLiveResource(id, res);
|
|
|
|
m_Buffers[live].resource = res;
|
|
m_Buffers[live].curType = eGL_NONE;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glGenBuffers(GLsizei n, GLuint *buffers)
|
|
{
|
|
m_Real.glGenBuffers(n, buffers);
|
|
|
|
for(GLsizei i=0; i < n; i++)
|
|
{
|
|
GLResource res = BufferRes(GetCtx(), buffers[i]);
|
|
ResourceId id = GetResourceManager()->RegisterResource(res);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
Chunk *chunk = NULL;
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(GEN_BUFFER);
|
|
Serialise_glGenBuffers(1, buffers+i);
|
|
|
|
chunk = scope.Get();
|
|
}
|
|
|
|
GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
|
|
RDCASSERT(record);
|
|
|
|
record->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
GetResourceManager()->AddLiveResource(id, res);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindBuffer(GLenum target, GLuint buffer)
|
|
{
|
|
SERIALISE_ELEMENT(GLenum, Target, target);
|
|
SERIALISE_ELEMENT(ResourceId, Id, (buffer ? GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)) : ResourceId()));
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
size_t idx = BufferIdx(target);
|
|
|
|
if(buffer != 0)
|
|
m_BufferRecord[idx]->datatype = Target;
|
|
}
|
|
else if(m_State < WRITING)
|
|
{
|
|
if(Id == ResourceId())
|
|
{
|
|
m_Real.glBindBuffer(Target, 0);
|
|
}
|
|
else
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(Id);
|
|
m_Real.glBindBuffer(Target, res.name);
|
|
|
|
m_Buffers[GetResourceManager()->GetLiveID(Id)].curType = Target;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindBuffer(GLenum target, GLuint buffer)
|
|
{
|
|
m_Real.glBindBuffer(target, buffer);
|
|
|
|
size_t idx = BufferIdx(target);
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
Chunk *chunk = NULL;
|
|
|
|
if(buffer == 0)
|
|
m_BufferRecord[idx] = NULL;
|
|
else
|
|
m_BufferRecord[idx] = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_BUFFER);
|
|
Serialise_glBindBuffer(target, buffer);
|
|
|
|
chunk = scope.Get();
|
|
}
|
|
|
|
m_ContextRecord->AddChunk(chunk);
|
|
}
|
|
|
|
if(buffer == 0)
|
|
{
|
|
m_BufferRecord[idx] = NULL;
|
|
return;
|
|
}
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_BufferRecord[idx] = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
|
|
// it's legal to re-type buffers, generate another BindBuffer chunk to rename
|
|
if(r->datatype != target)
|
|
{
|
|
Chunk *chunk = NULL;
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_BUFFER);
|
|
Serialise_glBindBuffer(target, buffer);
|
|
|
|
chunk = scope.Get();
|
|
}
|
|
|
|
r->AddChunk(chunk);
|
|
}
|
|
|
|
// element array buffer binding is vertex array record state, record there (if we've not just stopped)
|
|
if(m_State == WRITING_IDLE && target == eGL_ELEMENT_ARRAY_BUFFER && m_VertexArrayRecord && VertexArrayUpdateCheck())
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_BUFFER);
|
|
Serialise_glBindBuffer(target, buffer);
|
|
|
|
m_VertexArrayRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glNamedBufferStorageEXT(GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)));
|
|
SERIALISE_ELEMENT(uint64_t, Bytesize, (uint64_t)size);
|
|
|
|
byte *dummy = NULL;
|
|
|
|
if(m_State >= WRITING && data == NULL)
|
|
{
|
|
dummy = new byte[size];
|
|
data = dummy;
|
|
}
|
|
|
|
SERIALISE_ELEMENT_BUF(byte *, bytes, data, (size_t)Bytesize);
|
|
|
|
uint64_t offs = m_pSerialiser->GetOffset();
|
|
|
|
SERIALISE_ELEMENT(uint32_t, Flags, flags);
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glNamedBufferStorageEXT(res.name, (GLsizeiptr)Bytesize, bytes, Flags);
|
|
|
|
m_Buffers[GetResourceManager()->GetLiveID(id)].size = Bytesize;
|
|
|
|
SAFE_DELETE_ARRAY(bytes);
|
|
}
|
|
else if(m_State >= WRITING)
|
|
{
|
|
GetResourceManager()->GetResourceRecord(id)->SetDataOffset(offs - Bytesize);
|
|
}
|
|
|
|
if(dummy)
|
|
delete[] dummy;
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glNamedBufferStorageEXT(GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags)
|
|
{
|
|
m_Real.glNamedBufferStorageEXT(buffer, size, data, flags);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
RDCASSERT(record);
|
|
|
|
SCOPED_SERIALISE_CONTEXT(BUFFERSTORAGE);
|
|
Serialise_glNamedBufferStorageEXT(buffer, size, data, flags);
|
|
|
|
Chunk *chunk = scope.Get();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
m_ContextRecord->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
record->AddChunk(chunk);
|
|
record->SetDataPtr(chunk->GetData());
|
|
record->Length = (int32_t)size;
|
|
}
|
|
}
|
|
}
|
|
|
|
void WrappedOpenGL::glBufferStorage(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags)
|
|
{
|
|
m_Real.glBufferStorage(target, size, data, flags);
|
|
|
|
size_t idx = BufferIdx(target);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = m_BufferRecord[BufferIdx(target)];
|
|
RDCASSERT(record);
|
|
|
|
SCOPED_SERIALISE_CONTEXT(BUFFERSTORAGE);
|
|
Serialise_glNamedBufferStorageEXT(GetResourceManager()->GetCurrentResource(record->GetResourceID()).name,
|
|
size, data, flags);
|
|
|
|
Chunk *chunk = scope.Get();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
m_ContextRecord->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
record->AddChunk(chunk);
|
|
record->SetDataPtr(chunk->GetData());
|
|
record->Length = (int32_t)size;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glNamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const void *data, GLenum usage)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)));
|
|
SERIALISE_ELEMENT(uint64_t, Bytesize, (uint64_t)size);
|
|
|
|
byte *dummy = NULL;
|
|
|
|
if(m_State >= WRITING && data == NULL)
|
|
{
|
|
dummy = new byte[size];
|
|
data = dummy;
|
|
}
|
|
|
|
SERIALISE_ELEMENT_BUF(byte *, bytes, data, (size_t)Bytesize);
|
|
|
|
uint64_t offs = m_pSerialiser->GetOffset();
|
|
|
|
SERIALISE_ELEMENT(GLenum, Usage, usage);
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glNamedBufferDataEXT(res.name, (GLsizeiptr)Bytesize, bytes, Usage);
|
|
|
|
m_Buffers[GetResourceManager()->GetLiveID(id)].size = Bytesize;
|
|
|
|
SAFE_DELETE_ARRAY(bytes);
|
|
}
|
|
else if(m_State >= WRITING)
|
|
{
|
|
GetResourceManager()->GetResourceRecord(id)->SetDataOffset(offs - Bytesize);
|
|
}
|
|
|
|
if(dummy)
|
|
delete[] dummy;
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glNamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const void *data, GLenum usage)
|
|
{
|
|
m_Real.glNamedBufferDataEXT(buffer, size, data, usage);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
RDCASSERT(record);
|
|
|
|
// detect buffer orphaning and just update backing store
|
|
if(m_State == WRITING_IDLE && record->GetDataPtr() != NULL && size == record->Length && usage == record->usage)
|
|
{
|
|
if(data)
|
|
memcpy(record->GetDataPtr(), data, (size_t)size);
|
|
else
|
|
memset(record->GetDataPtr(), 0xbe, (size_t)size);
|
|
return;
|
|
}
|
|
|
|
SCOPED_SERIALISE_CONTEXT(BUFFERDATA);
|
|
Serialise_glNamedBufferDataEXT(buffer, size, data, usage);
|
|
|
|
Chunk *chunk = scope.Get();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
m_ContextRecord->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
record->AddChunk(chunk);
|
|
record->SetDataPtr(chunk->GetData());
|
|
record->Length = (int32_t)size;
|
|
record->usage = usage;
|
|
}
|
|
}
|
|
}
|
|
|
|
void WrappedOpenGL::glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
|
|
{
|
|
m_Real.glBufferData(target, size, data, usage);
|
|
|
|
size_t idx = BufferIdx(target);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = m_BufferRecord[BufferIdx(target)];
|
|
RDCASSERT(record);
|
|
|
|
// detect buffer orphaning and just update backing store
|
|
if(m_State == WRITING_IDLE && record->GetDataPtr() != NULL && size == record->Length && usage == record->usage)
|
|
{
|
|
if(data)
|
|
memcpy(record->GetDataPtr(), data, (size_t)size);
|
|
else
|
|
memset(record->GetDataPtr(), 0xbe, (size_t)size);
|
|
return;
|
|
}
|
|
|
|
SCOPED_SERIALISE_CONTEXT(BUFFERDATA);
|
|
Serialise_glNamedBufferDataEXT(GetResourceManager()->GetCurrentResource(record->GetResourceID()).name,
|
|
size, data, usage);
|
|
|
|
Chunk *chunk = scope.Get();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
m_ContextRecord->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
record->AddChunk(chunk);
|
|
record->SetDataPtr(chunk->GetData());
|
|
record->Length = (int32_t)size;
|
|
record->usage = usage;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glNamedBufferSubDataEXT(GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)));
|
|
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)offset);
|
|
SERIALISE_ELEMENT(uint64_t, Bytesize, (uint64_t)size);
|
|
SERIALISE_ELEMENT_BUF(byte *, bytes, data, (size_t)Bytesize);
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glNamedBufferSubDataEXT(res.name, (GLintptr)Offset, (GLsizeiptr)Bytesize, bytes);
|
|
|
|
SAFE_DELETE_ARRAY(bytes);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glNamedBufferSubDataEXT(GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data)
|
|
{
|
|
m_Real.glNamedBufferSubDataEXT(buffer, offset, size, data);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
if(m_HighTrafficResources.find(BufferRes(GetCtx(), buffer)) != m_HighTrafficResources.end() && m_State != WRITING_CAPFRAME)
|
|
return;
|
|
|
|
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
RDCASSERT(record);
|
|
|
|
SCOPED_SERIALISE_CONTEXT(BUFFERSUBDATA);
|
|
Serialise_glNamedBufferSubDataEXT(buffer, offset, size, data);
|
|
|
|
Chunk *chunk = scope.Get();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
m_ContextRecord->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
record->AddChunk(chunk);
|
|
record->UpdateCount++;
|
|
|
|
if(record->UpdateCount > 60)
|
|
{
|
|
m_HighTrafficResources.insert(BufferRes(GetCtx(), buffer));
|
|
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WrappedOpenGL::glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
|
|
{
|
|
m_Real.glBufferSubData(target, offset, size, data);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = m_BufferRecord[BufferIdx(target)];
|
|
RDCASSERT(record);
|
|
|
|
GLResource res = GetResourceManager()->GetCurrentResource(record->GetResourceID());
|
|
|
|
if(m_HighTrafficResources.find(res) != m_HighTrafficResources.end() && m_State != WRITING_CAPFRAME)
|
|
return;
|
|
|
|
SCOPED_SERIALISE_CONTEXT(BUFFERSUBDATA);
|
|
Serialise_glNamedBufferSubDataEXT(res.name, offset, size, data);
|
|
|
|
Chunk *chunk = scope.Get();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
m_ContextRecord->AddChunk(chunk);
|
|
else
|
|
{
|
|
record->AddChunk(chunk);
|
|
record->UpdateCount++;
|
|
|
|
if(record->UpdateCount > 60)
|
|
{
|
|
m_HighTrafficResources.insert(res);
|
|
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glNamedCopyBufferSubDataEXT(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, readid, GetResourceManager()->GetID(BufferRes(GetCtx(), readBuffer)));
|
|
SERIALISE_ELEMENT(ResourceId, writeid, GetResourceManager()->GetID(BufferRes(GetCtx(), writeBuffer)));
|
|
SERIALISE_ELEMENT(uint64_t, ReadOffset, (uint64_t)readOffset);
|
|
SERIALISE_ELEMENT(uint64_t, WriteOffset, (uint64_t)writeOffset);
|
|
SERIALISE_ELEMENT(uint64_t, Bytesize, (uint64_t)size);
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
GLResource readres = GetResourceManager()->GetLiveResource(readid);
|
|
GLResource writeres = GetResourceManager()->GetLiveResource(writeid);
|
|
m_Real.glNamedCopyBufferSubDataEXT(readres.name, writeres.name, (GLintptr)ReadOffset, (GLintptr)WriteOffset, (GLsizeiptr)Bytesize);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glNamedCopyBufferSubDataEXT(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
|
|
{
|
|
m_Real.glNamedCopyBufferSubDataEXT(readBuffer, writeBuffer, readOffset, writeOffset, size);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *readrecord = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), readBuffer));
|
|
GLResourceRecord *writerecord = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), writeBuffer));
|
|
RDCASSERT(readrecord && writerecord);
|
|
|
|
SCOPED_SERIALISE_CONTEXT(COPYBUFFERSUBDATA);
|
|
Serialise_glNamedCopyBufferSubDataEXT(readBuffer, writeBuffer, readOffset, writeOffset, size);
|
|
|
|
Chunk *chunk = scope.Get();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
m_ContextRecord->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
writerecord->AddChunk(chunk);
|
|
writerecord->AddParent(readrecord);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WrappedOpenGL::glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
|
|
{
|
|
m_Real.glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *readrecord = m_BufferRecord[BufferIdx(readTarget)];
|
|
GLResourceRecord *writerecord = m_BufferRecord[BufferIdx(writeTarget)];
|
|
RDCASSERT(readrecord && writerecord);
|
|
|
|
SCOPED_SERIALISE_CONTEXT(COPYBUFFERSUBDATA);
|
|
Serialise_glNamedCopyBufferSubDataEXT(GetResourceManager()->GetCurrentResource(readrecord->GetResourceID()).name,
|
|
GetResourceManager()->GetCurrentResource(writerecord->GetResourceID()).name,
|
|
readOffset, writeOffset, size);
|
|
|
|
Chunk *chunk = scope.Get();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
m_ContextRecord->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
writerecord->AddChunk(chunk);
|
|
writerecord->AddParent(readrecord);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
|
|
{
|
|
SERIALISE_ELEMENT(GLenum, Target, target);
|
|
SERIALISE_ELEMENT(uint32_t, Index, index);
|
|
SERIALISE_ELEMENT(ResourceId, id, (buffer ? GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)) : ResourceId()));
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id == ResourceId())
|
|
{
|
|
m_Real.glBindBuffer(Target, 0);
|
|
}
|
|
else
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindBufferBase(Target, Index, res.name);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
|
|
{
|
|
if(m_State >= WRITING && index == 0)
|
|
{
|
|
size_t idx = BufferIdx(target);
|
|
|
|
if(buffer == 0)
|
|
m_BufferRecord[idx] = NULL;
|
|
else
|
|
m_BufferRecord[idx] = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
}
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_BUFFER_BASE);
|
|
Serialise_glBindBufferBase(target, index, buffer);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
|
|
m_Real.glBindBufferBase(target, index, buffer);
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
|
|
{
|
|
SERIALISE_ELEMENT(GLenum, Target, target);
|
|
SERIALISE_ELEMENT(uint32_t, Index, index);
|
|
SERIALISE_ELEMENT(ResourceId, id, (buffer ? GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)) : ResourceId()));
|
|
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)offset);
|
|
SERIALISE_ELEMENT(uint64_t, Size, (uint64_t)size);
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id == ResourceId())
|
|
{
|
|
m_Real.glBindBuffer(Target, 0);
|
|
}
|
|
else
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindBufferRange(Target, Index, res.name, (GLintptr)Offset, (GLsizeiptr)Size);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
|
|
{
|
|
if(m_State >= WRITING && index == 0)
|
|
{
|
|
size_t idx = BufferIdx(target);
|
|
|
|
if(buffer == 0)
|
|
m_BufferRecord[idx] = NULL;
|
|
else
|
|
m_BufferRecord[idx] = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
}
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_BUFFER_RANGE);
|
|
Serialise_glBindBufferRange(target, index, buffer, offset, size);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
|
|
m_Real.glBindBufferRange(target, index, buffer, offset, size);
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindBuffersBase(GLenum target, GLuint first, GLsizei count, const GLuint *buffers)
|
|
{
|
|
SERIALISE_ELEMENT(GLenum, Target, target);
|
|
SERIALISE_ELEMENT(uint32_t, First, first);
|
|
SERIALISE_ELEMENT(int32_t, Count, count);
|
|
|
|
GLuint *bufs = NULL;
|
|
if(m_State <= EXECUTING) bufs = new GLuint[Count];
|
|
|
|
for(int32_t i=0; i < Count; i++)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), buffers[i])));
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
if(id != ResourceId())
|
|
bufs[i] = GetResourceManager()->GetLiveResource(id).name;
|
|
else
|
|
bufs[i] = 0;
|
|
}
|
|
}
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
m_Real.glBindBuffersBase(Target, First, Count, bufs);
|
|
|
|
delete[] bufs;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindBuffersBase(GLenum target, GLuint first, GLsizei count, const GLuint *buffers)
|
|
{
|
|
m_Real.glBindBuffersBase(target, first, count, buffers);
|
|
|
|
if(m_State >= WRITING && first == 0 && count > 0)
|
|
{
|
|
size_t idx = BufferIdx(target);
|
|
|
|
if(buffers[0] == 0)
|
|
m_BufferRecord[idx] = NULL;
|
|
else
|
|
m_BufferRecord[idx] = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffers[0]));
|
|
}
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_BUFFERS_BASE);
|
|
Serialise_glBindBuffersBase(target, first, count, buffers);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindBuffersRange(GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes)
|
|
{
|
|
SERIALISE_ELEMENT(GLenum, Target, target);
|
|
SERIALISE_ELEMENT(uint32_t, First, first);
|
|
SERIALISE_ELEMENT(int32_t, Count, count);
|
|
|
|
GLuint *bufs = NULL;
|
|
GLintptr *offs = NULL;
|
|
GLsizeiptr *sz = NULL;
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
bufs = new GLuint[Count];
|
|
offs = new GLintptr[Count];
|
|
sz = new GLsizeiptr[Count];
|
|
}
|
|
|
|
for(int32_t i=0; i < Count; i++)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), buffers[i])));
|
|
SERIALISE_ELEMENT(uint64_t, offset, (uint64_t)offsets[i]);
|
|
SERIALISE_ELEMENT(uint64_t, size, (uint64_t)sizes[i]);
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
if(id != ResourceId())
|
|
bufs[i] = GetResourceManager()->GetLiveResource(id).name;
|
|
else
|
|
bufs[i] = 0;
|
|
offs[i] = (GLintptr)offset;
|
|
sz[i] = (GLsizeiptr)sizes;
|
|
}
|
|
}
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
m_Real.glBindBuffersRange(Target, First, Count, bufs, offs, sz);
|
|
|
|
delete[] bufs;
|
|
delete[] offs;
|
|
delete[] sz;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindBuffersRange(GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes)
|
|
{
|
|
m_Real.glBindBuffersRange(target, first, count, buffers, offsets, sizes);
|
|
|
|
if(m_State >= WRITING && first == 0 && count > 0)
|
|
{
|
|
size_t idx = BufferIdx(target);
|
|
|
|
if(buffers[0] == 0)
|
|
m_BufferRecord[idx] = NULL;
|
|
else
|
|
m_BufferRecord[idx] = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffers[0]));
|
|
}
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_BUFFERS_RANGE);
|
|
Serialise_glBindBuffersRange(target, first, count, buffers, offsets, sizes);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
void WrappedOpenGL::glInvalidateBufferData(GLuint buffer)
|
|
{
|
|
m_Real.glInvalidateBufferData(buffer);
|
|
|
|
if(m_State == WRITING_IDLE)
|
|
GetResourceManager()->MarkDirtyResource(BufferRes(GetCtx(), buffer));
|
|
}
|
|
|
|
void WrappedOpenGL::glInvalidateBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr length)
|
|
{
|
|
m_Real.glInvalidateBufferSubData(buffer, offset, length);
|
|
|
|
if(m_State == WRITING_IDLE)
|
|
GetResourceManager()->MarkDirtyResource(BufferRes(GetCtx(), buffer));
|
|
}
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Mapping
|
|
|
|
void *WrappedOpenGL::glMapNamedBufferEXT(GLuint buffer, GLenum access)
|
|
{
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
|
|
GLint length;
|
|
m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, &length);
|
|
|
|
bool straightUp = false;
|
|
if(m_HighTrafficResources.find(BufferRes(GetCtx(), buffer)) != m_HighTrafficResources.end() && m_State != WRITING_CAPFRAME)
|
|
straightUp = true;
|
|
|
|
if(GetResourceManager()->IsResourceDirty(record->GetResourceID()) && m_State != WRITING_CAPFRAME)
|
|
straightUp = true;
|
|
|
|
if(!straightUp && (access == eGL_WRITE_ONLY || access == eGL_READ_WRITE) && m_State != WRITING_CAPFRAME)
|
|
{
|
|
straightUp = true;
|
|
m_HighTrafficResources.insert(BufferRes(GetCtx(), buffer));
|
|
if(m_State != WRITING_CAPFRAME)
|
|
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
|
|
}
|
|
|
|
record->Map.offset = 0;
|
|
record->Map.length = length;
|
|
record->Map.invalidate = false;
|
|
if(access == eGL_READ_ONLY) record->Map.access = GL_MAP_READ_BIT;
|
|
else if(access == eGL_WRITE_ONLY) record->Map.access = GL_MAP_WRITE_BIT;
|
|
else if(access == eGL_READ_WRITE) record->Map.access = GL_MAP_READ_BIT|GL_MAP_WRITE_BIT;
|
|
|
|
if(straightUp && m_State == WRITING_IDLE)
|
|
{
|
|
record->Map.ptr = (byte *)m_Real.glMapNamedBufferEXT(buffer, access);
|
|
record->Map.status = GLResourceRecord::Mapped_Ignore_Real;
|
|
|
|
return record->Map.ptr;
|
|
}
|
|
|
|
// TODO align return pointer to GL_MIN_MAP_BUFFER_ALIGNMENT (min 64)
|
|
|
|
if(access == eGL_READ_ONLY)
|
|
{
|
|
record->Map.status = GLResourceRecord::Mapped_Read_Real;
|
|
return m_Real.glMapNamedBufferEXT(buffer, access);
|
|
}
|
|
|
|
byte *ptr = record->GetDataPtr();
|
|
|
|
if(ptr == NULL)
|
|
{
|
|
RDCWARN("Mapping buffer that hasn't been allocated");
|
|
|
|
ptr = (byte *)m_Real.glMapNamedBufferEXT(buffer, access);
|
|
|
|
record->Map.ptr = ptr;
|
|
record->Map.status = GLResourceRecord::Mapped_Write_Real;
|
|
}
|
|
else
|
|
{
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
byte *shadow = (byte *)record->GetShadowPtr(0);
|
|
|
|
if(shadow == NULL)
|
|
{
|
|
record->AllocShadowStorage(length);
|
|
shadow = (byte *)record->GetShadowPtr(0);
|
|
|
|
if(GetResourceManager()->IsResourceDirty(record->GetResourceID()))
|
|
{
|
|
// TODO get contents from frame initial state
|
|
|
|
m_Real.glGetNamedBufferSubDataEXT(buffer, 0, length, ptr);
|
|
memcpy(shadow, ptr, length);
|
|
}
|
|
else
|
|
{
|
|
memcpy(shadow, ptr, length);
|
|
}
|
|
|
|
memcpy(record->GetShadowPtr(1), shadow, length);
|
|
}
|
|
|
|
record->Map.ptr = ptr = shadow;
|
|
record->Map.status = GLResourceRecord::Mapped_Write;
|
|
}
|
|
else
|
|
{
|
|
record->Map.ptr = ptr;
|
|
record->Map.status = GLResourceRecord::Mapped_Write;
|
|
|
|
record->UpdateCount++;
|
|
|
|
if(record->UpdateCount > 60)
|
|
m_HighTrafficResources.insert(BufferRes(GetCtx(), buffer));
|
|
}
|
|
}
|
|
|
|
m_Real.glGetNamedBufferSubDataEXT(buffer, 0, length, ptr);
|
|
|
|
return ptr;
|
|
}
|
|
|
|
return m_Real.glMapNamedBufferEXT(buffer, access);
|
|
}
|
|
|
|
void *WrappedOpenGL::glMapBuffer(GLenum target, GLenum access)
|
|
{
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = m_BufferRecord[BufferIdx(target)];
|
|
RDCASSERT(m_BufferRecord[BufferIdx(target)]);
|
|
|
|
if(record)
|
|
return glMapNamedBufferEXT(GetResourceManager()->GetCurrentResource(record->GetResourceID()).name, access);
|
|
|
|
RDCERR("glMapBuffer: Couldn't get resource record for target %x - no buffer bound?", target);
|
|
}
|
|
|
|
return m_Real.glMapBuffer(target, access);
|
|
}
|
|
|
|
void *WrappedOpenGL::glMapNamedBufferRangeEXT(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access)
|
|
{
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
|
|
bool straightUp = false;
|
|
if(m_HighTrafficResources.find(BufferRes(GetCtx(), buffer)) != m_HighTrafficResources.end() && m_State != WRITING_CAPFRAME)
|
|
straightUp = true;
|
|
|
|
if(GetResourceManager()->IsResourceDirty(record->GetResourceID()) && m_State != WRITING_CAPFRAME)
|
|
straightUp = true;
|
|
|
|
bool invalidateMap = (access & (GL_MAP_INVALIDATE_BUFFER_BIT|GL_MAP_INVALIDATE_RANGE_BIT)) != 0;
|
|
|
|
if(!straightUp && !invalidateMap && (access & GL_MAP_WRITE_BIT) && m_State != WRITING_CAPFRAME)
|
|
{
|
|
straightUp = true;
|
|
m_HighTrafficResources.insert(BufferRes(GetCtx(), buffer));
|
|
if(m_State != WRITING_CAPFRAME)
|
|
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
|
|
}
|
|
|
|
record->Map.offset = offset;
|
|
record->Map.length = length;
|
|
record->Map.access = access;
|
|
record->Map.invalidate = invalidateMap;
|
|
|
|
if(straightUp && m_State == WRITING_IDLE)
|
|
{
|
|
record->Map.ptr = (byte *)m_Real.glMapNamedBufferRangeEXT(buffer, offset, length, access);
|
|
record->Map.status = GLResourceRecord::Mapped_Ignore_Real;
|
|
|
|
return record->Map.ptr;
|
|
}
|
|
|
|
// TODO align return pointer to GL_MIN_MAP_BUFFER_ALIGNMENT (min 64)
|
|
|
|
if((access & (GL_MAP_COHERENT_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_FLUSH_EXPLICIT_BIT|GL_MAP_UNSYNCHRONIZED_BIT)) != 0)
|
|
RDCUNIMPLEMENTED("haven't implemented coherent/persistant/flush explicit/unsynchronized glMap calls");
|
|
|
|
if((access & GL_MAP_READ_BIT) != 0)
|
|
{
|
|
byte *ptr = record->GetDataPtr();
|
|
|
|
if(ptr == NULL)
|
|
{
|
|
RDCWARN("Mapping buffer that hasn't been allocated");
|
|
|
|
record->Map.status = GLResourceRecord::Mapped_Read_Real;
|
|
return m_Real.glMapNamedBufferRangeEXT(buffer, offset, length, access);
|
|
}
|
|
|
|
ptr += offset;
|
|
|
|
m_Real.glGetNamedBufferSubDataEXT(buffer, offset, length, ptr);
|
|
|
|
record->Map.status = GLResourceRecord::Mapped_Read;
|
|
|
|
return ptr;
|
|
}
|
|
|
|
byte *ptr = record->GetDataPtr();
|
|
|
|
if(ptr == NULL)
|
|
{
|
|
RDCWARN("Mapping buffer that hasn't been allocated");
|
|
|
|
ptr = (byte *)m_Real.glMapNamedBufferRangeEXT(buffer, offset, length, access);
|
|
|
|
record->Map.ptr = ptr;
|
|
record->Map.status = GLResourceRecord::Mapped_Write_Real;
|
|
}
|
|
else
|
|
{
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
byte *shadow = (byte *)record->GetShadowPtr(0);
|
|
|
|
if(shadow == NULL)
|
|
{
|
|
GLint buflength;
|
|
m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, &buflength);
|
|
|
|
record->AllocShadowStorage(buflength);
|
|
shadow = (byte *)record->GetShadowPtr(0);
|
|
|
|
if(!invalidateMap)
|
|
{
|
|
if(GetResourceManager()->IsResourceDirty(record->GetResourceID()))
|
|
{
|
|
// TODO get contents from frame initial state
|
|
|
|
m_Real.glGetNamedBufferSubDataEXT(buffer, 0, buflength, ptr);
|
|
memcpy(shadow, ptr, buflength);
|
|
|
|
}
|
|
else
|
|
{
|
|
memcpy(shadow+offset, ptr+offset, length);
|
|
}
|
|
}
|
|
|
|
memcpy(record->GetShadowPtr(1), shadow, buflength);
|
|
}
|
|
|
|
if(invalidateMap)
|
|
{
|
|
memset(shadow+offset, 0xcc, length);
|
|
memset(record->GetShadowPtr(1)+offset, 0xcc, length);
|
|
}
|
|
|
|
record->Map.ptr = ptr = shadow;
|
|
record->Map.status = GLResourceRecord::Mapped_Write;
|
|
}
|
|
else
|
|
{
|
|
ptr += offset;
|
|
|
|
record->Map.ptr = ptr;
|
|
record->Map.status = GLResourceRecord::Mapped_Write;
|
|
|
|
record->UpdateCount++;
|
|
|
|
if(record->UpdateCount > 60)
|
|
m_HighTrafficResources.insert(BufferRes(GetCtx(), buffer));
|
|
}
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
return m_Real.glMapNamedBufferRangeEXT(buffer, offset, length, access);
|
|
}
|
|
|
|
void *WrappedOpenGL::glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
|
|
{
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = m_BufferRecord[BufferIdx(target)];
|
|
RDCASSERT(m_BufferRecord[BufferIdx(target)]);
|
|
|
|
if(record)
|
|
return glMapNamedBufferRangeEXT(GetResourceManager()->GetCurrentResource(record->GetResourceID()).name, offset, length, access);
|
|
|
|
RDCERR("glMapBufferRange: Couldn't get resource record for target %x - no buffer bound?", target);
|
|
}
|
|
|
|
return m_Real.glMapBufferRange(target, offset, length, access);
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glUnmapNamedBufferEXT(GLuint buffer)
|
|
{
|
|
GLResourceRecord *record = NULL;
|
|
|
|
if(m_State >= WRITING)
|
|
record = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
|
|
ResourceId bufID;
|
|
uint64_t offs = 0;
|
|
uint64_t len = 0;
|
|
|
|
if(m_State < WRITING || m_State == WRITING_CAPFRAME)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, ID, record->GetResourceID());
|
|
SERIALISE_ELEMENT(uint64_t, offset, record->Map.offset);
|
|
SERIALISE_ELEMENT(uint64_t, length, record->Map.length);
|
|
|
|
bufID = ID;
|
|
offs = offset;
|
|
len = length;
|
|
}
|
|
else if(m_State == WRITING_IDLE)
|
|
{
|
|
bufID = record->GetResourceID();
|
|
offs = record->Map.offset;
|
|
len = record->Map.length;
|
|
|
|
void *ptr = m_Real.glMapNamedBufferRangeEXT(buffer, (GLintptr)offs, (GLsizeiptr)len, GL_MAP_WRITE_BIT);
|
|
memcpy(ptr, record->Map.ptr, (size_t)len);
|
|
m_Real.glUnmapNamedBufferEXT(buffer);
|
|
return true;
|
|
}
|
|
|
|
uint64_t bufBindStart = 0;
|
|
|
|
size_t diffStart = 0;
|
|
size_t diffEnd = (size_t)len;
|
|
|
|
if(m_State == WRITING_CAPFRAME && len > 512 && !record->Map.invalidate)
|
|
{
|
|
bool found = FindDiffRange(record->Map.ptr, record->GetShadowPtr(1), (size_t)len, diffStart, diffEnd);
|
|
if(found)
|
|
{
|
|
static size_t saved = 0;
|
|
|
|
saved += (size_t)len - (diffEnd-diffStart);
|
|
|
|
RDCDEBUG("Mapped resource size %u, difference: %u -> %u. Total bytes saved so far: %u",
|
|
(uint32_t)len, (uint32_t)diffStart, (uint32_t)diffEnd, (uint32_t)saved);
|
|
|
|
len = diffEnd-diffStart;
|
|
}
|
|
else
|
|
{
|
|
diffStart = 0;
|
|
diffEnd = 0;
|
|
|
|
len = 1;
|
|
}
|
|
}
|
|
|
|
if(m_State == WRITING_CAPFRAME && record->GetShadowPtr(1))
|
|
{
|
|
memcpy(record->GetShadowPtr(1)+diffStart, record->Map.ptr+diffStart, diffEnd-diffStart);
|
|
}
|
|
|
|
SERIALISE_ELEMENT(uint32_t, DiffStart, (uint32_t)diffStart);
|
|
SERIALISE_ELEMENT(uint32_t, DiffEnd, (uint32_t)diffEnd);
|
|
|
|
SERIALISE_ELEMENT_BUF(byte *, data, record->Map.ptr+diffStart, (size_t)len);
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(bufID);
|
|
buffer = res.name;
|
|
}
|
|
|
|
if(DiffEnd > DiffStart)
|
|
{
|
|
void *ptr = m_Real.glMapNamedBufferRangeEXT(buffer, (GLintptr)(offs+DiffStart), GLsizeiptr(DiffEnd-DiffStart), GL_MAP_WRITE_BIT);
|
|
memcpy(ptr, data, size_t(DiffEnd-DiffStart));
|
|
m_Real.glUnmapNamedBufferEXT(buffer);
|
|
}
|
|
|
|
if(m_State < WRITING)
|
|
delete[] data;
|
|
|
|
return true;
|
|
}
|
|
|
|
GLboolean WrappedOpenGL::glUnmapNamedBufferEXT(GLuint buffer)
|
|
{
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(BufferRes(GetCtx(), buffer));
|
|
auto status = record->Map.status;
|
|
|
|
GLboolean ret = GL_TRUE;
|
|
|
|
switch(status)
|
|
{
|
|
case GLResourceRecord::Unmapped:
|
|
RDCERR("Unmapped buffer being passed to glUnmapBuffer");
|
|
break;
|
|
case GLResourceRecord::Mapped_Read:
|
|
// can ignore
|
|
break;
|
|
case GLResourceRecord::Mapped_Ignore_Real:
|
|
if(m_State == WRITING_CAPFRAME)
|
|
RDCWARN("Failed to cap frame - uncapped Map/Unmap");
|
|
// deliberate fallthrough
|
|
case GLResourceRecord::Mapped_Read_Real:
|
|
// need to do real unmap
|
|
ret = m_Real.glUnmapNamedBufferEXT(buffer);
|
|
break;
|
|
case GLResourceRecord::Mapped_Write:
|
|
{
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(UNMAP);
|
|
Serialise_glUnmapNamedBufferEXT(buffer);
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
else
|
|
Serialise_glUnmapNamedBufferEXT(buffer);
|
|
|
|
break;
|
|
}
|
|
case GLResourceRecord::Mapped_Write_Real:
|
|
{
|
|
// Throwing away map contents as we don't have datastore allocated
|
|
// Could init chunk here using known data (although maybe it's only partial).
|
|
ret = m_Real.glUnmapNamedBufferEXT(buffer);
|
|
|
|
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
|
|
break;
|
|
}
|
|
}
|
|
|
|
record->Map.status = GLResourceRecord::Unmapped;
|
|
|
|
return ret;
|
|
}
|
|
|
|
return m_Real.glUnmapNamedBufferEXT(buffer);
|
|
}
|
|
|
|
GLboolean WrappedOpenGL::glUnmapBuffer(GLenum target)
|
|
{
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *record = m_BufferRecord[BufferIdx(target)];
|
|
RDCASSERT(m_BufferRecord[BufferIdx(target)]);
|
|
|
|
if(record)
|
|
return glUnmapNamedBufferEXT( GetResourceManager()->GetCurrentResource(record->GetResourceID()).name );
|
|
|
|
RDCERR("glUnmapBuffer: Couldn't get resource record for target %x - no buffer bound?", target);
|
|
}
|
|
|
|
return m_Real.glUnmapBuffer(target);
|
|
}
|
|
|
|
void WrappedOpenGL::glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
|
|
{
|
|
m_Real.glFlushMappedBufferRange(target, offset, length);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
RDCUNIMPLEMENTED("Persistant/unsynchronised/explicit flash maps are not yet supported");
|
|
}
|
|
}
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Transform Feedback
|
|
|
|
bool WrappedOpenGL::Serialise_glGenTransformFeedbacks(GLsizei n, GLuint* ids)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(FeedbackRes(GetCtx(), *ids)));
|
|
|
|
if(m_State == READING)
|
|
{
|
|
GLuint real = 0;
|
|
m_Real.glGenTransformFeedbacks(1, &real);
|
|
|
|
GLResource res = FeedbackRes(GetCtx(), real);
|
|
|
|
m_ResourceManager->RegisterResource(res);
|
|
GetResourceManager()->AddLiveResource(id, res);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glGenTransformFeedbacks(GLsizei n, GLuint *ids)
|
|
{
|
|
m_Real.glGenTransformFeedbacks(n, ids);
|
|
|
|
for(GLsizei i=0; i < n; i++)
|
|
{
|
|
GLResource res = FeedbackRes(GetCtx(), ids[i]);
|
|
ResourceId id = GetResourceManager()->RegisterResource(res);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
Chunk *chunk = NULL;
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(GEN_FEEDBACK);
|
|
Serialise_glGenTransformFeedbacks(1, ids+i);
|
|
|
|
chunk = scope.Get();
|
|
}
|
|
|
|
GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
|
|
RDCASSERT(record);
|
|
|
|
record->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
GetResourceManager()->AddLiveResource(id, res);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WrappedOpenGL::glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
|
|
{
|
|
for(GLsizei i=0; i < n; i++)
|
|
{
|
|
GLResource res = FeedbackRes(GetCtx(), ids[i]);
|
|
if(GetResourceManager()->HasCurrentResource(res))
|
|
{
|
|
if(GetResourceManager()->HasResourceRecord(res))
|
|
GetResourceManager()->GetResourceRecord(res)->Delete(GetResourceManager());
|
|
GetResourceManager()->UnregisterResource(res);
|
|
}
|
|
}
|
|
|
|
m_Real.glDeleteTransformFeedbacks(n, ids);
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindTransformFeedback(GLenum target, GLuint id)
|
|
{
|
|
SERIALISE_ELEMENT(GLenum, Target, target);
|
|
SERIALISE_ELEMENT(ResourceId, fid, GetResourceManager()->GetID(FeedbackRes(GetCtx(), id)));
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
m_Real.glBindTransformFeedback(Target, GetResourceManager()->GetLiveResource(fid).name);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindTransformFeedback(GLenum target, GLuint id)
|
|
{
|
|
m_Real.glBindTransformFeedback(target, id);
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_FEEDBACK);
|
|
Serialise_glBindTransformFeedback(target, id);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBeginTransformFeedback(GLenum primitiveMode)
|
|
{
|
|
SERIALISE_ELEMENT(GLenum, Mode, primitiveMode);
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
m_Real.glBeginTransformFeedback(Mode);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBeginTransformFeedback(GLenum primitiveMode)
|
|
{
|
|
m_Real.glBeginTransformFeedback(primitiveMode);
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BEGIN_FEEDBACK);
|
|
Serialise_glBeginTransformFeedback(primitiveMode);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glPauseTransformFeedback()
|
|
{
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
m_Real.glPauseTransformFeedback();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glPauseTransformFeedback()
|
|
{
|
|
m_Real.glPauseTransformFeedback();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(PAUSE_FEEDBACK);
|
|
Serialise_glPauseTransformFeedback();
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glResumeTransformFeedback()
|
|
{
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
m_Real.glResumeTransformFeedback();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glResumeTransformFeedback()
|
|
{
|
|
m_Real.glResumeTransformFeedback();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(RESUME_FEEDBACK);
|
|
Serialise_glResumeTransformFeedback();
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glEndTransformFeedback()
|
|
{
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
m_Real.glEndTransformFeedback();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glEndTransformFeedback()
|
|
{
|
|
m_Real.glEndTransformFeedback();
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(END_FEEDBACK);
|
|
Serialise_glEndTransformFeedback();
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Vertex Arrays
|
|
|
|
bool WrappedOpenGL::VertexArrayUpdateCheck()
|
|
{
|
|
// if no VAO is bound, nothing to check
|
|
if(m_VertexArrayRecord == NULL) return true;
|
|
|
|
// if we've already stopped tracking this VAO, return as such
|
|
if(m_VertexArrayRecord && m_VertexArrayRecord->UpdateCount > 64)
|
|
return false;
|
|
|
|
// increase update count
|
|
m_VertexArrayRecord->UpdateCount++;
|
|
|
|
// if update count is high, mark as dirty
|
|
if(m_VertexArrayRecord && m_VertexArrayRecord->UpdateCount > 64)
|
|
{
|
|
GetResourceManager()->MarkDirtyResource( m_VertexArrayRecord->GetResourceID() );
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, index);
|
|
SERIALISE_ELEMENT(int32_t, Size, size);
|
|
SERIALISE_ELEMENT(GLenum, Type, type);
|
|
SERIALISE_ELEMENT(uint8_t, Norm, normalized);
|
|
SERIALISE_ELEMENT(uint32_t, Stride, stride);
|
|
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)pointer);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glVertexAttribPointer(Index, Size, Type, Norm, Stride, (const void *)Offset);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer)
|
|
{
|
|
m_Real.glVertexAttribPointer(index, size, type, normalized, stride, pointer);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIBPOINTER);
|
|
Serialise_glVertexAttribPointer(index, size, type, normalized, stride, pointer);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, index);
|
|
SERIALISE_ELEMENT(int32_t, Size, size);
|
|
SERIALISE_ELEMENT(GLenum, Type, type);
|
|
SERIALISE_ELEMENT(uint32_t, Stride, stride);
|
|
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)pointer);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glVertexAttribIPointer(Index, Size, Type, Stride, (const void *)Offset);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
|
|
{
|
|
m_Real.glVertexAttribIPointer(index, size, type, stride, pointer);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIBIPOINTER);
|
|
Serialise_glVertexAttribIPointer(index, size, type, stride, pointer);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttribLPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, index);
|
|
SERIALISE_ELEMENT(int32_t, Size, size);
|
|
SERIALISE_ELEMENT(GLenum, Type, type);
|
|
SERIALISE_ELEMENT(uint32_t, Stride, stride);
|
|
SERIALISE_ELEMENT(uint64_t, Offset, (uint64_t)pointer);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glVertexAttribLPointer(Index, Size, Type, Stride, (const void *)Offset);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexAttribLPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
|
|
{
|
|
m_Real.glVertexAttribLPointer(index, size, type, stride, pointer);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIBLPOINTER);
|
|
Serialise_glVertexAttribLPointer(index, size, type, stride, pointer);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttribBinding(GLuint attribindex, GLuint bindingindex)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, aidx, attribindex);
|
|
SERIALISE_ELEMENT(uint32_t, bidx, bindingindex);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glVertexAttribBinding(aidx, bidx);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexAttribBinding(GLuint attribindex, GLuint bindingindex)
|
|
{
|
|
m_Real.glVertexAttribBinding(attribindex, bindingindex);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIBBINDING);
|
|
Serialise_glVertexAttribBinding(attribindex, bindingindex);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, attribindex);
|
|
SERIALISE_ELEMENT(int32_t, Size, size);
|
|
SERIALISE_ELEMENT(bool, Norm, normalized ? true : false);
|
|
SERIALISE_ELEMENT(GLenum, Type, type);
|
|
SERIALISE_ELEMENT(uint32_t, Offset, relativeoffset);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glVertexAttribFormat(Index, Size, Type, Norm, Offset);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset)
|
|
{
|
|
m_Real.glVertexAttribFormat(attribindex, size, type, normalized, relativeoffset);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIBFORMAT);
|
|
Serialise_glVertexAttribFormat(attribindex, size, type, normalized, relativeoffset);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttribIFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, attribindex);
|
|
SERIALISE_ELEMENT(int32_t, Size, size);
|
|
SERIALISE_ELEMENT(GLenum, Type, type);
|
|
SERIALISE_ELEMENT(uint32_t, Offset, relativeoffset);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glVertexAttribIFormat(Index, Size, Type, Offset);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexAttribIFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)
|
|
{
|
|
m_Real.glVertexAttribIFormat(attribindex, size, type, relativeoffset);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIBIFORMAT);
|
|
Serialise_glVertexAttribIFormat(attribindex, size, type, relativeoffset);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttribLFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, attribindex);
|
|
SERIALISE_ELEMENT(int32_t, Size, size);
|
|
SERIALISE_ELEMENT(GLenum, Type, type);
|
|
SERIALISE_ELEMENT(uint32_t, Offset, relativeoffset);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glVertexAttribLFormat(Index, Size, Type, Offset);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexAttribLFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)
|
|
{
|
|
m_Real.glVertexAttribLFormat(attribindex, size, type, relativeoffset);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIBLFORMAT);
|
|
Serialise_glVertexAttribLFormat(attribindex, size, type, relativeoffset);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttribDivisor(GLuint index, GLuint divisor)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, index);
|
|
SERIALISE_ELEMENT(uint32_t, Divisor, divisor);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glVertexAttribDivisor(Index, Divisor);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexAttribDivisor(GLuint index, GLuint divisor)
|
|
{
|
|
m_Real.glVertexAttribDivisor(index, divisor);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIBDIVISOR);
|
|
Serialise_glVertexAttribDivisor(index, divisor);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glEnableVertexAttribArray(GLuint index)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, index);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glEnableVertexAttribArray(Index);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glEnableVertexAttribArray(GLuint index)
|
|
{
|
|
m_Real.glEnableVertexAttribArray(index);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(ENABLEVERTEXATTRIBARRAY);
|
|
Serialise_glEnableVertexAttribArray(index);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glDisableVertexAttribArray(GLuint index)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, Index, index);
|
|
SERIALISE_ELEMENT(ResourceId, id, m_VertexArrayRecord ? m_VertexArrayRecord->GetResourceID() : ResourceId());
|
|
|
|
if(m_State < WRITING)
|
|
{
|
|
if(id != ResourceId())
|
|
{
|
|
GLResource res = GetResourceManager()->GetLiveResource(id);
|
|
m_Real.glBindVertexArray(res.name);
|
|
}
|
|
else
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
|
|
m_Real.glDisableVertexAttribArray(Index);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glDisableVertexAttribArray(GLuint index)
|
|
{
|
|
m_Real.glDisableVertexAttribArray(index);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
GLResourceRecord *r = m_State == WRITING_CAPFRAME ? m_ContextRecord : m_VertexArrayRecord;
|
|
|
|
if(r)
|
|
{
|
|
if(m_State == WRITING_IDLE && !VertexArrayUpdateCheck())
|
|
return;
|
|
if(m_State == WRITING_CAPFRAME && m_VertexArrayRecord)
|
|
GetResourceManager()->MarkResourceFrameReferenced(m_VertexArrayRecord->GetResourceID(), eFrameRef_Write);
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(DISABLEVERTEXATTRIBARRAY);
|
|
Serialise_glDisableVertexAttribArray(index);
|
|
|
|
r->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glGenVertexArrays(GLsizei n, GLuint* arrays)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(VertexArrayRes(GetCtx(), *arrays)));
|
|
|
|
if(m_State == READING)
|
|
{
|
|
GLuint real = 0;
|
|
m_Real.glGenVertexArrays(1, &real);
|
|
|
|
GLResource res = VertexArrayRes(GetCtx(), real);
|
|
|
|
m_ResourceManager->RegisterResource(res);
|
|
GetResourceManager()->AddLiveResource(id, res);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glGenVertexArrays(GLsizei n, GLuint *arrays)
|
|
{
|
|
m_Real.glGenVertexArrays(n, arrays);
|
|
|
|
for(GLsizei i=0; i < n; i++)
|
|
{
|
|
GLResource res = VertexArrayRes(GetCtx(), arrays[i]);
|
|
ResourceId id = GetResourceManager()->RegisterResource(res);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
Chunk *chunk = NULL;
|
|
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(GEN_VERTEXARRAY);
|
|
Serialise_glGenVertexArrays(1, arrays+i);
|
|
|
|
chunk = scope.Get();
|
|
}
|
|
|
|
GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
|
|
RDCASSERT(record);
|
|
|
|
record->AddChunk(chunk);
|
|
}
|
|
else
|
|
{
|
|
GetResourceManager()->AddLiveResource(id, res);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindVertexArray(GLuint array)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, (array ? GetResourceManager()->GetID(VertexArrayRes(GetCtx(), array)) : ResourceId()));
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
if(id == ResourceId())
|
|
{
|
|
m_Real.glBindVertexArray(0);
|
|
}
|
|
else
|
|
{
|
|
GLuint live = GetResourceManager()->GetLiveResource(id).name;
|
|
m_Real.glBindVertexArray(live);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindVertexArray(GLuint array)
|
|
{
|
|
m_Real.glBindVertexArray(array);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
if(array == 0)
|
|
{
|
|
m_VertexArrayRecord = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_VertexArrayRecord = GetResourceManager()->GetResourceRecord(VertexArrayRes(GetCtx(), array));
|
|
}
|
|
}
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_VERTEXARRAY);
|
|
Serialise_glBindVertexArray(array);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, idx, bindingindex);
|
|
SERIALISE_ELEMENT(ResourceId, id, (buffer ? GetResourceManager()->GetID(BufferRes(GetCtx(), buffer)) : ResourceId()));
|
|
SERIALISE_ELEMENT(uint64_t, offs, offset);
|
|
SERIALISE_ELEMENT(uint64_t, str, stride);
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
GLuint live = 0;
|
|
if(id != ResourceId())
|
|
live = GetResourceManager()->GetLiveResource(id).name;
|
|
|
|
m_Real.glBindVertexBuffer(idx, live, (GLintptr)offs, (GLsizei)str);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride)
|
|
{
|
|
m_Real.glBindVertexBuffer(bindingindex, buffer, offset, stride);
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_VERTEXBUFFER);
|
|
Serialise_glBindVertexBuffer(bindingindex, buffer, offset, stride);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glBindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, First, first);
|
|
SERIALISE_ELEMENT(int32_t, Count, count);
|
|
|
|
GLuint *bufs = NULL;
|
|
GLintptr *offs = NULL;
|
|
GLsizei *str = NULL;
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
bufs = new GLuint[Count];
|
|
offs = new GLintptr[Count];
|
|
str = new GLsizei[Count];
|
|
}
|
|
|
|
for(int32_t i=0; i < Count; i++)
|
|
{
|
|
SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(BufferRes(GetCtx(), buffers[i])));
|
|
SERIALISE_ELEMENT(uint64_t, offset, (uint64_t)offsets[i]);
|
|
SERIALISE_ELEMENT(uint64_t, stride, (uint64_t)strides[i]);
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
if(id != ResourceId())
|
|
bufs[i] = GetResourceManager()->GetLiveResource(id).name;
|
|
else
|
|
bufs[i] = 0;
|
|
offs[i] = (GLintptr)offset;
|
|
str[i] = (GLsizei)stride;
|
|
}
|
|
}
|
|
|
|
if(m_State <= EXECUTING)
|
|
{
|
|
m_Real.glBindVertexBuffers(First, Count, bufs, offs, str);
|
|
|
|
delete[] bufs;
|
|
delete[] offs;
|
|
delete[] str;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glBindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides)
|
|
{
|
|
m_Real.glBindVertexBuffers(first, count, buffers, offsets, strides);
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(BIND_VERTEXBUFFERS);
|
|
Serialise_glBindVertexBuffers(first, count, buffers, offsets, strides);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexBindingDivisor(GLuint bindingindex, GLuint divisor)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, idx, bindingindex);
|
|
SERIALISE_ELEMENT(uint32_t, d, divisor);
|
|
|
|
if(m_State <= EXECUTING)
|
|
m_Real.glVertexBindingDivisor(idx, d);
|
|
|
|
return true;
|
|
}
|
|
|
|
void WrappedOpenGL::glVertexBindingDivisor(GLuint bindingindex, GLuint divisor)
|
|
{
|
|
m_Real.glVertexBindingDivisor(bindingindex, divisor);
|
|
|
|
if(m_State == WRITING_CAPFRAME)
|
|
{
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXBINDINGDIVISOR);
|
|
Serialise_glVertexBindingDivisor(bindingindex, divisor);
|
|
|
|
m_ContextRecord->AddChunk(scope.Get());
|
|
}
|
|
}
|
|
|
|
void WrappedOpenGL::glDeleteBuffers(GLsizei n, const GLuint *buffers)
|
|
{
|
|
for(GLsizei i=0; i < n; i++)
|
|
{
|
|
GLResource res = BufferRes(GetCtx(), buffers[i]);
|
|
if(GetResourceManager()->HasCurrentResource(res))
|
|
{
|
|
if(GetResourceManager()->HasResourceRecord(res))
|
|
GetResourceManager()->GetResourceRecord(res)->Delete(GetResourceManager());
|
|
GetResourceManager()->UnregisterResource(res);
|
|
}
|
|
}
|
|
|
|
m_Real.glDeleteBuffers(n, buffers);
|
|
}
|
|
|
|
void WrappedOpenGL::glDeleteVertexArrays(GLsizei n, const GLuint *arrays)
|
|
{
|
|
for(GLsizei i=0; i < n; i++)
|
|
{
|
|
GLResource res = VertexArrayRes(GetCtx(), arrays[i]);
|
|
if(GetResourceManager()->HasCurrentResource(res))
|
|
{
|
|
if(GetResourceManager()->HasResourceRecord(res))
|
|
GetResourceManager()->GetResourceRecord(res)->Delete(GetResourceManager());
|
|
GetResourceManager()->UnregisterResource(res);
|
|
}
|
|
}
|
|
|
|
m_Real.glDeleteVertexArrays(n, arrays);
|
|
}
|
|
|
|
#pragma endregion
|
|
|
|
#pragma region Horrible glVertexAttrib variants
|
|
|
|
bool WrappedOpenGL::Serialise_glVertexAttrib(GLuint index, int count, GLenum type, GLboolean normalized, const void *value, int attribtype)
|
|
{
|
|
SERIALISE_ELEMENT(uint32_t, idx, index);
|
|
SERIALISE_ELEMENT(int32_t, Count, count);
|
|
SERIALISE_ELEMENT(int, Type, attribtype);
|
|
SERIALISE_ELEMENT(bool, norm, normalized == GL_TRUE);
|
|
SERIALISE_ELEMENT(GLenum, packedType, type);
|
|
|
|
AttribType attr = AttribType(Type & Attrib_typemask);
|
|
|
|
size_t elemSize = 1;
|
|
switch(attr)
|
|
{
|
|
case Attrib_GLdouble:
|
|
elemSize = 8;
|
|
break;
|
|
case Attrib_GLfloat:
|
|
case Attrib_GLint:
|
|
case Attrib_GLuint:
|
|
case Attrib_packed:
|
|
elemSize = 4;
|
|
break;
|
|
case Attrib_GLshort:
|
|
case Attrib_GLushort:
|
|
elemSize = 2;
|
|
break;
|
|
default:
|
|
case Attrib_GLbyte:
|
|
case Attrib_GLubyte:
|
|
elemSize = 1;
|
|
break;
|
|
}
|
|
|
|
size_t valueSize = elemSize*Count;
|
|
if(Type == Attrib_packed)
|
|
valueSize = sizeof(uint32_t);
|
|
|
|
if(m_State >= WRITING)
|
|
{
|
|
m_pSerialiser->RawWriteBytes(value, valueSize);
|
|
}
|
|
else if(m_State <= EXECUTING)
|
|
{
|
|
value = m_pSerialiser->RawReadBytes(valueSize);
|
|
|
|
if(Type == Attrib_packed)
|
|
{
|
|
if(Count == 1) m_Real.glVertexAttribP1uiv(idx, packedType, norm, (GLuint*)value);
|
|
else if(Count == 2) m_Real.glVertexAttribP2uiv(idx, packedType, norm, (GLuint*)value);
|
|
else if(Count == 3) m_Real.glVertexAttribP3uiv(idx, packedType, norm, (GLuint*)value);
|
|
else if(Count == 4) m_Real.glVertexAttribP4uiv(idx, packedType, norm, (GLuint*)value);
|
|
}
|
|
else if(Type & Attrib_I)
|
|
{
|
|
if(Count == 1)
|
|
{
|
|
if(attr == Attrib_GLint) m_Real.glVertexAttribI1iv(idx, (GLint*)value);
|
|
else if(attr == Attrib_GLuint) m_Real.glVertexAttribI1uiv(idx, (GLuint*)value);
|
|
}
|
|
else if(Count == 2)
|
|
{
|
|
if(attr == Attrib_GLint) m_Real.glVertexAttribI2iv(idx, (GLint*)value);
|
|
else if(attr == Attrib_GLuint) m_Real.glVertexAttribI2uiv(idx, (GLuint*)value);
|
|
}
|
|
else if(Count == 2)
|
|
{
|
|
if(attr == Attrib_GLint) m_Real.glVertexAttribI3iv(idx, (GLint*)value);
|
|
else if(attr == Attrib_GLuint) m_Real.glVertexAttribI3uiv(idx, (GLuint*)value);
|
|
}
|
|
else
|
|
{
|
|
if(attr == Attrib_GLbyte) m_Real.glVertexAttribI4bv(idx, (GLbyte*)value);
|
|
else if(attr == Attrib_GLint) m_Real.glVertexAttribI4iv(idx, (GLint*)value);
|
|
else if(attr == Attrib_GLshort) m_Real.glVertexAttribI4sv(idx, (GLshort*)value);
|
|
else if(attr == Attrib_GLubyte) m_Real.glVertexAttribI4ubv(idx, (GLubyte*)value);
|
|
else if(attr == Attrib_GLuint) m_Real.glVertexAttribI4uiv(idx, (GLuint*)value);
|
|
else if(attr == Attrib_GLushort) m_Real.glVertexAttribI4usv(idx, (GLushort*)value);
|
|
}
|
|
}
|
|
else if(Type & Attrib_L)
|
|
{
|
|
if(Count == 1) m_Real.glVertexAttribL1dv(idx, (GLdouble*)value);
|
|
else if(Count == 2) m_Real.glVertexAttribL2dv(idx, (GLdouble*)value);
|
|
else if(Count == 3) m_Real.glVertexAttribL3dv(idx, (GLdouble*)value);
|
|
else if(Count == 4) m_Real.glVertexAttribL4dv(idx, (GLdouble*)value);
|
|
}
|
|
else if(Type & Attrib_N)
|
|
{
|
|
if(attr == Attrib_GLbyte) m_Real.glVertexAttrib4Nbv(idx, (GLbyte*)value);
|
|
else if(attr == Attrib_GLint) m_Real.glVertexAttrib4Niv(idx, (GLint*)value);
|
|
else if(attr == Attrib_GLshort) m_Real.glVertexAttrib4Nsv(idx, (GLshort*)value);
|
|
else if(attr == Attrib_GLubyte) m_Real.glVertexAttrib4Nubv(idx, (GLubyte*)value);
|
|
else if(attr == Attrib_GLuint) m_Real.glVertexAttrib4Nuiv(idx, (GLuint*)value);
|
|
else if(attr == Attrib_GLushort) m_Real.glVertexAttrib4Nusv(idx, (GLushort*)value);
|
|
}
|
|
else
|
|
{
|
|
if(Count == 1)
|
|
{
|
|
if(attr == Attrib_GLdouble) m_Real.glVertexAttrib1dv(idx, (GLdouble*)value);
|
|
else if(attr == Attrib_GLfloat) m_Real.glVertexAttrib1fv(idx, (GLfloat*)value);
|
|
else if(attr == Attrib_GLshort) m_Real.glVertexAttrib1sv(idx, (GLshort*)value);
|
|
}
|
|
else if(Count == 2)
|
|
{
|
|
if(attr == Attrib_GLdouble) m_Real.glVertexAttrib2dv(idx, (GLdouble*)value);
|
|
else if(attr == Attrib_GLfloat) m_Real.glVertexAttrib2fv(idx, (GLfloat*)value);
|
|
else if(attr == Attrib_GLshort) m_Real.glVertexAttrib2sv(idx, (GLshort*)value);
|
|
}
|
|
else if(Count == 3)
|
|
{
|
|
if(attr == Attrib_GLdouble) m_Real.glVertexAttrib3dv(idx, (GLdouble*)value);
|
|
else if(attr == Attrib_GLfloat) m_Real.glVertexAttrib3fv(idx, (GLfloat*)value);
|
|
else if(attr == Attrib_GLshort) m_Real.glVertexAttrib3sv(idx, (GLshort*)value);
|
|
}
|
|
else
|
|
{
|
|
if(attr == Attrib_GLdouble) m_Real.glVertexAttrib4dv(idx, (GLdouble*)value);
|
|
else if(attr == Attrib_GLfloat) m_Real.glVertexAttrib4fv(idx, (GLfloat*)value);
|
|
else if(attr == Attrib_GLbyte) m_Real.glVertexAttrib4bv(idx, (GLbyte*)value);
|
|
else if(attr == Attrib_GLint) m_Real.glVertexAttrib4iv(idx, (GLint*)value);
|
|
else if(attr == Attrib_GLshort) m_Real.glVertexAttrib4sv(idx, (GLshort*)value);
|
|
else if(attr == Attrib_GLubyte) m_Real.glVertexAttrib4ubv(idx, (GLubyte*)value);
|
|
else if(attr == Attrib_GLuint) m_Real.glVertexAttrib4uiv(idx, (GLuint*)value);
|
|
else if(attr == Attrib_GLushort) m_Real.glVertexAttrib4usv(idx, (GLushort*)value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#define ATTRIB_FUNC(count, suffix, TypeOr, paramtype, ...) \
|
|
void WrappedOpenGL::CONCAT(glVertexAttrib, suffix)(GLuint index, __VA_ARGS__) \
|
|
{ \
|
|
m_Real.CONCAT(glVertexAttrib, suffix)(index, ARRAYLIST); \
|
|
\
|
|
if(m_State >= WRITING_CAPFRAME) \
|
|
{ \
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIB_GENERIC); \
|
|
const paramtype vals[] = { ARRAYLIST }; \
|
|
Serialise_glVertexAttrib(index, count, eGL_NONE, GL_FALSE, vals, TypeOr | CONCAT(Attrib_, paramtype)); \
|
|
\
|
|
m_ContextRecord->AddChunk(scope.Get()); \
|
|
} \
|
|
}
|
|
|
|
#define ARRAYLIST x
|
|
|
|
ATTRIB_FUNC(1, 1f, 0, GLfloat, GLfloat x)
|
|
ATTRIB_FUNC(1, 1s, 0, GLshort, GLshort x)
|
|
ATTRIB_FUNC(1, 1d, 0, GLdouble, GLdouble x)
|
|
ATTRIB_FUNC(1, L1d, Attrib_L, GLdouble, GLdouble x)
|
|
ATTRIB_FUNC(1, I1i, Attrib_I, GLint, GLint x)
|
|
ATTRIB_FUNC(1, I1ui, Attrib_I, GLuint, GLuint x)
|
|
|
|
#undef ARRAYLIST
|
|
#define ARRAYLIST x, y
|
|
|
|
ATTRIB_FUNC(2, 2f, 0, GLfloat, GLfloat x, GLfloat y)
|
|
ATTRIB_FUNC(2, 2s, 0, GLshort, GLshort x, GLshort y)
|
|
ATTRIB_FUNC(2, 2d, 0, GLdouble, GLdouble x, GLdouble y)
|
|
ATTRIB_FUNC(2, L2d, Attrib_L, GLdouble, GLdouble x, GLdouble y)
|
|
ATTRIB_FUNC(2, I2i, Attrib_I, GLint, GLint x, GLint y)
|
|
ATTRIB_FUNC(2, I2ui, Attrib_I, GLuint, GLuint x, GLuint y)
|
|
|
|
#undef ARRAYLIST
|
|
#define ARRAYLIST x, y, z
|
|
|
|
ATTRIB_FUNC(3, 3f, 0, GLfloat, GLfloat x, GLfloat y, GLfloat z)
|
|
ATTRIB_FUNC(3, 3s, 0, GLshort, GLshort x, GLshort y, GLshort z)
|
|
ATTRIB_FUNC(3, 3d, 0, GLdouble, GLdouble x, GLdouble y, GLdouble z)
|
|
ATTRIB_FUNC(3, L3d, Attrib_L, GLdouble, GLdouble x, GLdouble y, GLdouble z)
|
|
ATTRIB_FUNC(3, I3i, Attrib_I, GLint, GLint x, GLint y, GLint z)
|
|
ATTRIB_FUNC(3, I3ui, Attrib_I, GLuint, GLuint x, GLuint y, GLuint z)
|
|
|
|
#undef ARRAYLIST
|
|
#define ARRAYLIST x, y, z, w
|
|
|
|
ATTRIB_FUNC(4, 4f, 0, GLfloat, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
|
|
ATTRIB_FUNC(4, 4s, 0, GLshort, GLshort x, GLshort y, GLshort z, GLshort w)
|
|
ATTRIB_FUNC(4, 4d, 0, GLdouble, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
|
|
ATTRIB_FUNC(4, L4d, Attrib_L, GLdouble, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
|
|
ATTRIB_FUNC(4, I4i, Attrib_I, GLint, GLint x, GLint y, GLint z, GLint w)
|
|
ATTRIB_FUNC(4, I4ui, Attrib_I, GLuint, GLuint x, GLuint y, GLuint z, GLuint w)
|
|
ATTRIB_FUNC(4, 4Nub, Attrib_N, GLubyte, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
|
|
|
|
#undef ATTRIB_FUNC
|
|
#define ATTRIB_FUNC(count, suffix, TypeOr, paramtype) \
|
|
void WrappedOpenGL::CONCAT(glVertexAttrib, suffix)(GLuint index, const paramtype *value) \
|
|
{ \
|
|
m_Real.CONCAT(glVertexAttrib, suffix)(index, value); \
|
|
\
|
|
if(m_State >= WRITING_CAPFRAME) \
|
|
{ \
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIB_GENERIC); \
|
|
Serialise_glVertexAttrib(index, count, eGL_NONE, GL_FALSE, value, TypeOr | CONCAT(Attrib_, paramtype)); \
|
|
\
|
|
m_ContextRecord->AddChunk(scope.Get()); \
|
|
} \
|
|
}
|
|
|
|
ATTRIB_FUNC(1, 1dv, 0, GLdouble)
|
|
ATTRIB_FUNC(2, 2dv, 0, GLdouble)
|
|
ATTRIB_FUNC(3, 3dv, 0, GLdouble)
|
|
ATTRIB_FUNC(4, 4dv, 0, GLdouble)
|
|
ATTRIB_FUNC(1, 1sv, 0, GLshort)
|
|
ATTRIB_FUNC(2, 2sv, 0, GLshort)
|
|
ATTRIB_FUNC(3, 3sv, 0, GLshort)
|
|
ATTRIB_FUNC(4, 4sv, 0, GLshort)
|
|
ATTRIB_FUNC(1, 1fv, 0, GLfloat)
|
|
ATTRIB_FUNC(2, 2fv, 0, GLfloat)
|
|
ATTRIB_FUNC(3, 3fv, 0, GLfloat)
|
|
ATTRIB_FUNC(4, 4fv, 0, GLfloat)
|
|
ATTRIB_FUNC(4, 4bv, 0, GLbyte)
|
|
ATTRIB_FUNC(4, 4iv, 0, GLint)
|
|
ATTRIB_FUNC(4, 4uiv, 0, GLuint)
|
|
ATTRIB_FUNC(4, 4usv, 0, GLushort)
|
|
ATTRIB_FUNC(4, 4ubv, 0, GLubyte)
|
|
|
|
ATTRIB_FUNC(1, L1dv, Attrib_L, GLdouble)
|
|
ATTRIB_FUNC(2, L2dv, Attrib_L, GLdouble)
|
|
ATTRIB_FUNC(3, L3dv, Attrib_L, GLdouble)
|
|
ATTRIB_FUNC(4, L4dv, Attrib_L, GLdouble)
|
|
|
|
ATTRIB_FUNC(1, I1iv, Attrib_I, GLint)
|
|
ATTRIB_FUNC(1, I1uiv, Attrib_I, GLuint)
|
|
ATTRIB_FUNC(2, I2iv, Attrib_I, GLint)
|
|
ATTRIB_FUNC(2, I2uiv, Attrib_I, GLuint)
|
|
ATTRIB_FUNC(3, I3iv, Attrib_I, GLint)
|
|
ATTRIB_FUNC(3, I3uiv, Attrib_I, GLuint)
|
|
|
|
ATTRIB_FUNC(4, I4bv, Attrib_I, GLbyte)
|
|
ATTRIB_FUNC(4, I4iv, Attrib_I, GLint)
|
|
ATTRIB_FUNC(4, I4sv, Attrib_I, GLshort)
|
|
ATTRIB_FUNC(4, I4ubv, Attrib_I, GLubyte)
|
|
ATTRIB_FUNC(4, I4uiv, Attrib_I, GLuint)
|
|
ATTRIB_FUNC(4, I4usv, Attrib_I, GLushort)
|
|
|
|
ATTRIB_FUNC(4, 4Nbv, Attrib_N, GLbyte)
|
|
ATTRIB_FUNC(4, 4Niv, Attrib_N, GLint)
|
|
ATTRIB_FUNC(4, 4Nsv, Attrib_N, GLshort)
|
|
ATTRIB_FUNC(4, 4Nubv, Attrib_N, GLubyte)
|
|
ATTRIB_FUNC(4, 4Nuiv, Attrib_N, GLuint)
|
|
ATTRIB_FUNC(4, 4Nusv, Attrib_N, GLushort)
|
|
|
|
#undef ATTRIB_FUNC
|
|
#define ATTRIB_FUNC(count, suffix, funcparam, passparam) \
|
|
void WrappedOpenGL::CONCAT(CONCAT(glVertexAttribP, count), suffix)(GLuint index, GLenum type, GLboolean normalized, funcparam) \
|
|
{ \
|
|
m_Real.CONCAT(CONCAT(glVertexAttribP, count), suffix)(index, type, normalized, value); \
|
|
\
|
|
if(m_State >= WRITING_CAPFRAME) \
|
|
{ \
|
|
SCOPED_SERIALISE_CONTEXT(VERTEXATTRIB_GENERIC); \
|
|
Serialise_glVertexAttrib(index, count, type, normalized, passparam, Attrib_packed); \
|
|
\
|
|
m_ContextRecord->AddChunk(scope.Get()); \
|
|
} \
|
|
}
|
|
|
|
ATTRIB_FUNC(1, ui, GLuint value, &value)
|
|
ATTRIB_FUNC(2, ui, GLuint value, &value)
|
|
ATTRIB_FUNC(3, ui, GLuint value, &value)
|
|
ATTRIB_FUNC(4, ui, GLuint value, &value)
|
|
ATTRIB_FUNC(1, uiv, const GLuint *value, value)
|
|
ATTRIB_FUNC(2, uiv, const GLuint *value, value)
|
|
ATTRIB_FUNC(3, uiv, const GLuint *value, value)
|
|
ATTRIB_FUNC(4, uiv, const GLuint *value, value)
|
|
|
|
#pragma endregion |