Files
renderdoc/renderdoc/driver/gl/gl_manager.cpp
T

213 lines
6.2 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 "driver/gl/gl_manager.h"
#include "driver/gl/gl_driver.h"
struct VertexArrayInitialData
{
VertexArrayInitialData()
{
RDCEraseEl(*this);
}
uint32_t enabled;
uint32_t vbslot;
uint32_t offset;
GLenum type;
int32_t normalized;
uint32_t integer;
uint32_t size;
};
bool GLResourceManager::SerialisableResource(ResourceId id, GLResourceRecord *record)
{
if(id == m_GL->GetContextResourceID())
return false;
return true;
}
bool GLResourceManager::Need_InitialStateChunk(GLResource res)
{
return res.Namespace != eResBuffer;
}
bool GLResourceManager::Prepare_InitialState(GLResource res)
{
ResourceId Id = GetID(res);
if(res.Namespace == eResBuffer)
{
GLResourceRecord *record = GetResourceRecord(res);
// TODO copy this to an immutable buffer elsewhere and SetInitialContents() it.
// then only do the readback in Serialise_InitialState
GLint length;
m_GL->glGetNamedBufferParameterivEXT(res.name, eGL_BUFFER_SIZE, &length);
m_GL->glGetNamedBufferSubDataEXT(res.name, 0, length, record->GetDataPtr());
}
else if(res.Namespace == eResVertexArray)
{
GLuint VAO = 0;
m_GL->glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);
m_GL->glBindVertexArray(res.name);
VertexArrayInitialData *data = (VertexArrayInitialData *)new byte[sizeof(VertexArrayInitialData)*16];
for(GLuint i=0; i < 16; i++)
{
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *)&data[i].enabled);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_BINDING, (GLint *)&data[i].vbslot);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_RELATIVE_OFFSET, (GLint*)&data[i].offset);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint *)&data[i].type);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_NORMALIZED, (GLint *)&data[i].normalized);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_INTEGER, (GLint *)&data[i].integer);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_SIZE, (GLint *)&data[i].size);
}
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, (byte *)data));
m_GL->glBindVertexArray(VAO);
}
else
{
RDCERR("Unexpected type of resource requiring initial state");
}
return true;
}
bool GLResourceManager::Force_InitialState(GLResource res)
{
// hack for now, these should be tracked through the normal dirty/ref tracking process.
if(res.Namespace == eResVertexArray) return true;
return false;
}
bool GLResourceManager::Serialise_InitialState(GLResource res)
{
ResourceId Id = ResourceId();
if(m_State >= WRITING)
{
Id = GetID(res);
if(res.Namespace != eResBuffer)
m_pSerialiser->Serialise("Id", Id);
}
else
{
m_pSerialiser->Serialise("Id", Id);
}
if(m_State < WRITING)
{
if(HasLiveResource(Id))
res = GetLiveResource(Id);
else
res = GLResource(MakeNullResource);
}
if(res.Namespace == eResVertexArray)
{
VertexArrayInitialData data[16];
if(m_State >= WRITING)
{
VertexArrayInitialData *initialdata = (VertexArrayInitialData *)GetInitialContents(Id).blob;
memcpy(data, initialdata, sizeof(data));
}
for(GLuint i=0; i < 16; i++)
{
m_pSerialiser->Serialise("data[].enabled", data[i].enabled);
m_pSerialiser->Serialise("data[].vbslot", data[i].vbslot);
m_pSerialiser->Serialise("data[].offset", data[i].offset);
m_pSerialiser->Serialise("data[].type", data[i].type);
m_pSerialiser->Serialise("data[].normalized", data[i].normalized);
m_pSerialiser->Serialise("data[].integer", data[i].integer);
m_pSerialiser->Serialise("data[].size", data[i].size);
}
if(m_State < WRITING)
{
byte *blob = new byte[sizeof(data)];
memcpy(blob, data, sizeof(data));
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, blob));
}
}
else
{
RDCERR("Unexpected type of resource requiring initial state");
}
return true;
}
void GLResourceManager::Create_InitialState(ResourceId id, GLResource live, bool hasData)
{
if(live.Namespace != eResBuffer)
{
RDCUNIMPLEMENTED("Expect all initial states to be created & not skipped, presently");
}
}
void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData initial)
{
if(live.Namespace == eResVertexArray)
{
GLuint VAO = 0;
m_GL->glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);
m_GL->glBindVertexArray(live.name);
VertexArrayInitialData *initialdata = (VertexArrayInitialData *)initial.blob;
for(GLuint i=0; i < 16; i++)
{
if(initialdata[i].enabled)
m_GL->glEnableVertexAttribArray(i);
else
m_GL->glDisableVertexAttribArray(i);
m_GL->glVertexAttribBinding(i, initialdata[i].vbslot);
if(initialdata[i].integer == 0)
m_GL->glVertexAttribFormat(i, initialdata[i].size, initialdata[i].type, (GLboolean)initialdata[i].normalized, initialdata[i].offset);
else
m_GL->glVertexAttribIFormat(i, initialdata[i].size, initialdata[i].type, initialdata[i].offset);
}
m_GL->glBindVertexArray(VAO);
}
else
{
RDCERR("Unexpected type of resource requiring initial state");
}
}