bool WrappedOpenGL::Serialise_glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ,
												                         GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ,
												                         GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
{
	SERIALISE_ELEMENT(ResourceId, srcid, GetResourceManager()->GetID(TextureRes(GetCtx(), srcName)));
	SERIALISE_ELEMENT(ResourceId, dstid, GetResourceManager()->GetID(TextureRes(GetCtx(), dstName)));
	SERIALISE_ELEMENT(GLenum, SourceTarget, srcTarget);
	SERIALISE_ELEMENT(GLenum, DestTarget, dstTarget);
	SERIALISE_ELEMENT(uint32_t, SourceLevel, srcLevel);
	SERIALISE_ELEMENT(uint32_t, SourceX, srcX);
	SERIALISE_ELEMENT(uint32_t, SourceY, srcY);
	SERIALISE_ELEMENT(uint32_t, SourceZ, srcZ);
	SERIALISE_ELEMENT(uint32_t, SourceWidth, srcWidth);
	SERIALISE_ELEMENT(uint32_t, SourceHeight, srcHeight);
	SERIALISE_ELEMENT(uint32_t, SourceDepth, srcDepth);
	SERIALISE_ELEMENT(uint32_t, DestLevel, dstLevel);
	SERIALISE_ELEMENT(uint32_t, DestX, dstX);
	SERIALISE_ELEMENT(uint32_t, DestY, dstY);
	SERIALISE_ELEMENT(uint32_t, DestZ, dstZ);
	
	if(m_State < WRITING)
	{
		GLResource srcres = GetResourceManager()->GetLiveResource(srcid);
		GLResource dstres = GetResourceManager()->GetLiveResource(dstid);
		m_Real.glCopyImageSubData(srcres.name, SourceTarget, SourceLevel, SourceX, SourceY, SourceZ,
															dstres.name, DestTarget, DestLevel, DestX, DestY, DestZ,
															SourceWidth, SourceHeight, SourceDepth);
	}
	return true;
}
void WrappedOpenGL::glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ,
												               GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ,
												               GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
{
	m_Real.glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ,
												    dstName, dstTarget, dstLevel, dstX, dstY, dstZ,
												    srcWidth, srcHeight, srcDepth);
	
	if(m_State >= WRITING)
	{
		GLResourceRecord *srcrecord = GetResourceManager()->GetResourceRecord(TextureRes(srcName));
		GLResourceRecord *dstrecord = GetResourceManager()->GetResourceRecord(TextureRes(dstName));
		RDCASSERT(srcrecord && dstrecord);

		SCOPED_SERIALISE_CONTEXT(COPY_SUBIMAGE);
		Serialise_glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ,
												         dstName, dstTarget, dstLevel, dstX, dstY, dstZ,
												         srcWidth, srcHeight, srcDepth);

		Chunk *chunk = scope.Get();

		if(m_State == WRITING_CAPFRAME)
		{
			m_ContextRecord->AddChunk(chunk);
		}
		else
		{
			dstrecord->AddChunk(chunk);
			dstrecord->AddParent(srcrecord);
		}
	}
}
bool WrappedOpenGL::Serialise_glCompressedTextureSubImage3DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(int32_t, Level, level);
	SERIALISE_ELEMENT(int32_t, xoff, xoffset);
	SERIALISE_ELEMENT(int32_t, yoff, yoffset);
	SERIALISE_ELEMENT(int32_t, zoff, zoffset);
	SERIALISE_ELEMENT(uint32_t, Width, width);
	SERIALISE_ELEMENT(uint32_t, Height, height);
	SERIALISE_ELEMENT(uint32_t, Depth, depth);
	SERIALISE_ELEMENT(GLenum, fmt, format);
	SERIALISE_ELEMENT(uint32_t, byteSize, imageSize);
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture)));

	SERIALISE_ELEMENT_BUF(byte *, buf, pixels, byteSize);
	
	if(m_State == READING)
	{
		m_Real.glCompressedTextureSubImage3DEXT(GetResourceManager()->GetLiveResource(id).name, Target, Level, xoff, yoff, zoff, Width, Height, Depth, fmt, byteSize, buf);

		delete[] buf;
	}

	return true;
}
bool WrappedOpenGL::Serialise_glNamedFramebufferTextureEXT(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level)
{
	SERIALISE_ELEMENT(GLenum, Attach, attachment);
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture)));
	SERIALISE_ELEMENT(int32_t, Level, level);
	SERIALISE_ELEMENT(ResourceId, fbid, (framebuffer == 0 ? ResourceId() : GetResourceManager()->GetID(FramebufferRes(GetCtx(), framebuffer))));
	
	if(m_State < WRITING)
	{
		GLResource res = GetResourceManager()->GetLiveResource(id);
		if(fbid == ResourceId())
		{
			glNamedFramebufferTextureEXT(0, Attach, res.name, Level);
		}
		else
		{
			GLResource fbres = GetResourceManager()->GetLiveResource(fbid);
			glNamedFramebufferTextureEXT(fbres.name, Attach, res.name, Level);
		}

		if(m_State == READING)
		{
			m_Textures[GetResourceManager()->GetLiveID(id)].creationFlags |= eTextureCreate_RTV;
		}
	}

	return true;
}
void WrappedOpenGL::glGenTextures(GLsizei n, GLuint* textures)
{
	m_Real.glGenTextures(n, textures);

	for(GLsizei i=0; i < n; i++)
	{
		GLResource res = TextureRes(textures[i]);
		ResourceId id = GetResourceManager()->RegisterResource(res);

		if(m_State >= WRITING)
		{
			Chunk *chunk = NULL;

			{
				SCOPED_SERIALISE_CONTEXT(GEN_TEXTURE);
				Serialise_glGenTextures(1, textures+i);

				chunk = scope.Get();
			}

			GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
			RDCASSERT(record);

			record->AddChunk(chunk);
		}
		else
		{
			GetResourceManager()->AddLiveResource(id, res);
			m_Textures[id].resource = res;
			m_Textures[id].curType = eGL_UNKNOWN_ENUM;
		}
	}
}
void WrappedOpenGL::glDeleteTextures(GLsizei n, const GLuint *textures)
{
	m_Real.glDeleteTextures(n, textures);

	for(GLsizei i=0; i < n; i++)
		GetResourceManager()->UnregisterResource(TextureRes(textures[i]));
}
bool WrappedOpenGL::Serialise_glBindTexture(GLenum target, GLuint texture)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(ResourceId, Id, GetResourceManager()->GetID(TextureRes(texture)));
	
	if(m_State == WRITING_IDLE)
	{
		m_TextureRecord[m_TextureUnit]->datatype = Target;
	}
	else if(m_State < WRITING)
	{
		if(Id == ResourceId())
		{
			m_Real.glBindTexture(Target, 0);
		}
		else
		{
			GLResource res = GetResourceManager()->GetLiveResource(Id);
			m_Real.glBindTexture(Target, res.name);

			m_Textures[GetResourceManager()->GetLiveID(Id)].curType = Target;
		}
	}

	return true;
}
bool WrappedOpenGL::Serialise_glTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(int32_t, Level, level);
	SERIALISE_ELEMENT(int32_t, xoff, xoffset);
	SERIALISE_ELEMENT(int32_t, yoff, yoffset);
	SERIALISE_ELEMENT(uint32_t, Width, width);
	SERIALISE_ELEMENT(uint32_t, Height, height);
	SERIALISE_ELEMENT(GLenum, Format, format);
	SERIALISE_ELEMENT(GLenum, Type, type);
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture)));

	GLint align = 1;
	m_Real.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &align);

	size_t subimageSize = GetByteSize(Width, Height, 1, Format, Type, Level, align);

	SERIALISE_ELEMENT_BUF(byte *, buf, pixels, subimageSize);
	
	if(m_State == READING)
	{
		m_Real.glTextureSubImage2DEXT(GetResourceManager()->GetLiveResource(id).name, Target, Level, xoff, yoff, Width, Height, Format, Type, buf);

		delete[] buf;
	}

	return true;
}
void WrappedOpenGL::glTextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
{
	m_Real.glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
	
	if(m_State >= WRITING)
	{
		ResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture));
		ResourceRecord *origrecord = GetResourceManager()->GetResourceRecord(TextureRes(origtexture));
		RDCASSERT(record && origrecord);

		SCOPED_SERIALISE_CONTEXT(TEXTURE_VIEW);
		Serialise_glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);

		record->AddChunk(scope.Get());
		record->AddParent(origrecord);
	}
}
bool WrappedOpenGL::Serialise_glTextureBufferRangeEXT(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(uint64_t, offs, (uint64_t)offset);
	SERIALISE_ELEMENT(uint64_t, Size, (uint64_t)size);
	SERIALISE_ELEMENT(GLenum, fmt, internalformat);
	SERIALISE_ELEMENT(ResourceId, texid, GetResourceManager()->GetID(TextureRes(texture)));
	SERIALISE_ELEMENT(ResourceId, bufid, GetResourceManager()->GetID(TextureRes(buffer)));
	
	if(m_State == READING)
	{
		m_Real.glTextureBufferRangeEXT(GetResourceManager()->GetLiveResource(texid).name,
																	 Target, fmt,
																	 GetResourceManager()->GetLiveResource(bufid).name,
																	 (GLintptr)offs, (GLsizeiptr)Size);
	}

	return true;
}
bool WrappedOpenGL::Serialise_glTextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(GLenum, InternalFormat, internalformat);
	SERIALISE_ELEMENT(uint32_t, MinLevel, minlevel);
	SERIALISE_ELEMENT(uint32_t, NumLevels, numlevels);
	SERIALISE_ELEMENT(uint32_t, MinLayer, minlayer);
	SERIALISE_ELEMENT(uint32_t, NumLayers, numlayers);
	SERIALISE_ELEMENT(ResourceId, texid, GetResourceManager()->GetID(TextureRes(texture)));
	SERIALISE_ELEMENT(ResourceId, origid, GetResourceManager()->GetID(TextureRes(origtexture)));

	if(m_State == READING)
	{
		GLResource tex = GetResourceManager()->GetLiveResource(texid);
		GLResource origtex = GetResourceManager()->GetLiveResource(origid);
		m_Real.glTextureView(tex.name, Target, origtex.name, InternalFormat, MinLevel, NumLevels, MinLayer, NumLayers);
	}

	return true;
}
bool WrappedOpenGL::Serialise_glGenTextures(GLsizei n, GLuint* textures)
{
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(*textures)));

	if(m_State == READING)
	{
		GLuint real = 0;
		m_Real.glGenTextures(1, &real);
		
		GLResource res = TextureRes(real);

		ResourceId live = m_ResourceManager->RegisterResource(res);
		GetResourceManager()->AddLiveResource(id, res);

		m_Textures[live].resource = res;
		m_Textures[live].curType = eGL_UNKNOWN_ENUM;
	}

	return true;
}
bool WrappedOpenGL::Serialise_glGenerateTextureMipmapEXT(GLuint texture, GLenum target)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture)));

	if(m_State == READING)
	{
		m_Real.glGenerateTextureMipmapEXT(GetResourceManager()->GetLiveResource(id).name, Target);
	}

	return true;
}
void WrappedOpenGL::glBindTexture(GLenum target, GLuint texture)
{
	m_Real.glBindTexture(target, texture);
	
	if(m_State == WRITING_CAPFRAME)
	{
		Chunk *chunk = NULL;

		{
			SCOPED_SERIALISE_CONTEXT(BIND_TEXTURE);
			Serialise_glBindTexture(target, texture);

			chunk = scope.Get();
		}
		
		m_ContextRecord->AddChunk(chunk);
	}
	else if(m_State < WRITING)
	{
		m_Textures[GetResourceManager()->GetID(TextureRes(texture))].curType = target;
	}

	if(texture == 0)
	{
		m_TextureRecord[m_TextureUnit] = NULL;
		return;
	}

	if(m_State >= WRITING)
	{
		GLResourceRecord *r = m_TextureRecord[m_TextureUnit] = GetResourceManager()->GetResourceRecord(TextureRes(texture));

		if(r->datatype)
		{
			// it's illegal to retype a texture
			RDCASSERT(r->datatype == target);
		}
		else
		{
			Chunk *chunk = NULL;

			{
				SCOPED_SERIALISE_CONTEXT(BIND_TEXTURE);
				Serialise_glBindTexture(target, texture);

				chunk = scope.Get();
			}

			r->AddChunk(chunk);
		}
	}
}
void WrappedOpenGL::glTextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
{
	m_Real.glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
	
	if(m_State >= WRITING)
	{
		GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), texture));
		GLResourceRecord *origrecord = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), origtexture));
		RDCASSERT(record && origrecord);

		SCOPED_SERIALISE_CONTEXT(TEXTURE_VIEW);
		Serialise_glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);

		record->AddChunk(scope.Get());
		record->AddParent(origrecord);

		// illegal to re-type textures
		if(record->datatype == eGL_UNKNOWN_ENUM)
			record->datatype = target;
		else
			RDCASSERT(record->datatype == target);
	}
}
bool WrappedOpenGL::Serialise_glTextureParameterfEXT(GLuint texture, GLenum target, GLenum pname, GLfloat param)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(GLenum, PName, pname);
	SERIALISE_ELEMENT(float, Param, param);
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture)));
	
	if(m_State < WRITING)
	{
		m_Real.glTextureParameterfEXT(GetResourceManager()->GetLiveResource(id).name, Target, PName, Param);
	}

	return true;
}
void WrappedOpenGL::glTextureBufferRangeEXT(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
{
	m_Real.glTextureBufferRangeEXT(texture, target, internalformat, buffer, offset, size);
		
	if(m_State >= WRITING)
	{
		GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture));
		RDCASSERT(record);

		SCOPED_SERIALISE_CONTEXT(TEXBUFFER_RANGE);
		Serialise_glTextureBufferRangeEXT(texture, target, internalformat, buffer, offset, size);

		record->AddChunk(scope.Get());
	}
}
bool WrappedOpenGL::Serialise_glTextureParameterfvEXT(GLuint texture, GLenum target, GLenum pname, const GLfloat *params)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(GLenum, PName, pname);
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture)));
	const size_t nParams = (PName == eGL_TEXTURE_BORDER_COLOR ? 4U : 1U);
	SERIALISE_ELEMENT_ARR(float, Params, params, nParams);

	if(m_State < WRITING)
	{
		m_Real.glTextureParameterfvEXT(GetResourceManager()->GetLiveResource(id).name, Target, PName, Params);
	}

	delete[] Params;

	return true;
}
void WrappedOpenGL::glTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
{
	m_Real.glTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, type, pixels);
	
	if(m_State >= WRITING)
	{
		GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture));
		RDCASSERT(record);

		SCOPED_SERIALISE_CONTEXT(TEXSUBIMAGE2D);
		Serialise_glTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, type, pixels);

		if(m_State == WRITING_CAPFRAME)
			m_ContextRecord->AddChunk(scope.Get());
		else
			record->AddChunk(scope.Get());
	}
}
void WrappedOpenGL::glTextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
	m_Real.glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth);
	
	if(m_State >= WRITING)
	{
		GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture));
		RDCASSERT(record);

		SCOPED_SERIALISE_CONTEXT(TEXSTORAGE3D);
		Serialise_glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth);

		if(m_State == WRITING_CAPFRAME)
			m_ContextRecord->AddChunk(scope.Get());
		else
			record->AddChunk(scope.Get());
	}
}
void WrappedOpenGL::glTextureParameterfvEXT(GLuint texture, GLenum target, GLenum pname, const GLfloat *params)
{
	m_Real.glTextureParameterfvEXT(texture, target, pname, params);
	
	if(m_State >= WRITING)
	{
		GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture));
		RDCASSERT(record);

		SCOPED_SERIALISE_CONTEXT(TEXPARAMETERFV);
		Serialise_glTextureParameterfvEXT(texture, target, pname, params);

		if(m_State == WRITING_IDLE)
			record->AddChunk(scope.Get());
		else
			m_ContextRecord->AddChunk(scope.Get());
	}
}
bool WrappedOpenGL::Serialise_glTextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
{
	SERIALISE_ELEMENT(GLenum, Target, target);
	SERIALISE_ELEMENT(uint32_t, Levels, levels);
	SERIALISE_ELEMENT(GLenum, Format, internalformat);
	SERIALISE_ELEMENT(uint32_t, Width, width);
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture)));

	if(m_State == READING)
	{
		ResourceId liveId = GetResourceManager()->GetLiveID(id);
		m_Textures[liveId].width = Width;
		m_Textures[liveId].height = 1;
		m_Textures[liveId].depth = 1;

		m_Real.glTextureStorage1DEXT(GetResourceManager()->GetLiveResource(id).name, Target, Levels, Format, Width);
	}

	return true;
}
void WrappedOpenGL::glTextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
	m_Real.glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth);
	
	if(m_State >= WRITING)
	{
		GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), texture));
		RDCASSERT(record);

		SCOPED_SERIALISE_CONTEXT(TEXSTORAGE3D);
		Serialise_glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth);

		record->AddChunk(scope.Get());

		// illegal to re-type textures
		if(record->datatype == eGL_UNKNOWN_ENUM)
			record->datatype = target;
		else
			RDCASSERT(record->datatype == target);
	}
}
void WrappedOpenGL::glGenerateTextureMipmapEXT(GLuint texture, GLenum target)
{
	m_Real.glGenerateTextureMipmapEXT(texture, target);
	
	if(m_State == WRITING_CAPFRAME)
	{
		SCOPED_SERIALISE_CONTEXT(GENERATE_MIPMAP);
		Serialise_glGenerateTextureMipmapEXT(texture, target);
		
		m_ContextRecord->AddChunk(scope.Get());
	}
	else if(m_State == WRITING_IDLE)
	{
		SCOPED_SERIALISE_CONTEXT(GENERATE_MIPMAP);
		Serialise_glGenerateTextureMipmapEXT(texture, target);

		ResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture));
		RDCASSERT(record);
		if(record)
			record->AddChunk(scope.Get());
	}
}
Exemple #25
0
ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID)
{
	WrappedOpenGL &gl = *m_pDriver;
	
	MakeCurrentReplayContext(&m_ReplayCtx);

	GLuint curProg = 0;
	gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg);

	GLuint curDrawFBO = 0;
	GLuint curReadFBO = 0;
	gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&curDrawFBO);
	gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&curReadFBO);
	
	auto &progDetails = m_pDriver->m_Programs[m_pDriver->GetResourceManager()->GetID(ProgramRes(curProg))];

	if(progDetails.colOutProg == 0)
	{
		progDetails.colOutProg = gl.glCreateProgram();
		GLuint shad = gl.glCreateShader(eGL_FRAGMENT_SHADER);

		const char *src = DebugData.genericfsSource.c_str();
		gl.glShaderSource(shad, 1, &src, NULL);
		gl.glCompileShader(shad);
		gl.glAttachShader(progDetails.colOutProg, shad);
		gl.glDeleteShader(shad);

		for(size_t i=0; i < progDetails.shaders.size(); i++)
		{
			const auto &shadDetails = m_pDriver->m_Shaders[progDetails.shaders[i]];

			if(shadDetails.type != eGL_FRAGMENT_SHADER)
			{
				shad = gl.glCreateShader(shadDetails.type);
				for(size_t s=0; s < shadDetails.sources.size(); s++)
				{
					src = shadDetails.sources[s].c_str();
					gl.glShaderSource(shad, 1, &src, NULL);
				}
				gl.glCompileShader(shad);
				gl.glAttachShader(progDetails.colOutProg, shad);
				gl.glDeleteShader(shad);
			}
		}

		gl.glLinkProgram(progDetails.colOutProg);
	}
	
	auto &texDetails = m_pDriver->m_Textures[texid];
	
	if(DebugData.overlayTexWidth != texDetails.width || DebugData.overlayTexHeight != texDetails.height)
	{
		if(DebugData.overlayFBO)
		{
			gl.glDeleteFramebuffers(1, &DebugData.overlayFBO);
			gl.glDeleteTextures(1, &DebugData.overlayTex);
		}

		gl.glGenFramebuffers(1, &DebugData.overlayFBO);
		gl.glBindFramebuffer(eGL_FRAMEBUFFER, DebugData.overlayFBO);

		GLuint curTex = 0;
		gl.glGetIntegerv(eGL_TEXTURE_BINDING_2D, (GLint*)&curTex);

		gl.glGenTextures(1, &DebugData.overlayTex);
		gl.glBindTexture(eGL_TEXTURE_2D, DebugData.overlayTex);

		DebugData.overlayTexWidth = texDetails.width;
		DebugData.overlayTexHeight = texDetails.height;

		gl.glTexStorage2D(eGL_TEXTURE_2D, 1, eGL_RGBA8, texDetails.width, texDetails.height); 
		gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST);
		gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST);
		gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_S, eGL_CLAMP_TO_EDGE);
		gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_T, eGL_CLAMP_TO_EDGE);
		gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, DebugData.overlayTex, 0);
		
		gl.glBindTexture(eGL_TEXTURE_2D, curTex);
	}
	
	gl.glBindFramebuffer(eGL_FRAMEBUFFER, DebugData.overlayFBO);
	
	if(overlay == eTexOverlay_NaN || overlay == eTexOverlay_Clipping)
	{
		// just need the basic texture
		float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
		gl.glClearBufferfv(eGL_COLOR, 0, black);
	}
	else if(overlay == eTexOverlay_Drawcall)
	{
		gl.glUseProgram(progDetails.colOutProg);
		
		{
			// copy across uniforms
			GLint numUniforms = 0;
			gl.glGetProgramiv(curProg, eGL_ACTIVE_UNIFORMS, &numUniforms);

			for(GLint i=0; i < numUniforms; i++)
			{
				char uniName[1024] = {};
				GLint uniSize = 0;
				GLenum uniType = eGL_UNKNOWN_ENUM;
				gl.glGetActiveUniform(curProg, i, 1024, NULL, &uniSize, &uniType, uniName);

				GLint origloc = gl.glGetUniformLocation(curProg, uniName);
				GLint newloc = gl.glGetUniformLocation(progDetails.colOutProg, uniName);

				double dv[16];
				float *fv = (float *)dv;

				if(uniSize > 1)
				{
					RDCERR("Array elements beyond [0] not being copied to new program");
				}

				if(origloc != -1 && newloc != -1)
				{
					if(uniType == eGL_FLOAT_MAT4)
					{
						gl.glGetUniformfv(curProg, origloc, fv);
						gl.glUniformMatrix4fv(newloc, 1, false, fv);
					}
					else if(uniType == eGL_FLOAT_VEC3)
					{
						gl.glGetUniformfv(curProg, origloc, fv);
						gl.glUniform3fv(newloc, 1, fv);
					}
					else if(uniType == eGL_FLOAT_VEC4)
					{
						gl.glGetUniformfv(curProg, origloc, fv);
						gl.glUniform4fv(newloc, 1, fv);
					}
					else
					{
						RDCERR("Uniform type '%s' not being copied to new program", ToStr::Get(uniType).c_str());
					}
				}
			}
		}
		
		float black[] = { 0.0f, 0.0f, 0.0f, 0.5f };
		gl.glClearBufferfv(eGL_COLOR, 0, black);

		GLint colLoc = gl.glGetUniformLocation(progDetails.colOutProg, "RENDERDOC_GenericFS_Color");
		float colVal[] = { 0.8f, 0.1f, 0.8f, 1.0f };
		gl.glUniform4fv(colLoc, 1, colVal);

		ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
		
		gl.glUseProgram(curProg);
	}
	else if(overlay == eTexOverlay_Wireframe)
	{
		gl.glUseProgram(progDetails.colOutProg);
		
		{
			// copy across uniforms
			GLint numUniforms = 0;
			gl.glGetProgramiv(curProg, eGL_ACTIVE_UNIFORMS, &numUniforms);

			for(GLint i=0; i < numUniforms; i++)
			{
				char uniName[1024] = {};
				GLint uniSize = 0;
				GLenum uniType = eGL_UNKNOWN_ENUM;
				gl.glGetActiveUniform(curProg, i, 1024, NULL, &uniSize, &uniType, uniName);

				GLint origloc = gl.glGetUniformLocation(curProg, uniName);
				GLint newloc = gl.glGetUniformLocation(progDetails.colOutProg, uniName);

				double dv[16];
				float *fv = (float *)dv;

				if(uniSize > 1)
				{
					RDCERR("Array elements beyond [0] not being copied to new program");
				}

				if(origloc != -1 && newloc != -1)
				{
					if(uniType == eGL_FLOAT_MAT4)
					{
						gl.glGetUniformfv(curProg, origloc, fv);
						gl.glUniformMatrix4fv(newloc, 1, false, fv);
					}
					else if(uniType == eGL_FLOAT_VEC3)
					{
						gl.glGetUniformfv(curProg, origloc, fv);
						gl.glUniform3fv(newloc, 1, fv);
					}
					else if(uniType == eGL_FLOAT_VEC4)
					{
						gl.glGetUniformfv(curProg, origloc, fv);
						gl.glUniform4fv(newloc, 1, fv);
					}
					else
					{
						RDCERR("Uniform type '%s' not being copied to new program", ToStr::Get(uniType).c_str());
					}
				}
			}
		}
		
		float wireCol[] = { 200.0f/255.0f, 255.0f/255.0f, 0.0f/255.0f, 0.0f };
		gl.glClearBufferfv(eGL_COLOR, 0, wireCol);

		GLint colLoc = gl.glGetUniformLocation(progDetails.colOutProg, "RENDERDOC_GenericFS_Color");
		wireCol[3] = 1.0f;
		gl.glUniform4fv(colLoc, 1, wireCol);

		GLint depthTest = GL_FALSE;
		gl.glGetIntegerv(eGL_DEPTH_TEST, (GLint*)&depthTest);
		GLenum polyMode = eGL_FILL;
		gl.glGetIntegerv(eGL_POLYGON_MODE, (GLint*)&polyMode);

		gl.glDisable(eGL_DEPTH_TEST);
		gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_LINE);

		ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);

		if(depthTest)
			gl.glEnable(eGL_DEPTH_TEST);
		if(polyMode != eGL_LINE)
			gl.glPolygonMode(eGL_FRONT_AND_BACK, polyMode);
		
		gl.glUseProgram(curProg);
	}
	
	gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, curDrawFBO);
	gl.glBindFramebuffer(eGL_READ_FRAMEBUFFER, curReadFBO);

	return m_pDriver->GetResourceManager()->GetID(TextureRes(DebugData.overlayTex));
}
Exemple #26
0
void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl)
{
	GLResourceManager *rm = gl->GetResourceManager();
	// TODO check GL_MAX_*

	m_pSerialiser->Serialise<eEnabled_Count>("GL_ENABLED", Enabled);
	
	for(size_t i=0; i < ARRAY_COUNT(Tex2D); i++)
	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(TextureRes(ctx, Tex2D[i]));
		m_pSerialiser->Serialise("GL_TEXTURE_BINDING_2D", ID);
		if(state < WRITING && ID != ResourceId()) Tex2D[i] = rm->GetLiveResource(ID).name;
	}
	
	for(size_t i=0; i < ARRAY_COUNT(Samplers); i++)
	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(SamplerRes(ctx, Samplers[i]));
		m_pSerialiser->Serialise("GL_SAMPLER_BINDING", ID);
		if(state < WRITING && ID != ResourceId()) Samplers[i] = rm->GetLiveResource(ID).name;
	}

	m_pSerialiser->Serialise("GL_ACTIVE_TEXTURE", ActiveTexture);
	
	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(VertexArrayRes(ctx, VAO));
		m_pSerialiser->Serialise("GL_VERTEX_ARRAY_BINDING", ID);
		if(state < WRITING && ID != ResourceId()) VAO = rm->GetLiveResource(ID).name;

		if(VAO == 0) VAO = gl->GetFakeVAO();
	}
	
	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(FeedbackRes(ctx, FeedbackObj));
		m_pSerialiser->Serialise("GL_TRANSFORM_FEEDBACK_BINDING", ID);
		if(state < WRITING && ID != ResourceId()) FeedbackObj = rm->GetLiveResource(ID).name;
	}
	
	for(size_t i=0; i < ARRAY_COUNT(GenericVertexAttribs); i++)
	{
		m_pSerialiser->Serialise<4>("GL_CURRENT_VERTEX_ATTRIB", &GenericVertexAttribs[i].x);
	}
	
	m_pSerialiser->Serialise("GL_POINT_FADE_THRESHOLD_SIZE", PointFadeThresholdSize);
	m_pSerialiser->Serialise("GL_POINT_SPRITE_COORD_ORIGIN", PointSpriteOrigin);
	m_pSerialiser->Serialise("GL_LINE_WIDTH", LineWidth);
	m_pSerialiser->Serialise("GL_POINT_SIZE", PointSize);
	
	m_pSerialiser->Serialise("GL_PRIMITIVE_RESTART_INDEX", PrimitiveRestartIndex);
	m_pSerialiser->Serialise("GL_CLIP_ORIGIN", ClipOrigin);
	m_pSerialiser->Serialise("GL_CLIP_DEPTH_MODE", ClipDepth);
	m_pSerialiser->Serialise("GL_PROVOKING_VERTEX", ProvokingVertex);

	for(size_t i=0; i < ARRAY_COUNT(BufferBindings); i++)
	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(BufferRes(ctx, BufferBindings[i]));
		m_pSerialiser->Serialise("GL_BUFFER_BINDING", ID);
		if(state < WRITING && ID != ResourceId()) BufferBindings[i] = rm->GetLiveResource(ID).name;
	}
	
	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(ProgramRes(ctx, Program));
		m_pSerialiser->Serialise("GL_CURRENT_PROGRAM", ID);
		if(state < WRITING && ID != ResourceId()) Program = rm->GetLiveResource(ID).name;
	}
	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(ProgramPipeRes(ctx, Pipeline));
		m_pSerialiser->Serialise("GL_PROGRAM_PIPELINE_BINDING", ID);
		if(state < WRITING && ID != ResourceId()) Pipeline = rm->GetLiveResource(ID).name;
	}
	
	for(size_t s=0; s < ARRAY_COUNT(Subroutines); s++)
	{
		m_pSerialiser->Serialise("GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS", Subroutines[s].numSubroutines);
		m_pSerialiser->Serialise<128>("GL_SUBROUTINE_UNIFORMS", Subroutines[s].Values);
	}

	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(FramebufferRes(ctx, DrawFBO));
		m_pSerialiser->Serialise("GL_DRAW_FRAMEBUFFER_BINDING", ID);
		if(state < WRITING && ID != ResourceId()) DrawFBO = rm->GetLiveResource(ID).name;

		if(DrawFBO == 0) DrawFBO = gl->GetFakeBBFBO();
	}
	{
		ResourceId ID = ResourceId();
		if(state >= WRITING) ID = rm->GetID(FramebufferRes(ctx, ReadFBO));
		m_pSerialiser->Serialise("GL_READ_FRAMEBUFFER_BINDING", ID);
		if(state < WRITING && ID != ResourceId()) ReadFBO = rm->GetLiveResource(ID).name;

		if(ReadFBO == 0) ReadFBO = gl->GetFakeBBFBO();
	}
	
	struct { IdxRangeBuffer *bufs; int count; } idxBufs[] =
	{
		{ AtomicCounter, ARRAY_COUNT(AtomicCounter), },
		{ ShaderStorage, ARRAY_COUNT(ShaderStorage), },
		{ TransformFeedback, ARRAY_COUNT(TransformFeedback), },
		{ UniformBinding, ARRAY_COUNT(UniformBinding), },
	};

	for(size_t b=0; b < ARRAY_COUNT(idxBufs); b++)
	{
		for(int i=0; i < idxBufs[b].count; i++)
		{
			ResourceId ID = ResourceId();
			if(state >= WRITING) ID = rm->GetID(BufferRes(ctx, idxBufs[b].bufs[i].name));
			m_pSerialiser->Serialise("BUFFER_BINDING", ID);
			if(state < WRITING && ID != ResourceId()) idxBufs[b].bufs[i].name = rm->GetLiveResource(ID).name;

			m_pSerialiser->Serialise("BUFFER_START", idxBufs[b].bufs[i].start);
			m_pSerialiser->Serialise("BUFFER_SIZE", idxBufs[b].bufs[i].size);
		}
	}
	
	for(size_t i=0; i < ARRAY_COUNT(Blends); i++)
	{
		m_pSerialiser->Serialise("GL_BLEND_EQUATION_RGB", Blends[i].EquationRGB);
		m_pSerialiser->Serialise("GL_BLEND_EQUATION_ALPHA", Blends[i].EquationAlpha);

		m_pSerialiser->Serialise("GL_BLEND_SRC_RGB", Blends[i].SourceRGB);
		m_pSerialiser->Serialise("GL_BLEND_SRC_ALPHA", Blends[i].SourceAlpha);

		m_pSerialiser->Serialise("GL_BLEND_DST_RGB", Blends[i].DestinationRGB);
		m_pSerialiser->Serialise("GL_BLEND_DST_ALPHA", Blends[i].DestinationAlpha);
		
		m_pSerialiser->Serialise("GL_BLEND", Blends[i].Enabled);
	}
	
	m_pSerialiser->Serialise<4>("GL_BLEND_COLOR", BlendColor);
		
	for(size_t i=0; i < ARRAY_COUNT(Viewports); i++)
	{
		m_pSerialiser->Serialise("GL_VIEWPORT.x", Viewports[i].x);
		m_pSerialiser->Serialise("GL_VIEWPORT.y", Viewports[i].y);
		m_pSerialiser->Serialise("GL_VIEWPORT.w", Viewports[i].width);
		m_pSerialiser->Serialise("GL_VIEWPORT.h", Viewports[i].height);
	}

	for(size_t i=0; i < ARRAY_COUNT(Scissors); i++)
	{
		m_pSerialiser->Serialise("GL_SCISSOR.x", Scissors[i].x);
		m_pSerialiser->Serialise("GL_SCISSOR.y", Scissors[i].y);
		m_pSerialiser->Serialise("GL_SCISSOR.w", Scissors[i].width);
		m_pSerialiser->Serialise("GL_SCISSOR.h", Scissors[i].height);
		m_pSerialiser->Serialise("GL_SCISSOR.enabled", Scissors[i].enabled);
	}
	
	m_pSerialiser->Serialise<8>("GL_DRAW_BUFFERS", DrawBuffers);
	m_pSerialiser->Serialise("GL_READ_BUFFER", ReadBuffer);

	m_pSerialiser->Serialise("GL_FRAGMENT_SHADER_DERIVATIVE_HINT", Hints.Derivatives);
	m_pSerialiser->Serialise("GL_LINE_SMOOTH_HINT", Hints.LineSmooth);
	m_pSerialiser->Serialise("GL_POLYGON_SMOOTH_HINT", Hints.PolySmooth);
	m_pSerialiser->Serialise("GL_TEXTURE_COMPRESSION_HINT", Hints.TexCompression);
	
	m_pSerialiser->Serialise("GL_DEPTH_WRITEMASK", DepthWriteMask);
	m_pSerialiser->Serialise("GL_DEPTH_CLEAR_VALUE", DepthClearValue);
	m_pSerialiser->Serialise("GL_DEPTH_FUNC", DepthFunc);
	
	for(size_t i=0; i < ARRAY_COUNT(DepthRanges); i++)
	{
		m_pSerialiser->Serialise("GL_DEPTH_RANGE.near", DepthRanges[i].nearZ);
		m_pSerialiser->Serialise("GL_DEPTH_RANGE.far", DepthRanges[i].farZ);
	}
	
	{
		m_pSerialiser->Serialise("GL_DEPTH_BOUNDS_EXT.near", DepthBounds.nearZ);
		m_pSerialiser->Serialise("GL_DEPTH_BOUNDS_EXT.far", DepthBounds.farZ);
	}
	
	{
		m_pSerialiser->Serialise("GL_STENCIL_FUNC", StencilFront.func);
		m_pSerialiser->Serialise("GL_STENCIL_BACK_FUNC", StencilBack.func);

		m_pSerialiser->Serialise("GL_STENCIL_REF", StencilFront.ref);
		m_pSerialiser->Serialise("GL_STENCIL_BACK_REF", StencilBack.ref);

		m_pSerialiser->Serialise("GL_STENCIL_VALUE_MASK", StencilFront.valuemask);
		m_pSerialiser->Serialise("GL_STENCIL_BACK_VALUE_MASK", StencilBack.valuemask);
		
		m_pSerialiser->Serialise("GL_STENCIL_WRITEMASK", StencilFront.writemask);
		m_pSerialiser->Serialise("GL_STENCIL_BACK_WRITEMASK", StencilBack.writemask);

		m_pSerialiser->Serialise("GL_STENCIL_FAIL", StencilFront.stencilFail);
		m_pSerialiser->Serialise("GL_STENCIL_BACK_FAIL", StencilBack.stencilFail);

		m_pSerialiser->Serialise("GL_STENCIL_PASS_DEPTH_FAIL", StencilFront.depthFail);
		m_pSerialiser->Serialise("GL_STENCIL_BACK_PASS_DEPTH_FAIL", StencilBack.depthFail);

		m_pSerialiser->Serialise("GL_STENCIL_PASS_DEPTH_PASS", StencilFront.pass);
		m_pSerialiser->Serialise("GL_STENCIL_BACK_PASS_DEPTH_PASS", StencilBack.pass);
	}

	m_pSerialiser->Serialise("GL_STENCIL_CLEAR_VALUE", StencilClearValue);

	for(size_t i=0; i < ARRAY_COUNT(ColorMasks); i++)
		m_pSerialiser->Serialise<4>("GL_COLOR_WRITEMASK", &ColorMasks[i].red);
	
	m_pSerialiser->Serialise<2>("GL_SAMPLE_MASK_VALUE", &SampleMask[0]);
	m_pSerialiser->Serialise("GL_SAMPLE_COVERAGE_VALUE", SampleCoverage);
	m_pSerialiser->Serialise("GL_SAMPLE_COVERAGE_INVERT", SampleCoverageInvert);
	m_pSerialiser->Serialise("GL_MIN_SAMPLE_SHADING", MinSampleShading);

	m_pSerialiser->Serialise("GL_RASTER_SAMPLES_EXT", RasterSamples);
	m_pSerialiser->Serialise("GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT", RasterFixed);

	m_pSerialiser->Serialise("GL_LOGIC_OP_MODE", LogicOp);

	m_pSerialiser->Serialise<4>("GL_COLOR_CLEAR_VALUE", &ColorClearValue.red);

	{
		m_pSerialiser->Serialise("GL_PATCH_VERTICES", PatchParams.numVerts);
		m_pSerialiser->Serialise<2>("GL_PATCH_DEFAULT_INNER_LEVEL", &PatchParams.defaultInnerLevel[0]);
		m_pSerialiser->Serialise<4>("GL_PATCH_DEFAULT_OUTER_LEVEL", &PatchParams.defaultOuterLevel[0]);
	}

	m_pSerialiser->Serialise("GL_POLYGON_MODE", PolygonMode);
	m_pSerialiser->Serialise("GL_POLYGON_OFFSET_FACTOR", PolygonOffset[0]);
	m_pSerialiser->Serialise("GL_POLYGON_OFFSET_UNITS", PolygonOffset[1]);
	m_pSerialiser->Serialise("GL_POLYGON_OFFSET_CLAMP_EXT", PolygonOffset[2]);
		
	m_pSerialiser->Serialise("GL_FRONT_FACE", FrontFace);
	m_pSerialiser->Serialise("GL_CULL_FACE_MODE", CullFace);
}
Exemple #27
0
void GLReplay::SavePipelineState()
{
	GLPipelineState &pipe = m_CurPipelineState;
	WrappedOpenGL &gl = *m_pDriver;
	GLResourceManager *rm = m_pDriver->GetResourceManager();

	MakeCurrentReplayContext(&m_ReplayCtx);

	// Index buffer

	pipe.m_VtxIn.ibuffer.Offset = m_pDriver->m_LastIndexOffset;
	
	pipe.m_VtxIn.ibuffer.Format = ResourceFormat();
	pipe.m_VtxIn.ibuffer.Format.special = false;
	pipe.m_VtxIn.ibuffer.Format.compCount = 1;
	pipe.m_VtxIn.ibuffer.Format.compType = eCompType_UInt;
	switch(m_pDriver->m_LastIndexSize)
	{
		default:
			break;
		case eGL_UNSIGNED_BYTE:
			pipe.m_VtxIn.ibuffer.Format.compByteWidth = 1;
			pipe.m_VtxIn.ibuffer.Format.strname = L"GL_UNSIGNED_BYTE";
			break;
		case eGL_UNSIGNED_SHORT:
			pipe.m_VtxIn.ibuffer.Format.compByteWidth = 2;
			pipe.m_VtxIn.ibuffer.Format.strname = L"GL_UNSIGNED_SHORT";
			break;
		case eGL_UNSIGNED_INT:
			pipe.m_VtxIn.ibuffer.Format.compByteWidth = 4;
			pipe.m_VtxIn.ibuffer.Format.strname = L"GL_UNSIGNED_INT";
			break;
	}

	GLint curIdxBuf = 0;
	gl.glGetIntegerv(eGL_ELEMENT_ARRAY_BUFFER_BINDING, &curIdxBuf);

	pipe.m_VtxIn.ibuffer.Buffer = rm->GetOriginalID(rm->GetID(BufferRes(curIdxBuf)));

	// Vertex buffers and attributes
	GLint numVBufferBindings = 16;
	gl.glGetIntegerv(eGL_MAX_VERTEX_ATTRIB_BINDINGS, &numVBufferBindings);
	
	GLint numVAttribBindings = 16;
	gl.glGetIntegerv(eGL_MAX_VERTEX_ATTRIBS, &numVAttribBindings);

	create_array_uninit(pipe.m_VtxIn.vbuffers, numVBufferBindings);
	create_array_uninit(pipe.m_VtxIn.attributes, numVAttribBindings);

	for(GLuint i=0; i < (GLuint)numVBufferBindings; i++)
	{
		GLint vb = 0;
		gl.glGetIntegeri_v(eGL_VERTEX_BINDING_BUFFER, i, &vb);
		pipe.m_VtxIn.vbuffers[i].Buffer = rm->GetOriginalID(rm->GetID(BufferRes(vb)));

		gl.glGetIntegeri_v(eGL_VERTEX_BINDING_STRIDE, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Stride);
		gl.glGetIntegeri_v(eGL_VERTEX_BINDING_OFFSET, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Offset);
		gl.glGetIntegeri_v(eGL_VERTEX_BINDING_DIVISOR, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Divisor);
		pipe.m_VtxIn.vbuffers[i].PerInstance = (pipe.m_VtxIn.vbuffers[i].Divisor != 0);
	}
	
	for(GLuint i=0; i < (GLuint)numVAttribBindings; i++)
	{
		gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *)&pipe.m_VtxIn.attributes[i].Enabled);
		gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_BINDING, (GLint *)&pipe.m_VtxIn.attributes[i].BufferSlot);
		gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_RELATIVE_OFFSET, (GLint*)&pipe.m_VtxIn.attributes[i].RelativeOffset);

		GLenum type = eGL_FLOAT;
		GLint normalized = 0;
		
		gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint *)&type);
		gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized);

		ResourceFormat fmt;

		fmt.special = false;
		fmt.compCount = 4;
		gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_SIZE, (GLint *)&fmt.compCount);
		
		switch(type)
		{
			default:
			case eGL_BYTE:
				fmt.compByteWidth = 1;
				fmt.compType = normalized ? eCompType_SInt : eCompType_SNorm;
				fmt.strname = StringFormat::WFmt(L"GL_BYTE%d", fmt.compCount) + (normalized ? L"" : L"_SNORM");
				break;
			case eGL_UNSIGNED_BYTE:
				fmt.compByteWidth = 1;
				fmt.compType = normalized ? eCompType_UInt : eCompType_UNorm;
				fmt.strname = StringFormat::WFmt(L"GL_UNSIGNED_BYTE%d", fmt.compCount) + (normalized ? L"" : L"_UNORM");
				break;
			case eGL_SHORT:
				fmt.compByteWidth = 2;
				fmt.compType = normalized ? eCompType_SInt : eCompType_SNorm;
				fmt.strname = StringFormat::WFmt(L"GL_SHORT%d", fmt.compCount) + (normalized ? L"" : L"_SNORM");
				break;
			case eGL_UNSIGNED_SHORT:
				fmt.compByteWidth = 2;
				fmt.compType = normalized ? eCompType_UInt : eCompType_UNorm;
				fmt.strname = StringFormat::WFmt(L"GL_UNSIGNED_SHORT%d", fmt.compCount) + (normalized ? L"" : L"_UNORM");
				break;
			case eGL_INT:
				fmt.compByteWidth = 4;
				fmt.compType = normalized ? eCompType_SInt : eCompType_SNorm;
				fmt.strname = StringFormat::WFmt(L"GL_INT%d", fmt.compCount) + (normalized ? L"" : L"_SNORM");
				break;
			case eGL_UNSIGNED_INT:
				fmt.compByteWidth = 4;
				fmt.compType = normalized ? eCompType_UInt : eCompType_UNorm;
				fmt.strname = StringFormat::WFmt(L"GL_UNSIGNED_INT%d", fmt.compCount) + (normalized ? L"" : L"_UNORM");
				break;
			case eGL_FLOAT:
				fmt.compByteWidth = 4;
				fmt.compType = eCompType_Float;
				fmt.strname = StringFormat::WFmt(L"GL_FLOAT%d", fmt.compCount);
				break;
			case eGL_DOUBLE:
				fmt.compByteWidth = 8;
				fmt.compType = eCompType_Double;
				fmt.strname = StringFormat::WFmt(L"GL_DOUBLE%d", fmt.compCount);
				break;
			case eGL_HALF_FLOAT:
				fmt.compByteWidth = 2;
				fmt.compType = eCompType_Float;
				fmt.strname = StringFormat::WFmt(L"GL_HALF_FLOAT%d", fmt.compCount);
				break;
			case eGL_INT_2_10_10_10_REV:
				fmt.special = true;
				fmt.specialFormat = eSpecial_R10G10B10A2;
				fmt.compCount = 4;
				fmt.compType = eCompType_UInt;
				fmt.strname = L"GL_INT_2_10_10_10_REV";
				break;
			case eGL_UNSIGNED_INT_2_10_10_10_REV:
				fmt.special = true;
				fmt.specialFormat = eSpecial_R10G10B10A2;
				fmt.compCount = 4;
				fmt.compType = eCompType_SInt;
				fmt.strname = L"eGL_UNSIGNED_INT_2_10_10_10_REV";
				break;
			case eGL_UNSIGNED_INT_10F_11F_11F_REV:
				fmt.special = true;
				fmt.specialFormat = eSpecial_R11G11B10;
				fmt.compCount = 3;
				fmt.compType = eCompType_SInt;
				fmt.strname = L"eGL_UNSIGNED_INT_10F_11F_11F_REV";
				break;
		}

		pipe.m_VtxIn.attributes[i].Format = fmt;
	}

	switch(m_pDriver->m_LastDrawMode)
	{
		default:
			pipe.m_VtxIn.Topology = eTopology_Unknown;
			break;
		case GL_POINTS:
			pipe.m_VtxIn.Topology = eTopology_PointList;
			break;
		case GL_LINE_STRIP:
			pipe.m_VtxIn.Topology = eTopology_LineStrip;
			break;
		case GL_LINE_LOOP:
			pipe.m_VtxIn.Topology = eTopology_LineLoop;
			break;
		case GL_LINES:
			pipe.m_VtxIn.Topology = eTopology_LineList;
			break;
		case GL_LINE_STRIP_ADJACENCY:
			pipe.m_VtxIn.Topology = eTopology_LineStrip_Adj;
			break;
		case GL_LINES_ADJACENCY:
			pipe.m_VtxIn.Topology = eTopology_LineList_Adj;
			break;
		case GL_TRIANGLE_STRIP:
			pipe.m_VtxIn.Topology = eTopology_TriangleStrip;
			break;
		case GL_TRIANGLE_FAN:
			pipe.m_VtxIn.Topology = eTopology_TriangleFan;
			break;
		case GL_TRIANGLES:
			pipe.m_VtxIn.Topology = eTopology_TriangleList;
			break;
		case GL_TRIANGLE_STRIP_ADJACENCY:
			pipe.m_VtxIn.Topology = eTopology_TriangleStrip_Adj;
			break;
		case GL_TRIANGLES_ADJACENCY:
			pipe.m_VtxIn.Topology = eTopology_TriangleList_Adj;
			break;
		case GL_PATCHES:
		{
			GLint patchCount = 3;
			gl.glGetIntegerv(eGL_PATCH_VERTICES, &patchCount);
			pipe.m_VtxIn.Topology = PrimitiveTopology(eTopology_PatchList_1CPs+patchCount);
			break;
		}
	}

	// Shader stages
	
	GLuint curProg = 0;
	gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg);
	
	auto &progDetails = m_pDriver->m_Programs[rm->GetID(ProgramRes(curProg))];

	RDCASSERT(progDetails.shaders.size());

	for(size_t i=0; i < progDetails.shaders.size(); i++)
	{
		if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_VERTEX_SHADER)
			pipe.m_VS.Shader = rm->GetOriginalID(progDetails.shaders[i]);
		else if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_FRAGMENT_SHADER)
			pipe.m_FS.Shader = rm->GetOriginalID(progDetails.shaders[i]);
	}
	
	pipe.m_VS.stage = eShaderStage_Vertex;
	pipe.m_TCS.stage = eShaderStage_Tess_Control;
	pipe.m_TES.stage = eShaderStage_Tess_Eval;
	pipe.m_GS.stage = eShaderStage_Geometry;
	pipe.m_FS.stage = eShaderStage_Fragment;
	pipe.m_CS.stage = eShaderStage_Compute;

	// Textures
	
	GLint numTexUnits = 8;
	gl.glGetIntegerv(eGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numTexUnits);
	create_array_uninit(pipe.Textures, numTexUnits);

	GLenum activeTexture = eGL_TEXTURE0;
	gl.glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint*)&activeTexture);

	// GL is ass-backwards in its handling of texture units. When a shader is active
	// the types in the glsl samplers inform which targets are used from which texture units
	//
	// So texture unit 5 can have a 2D bound (texture 52) and a Cube bound (texture 77).
	// * if a uniform sampler2D has value 5 then the 2D texture is used, and we sample from 52
	// * if a uniform samplerCube has value 5 then the Cube texture is used, and we sample from 77
	// It's illegal for both a sampler2D and samplerCube to both have the same value (or any two
	// different types). It makes it all rather pointless and needlessly complex.
	//
	// What we have to do then, is consider the program, look at the values of the uniforms, and
	// then get the appropriate current binding based on the uniform type. We can warn/alert the
	// user if we hit the illegal case of two uniforms with different types but the same value
	//
	// Handling is different if no shaders are active, but we don't consider that case.


	// prefetch uniform values in GetShader()
	ShaderReflection *refls[6];
	for(size_t s=0; s < progDetails.shaders.size(); s++)
		refls[s] = GetShader(progDetails.shaders[s]);

	for(GLint unit=0; unit < numTexUnits; unit++)
	{
		GLenum binding = eGL_UNKNOWN_ENUM;
		GLenum target = eGL_UNKNOWN_ENUM;
		
		for(size_t s=0; s < progDetails.shaders.size(); s++)
		{
			if(refls[s] == NULL) continue;

			for(int32_t r=0; r < refls[s]->Resources.count; r++)
			{
				// bindPoint is the uniform value for this sampler
				if(refls[s]->Resources[r].bindPoint == (uint32_t)unit)
				{
					GLenum t = eGL_UNKNOWN_ENUM;

					switch(refls[s]->Resources[r].resType)
					{
						case eResType_None:
							t = eGL_UNKNOWN_ENUM;
							break;
						case eResType_Buffer:
							t = eGL_TEXTURE_BINDING_BUFFER;
							break;
						case eResType_Texture1D:
							t = eGL_TEXTURE_BINDING_1D;
							target = eGL_TEXTURE_1D;
							break;
						case eResType_Texture1DArray:
							t = eGL_TEXTURE_BINDING_1D_ARRAY;
							target = eGL_TEXTURE_1D_ARRAY;
							break;
						case eResType_Texture2D:
							t = eGL_TEXTURE_BINDING_2D;
							target = eGL_TEXTURE_2D;
							break;
						case eResType_Texture2DArray:
							t = eGL_TEXTURE_BINDING_2D_ARRAY;
							target = eGL_TEXTURE_2D_ARRAY;
							break;
						case eResType_Texture2DMS:
							t = eGL_TEXTURE_BINDING_2D_MULTISAMPLE;
							target = eGL_TEXTURE_2D_MULTISAMPLE;
							break;
						case eResType_Texture2DMSArray:
							t = eGL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY;
							target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY;
							break;
						case eResType_Texture3D:
							t = eGL_TEXTURE_BINDING_3D;
							target = eGL_TEXTURE_3D;
							break;
						case eResType_TextureCube:
							t = eGL_TEXTURE_BINDING_CUBE_MAP;
							target = eGL_TEXTURE_CUBE_MAP;
							break;
						case eResType_TextureCubeArray:
							t = eGL_TEXTURE_BINDING_CUBE_MAP_ARRAY;
							target = eGL_TEXTURE_CUBE_MAP_ARRAY;
							break;
					}

					if(binding == eGL_UNKNOWN_ENUM)
					{
						binding = t;
					}
					else if(binding == t)
					{
						// two uniforms with the same type pointing to the same slot is fine
						binding = t;
					}
					else if(binding != t)
					{
						RDCWARN("Two uniforms pointing to texture unit %d with types %s and %s", unit, ToStr::Get(binding).c_str(), ToStr::Get(t).c_str());
					}
				}
			}
		}

		if(binding != eGL_UNKNOWN_ENUM)
		{
			gl.glActiveTexture(GLenum(eGL_TEXTURE0+unit));

			GLuint tex;
			gl.glGetIntegerv(binding, (GLint *)&tex);

			// very bespoke/specific
			GLint firstSlice = 0;
			gl.glGetTexParameteriv(target, eGL_TEXTURE_VIEW_MIN_LEVEL, &firstSlice);

			pipe.Textures[unit].Resource = rm->GetOriginalID(rm->GetID(TextureRes(tex)));
			pipe.Textures[unit].FirstSlice = (uint32_t)firstSlice;
		}
		else
		{
			// what should we do in this case? there could be something bound just not used,
			// it'd be nice to return that
		}
	}

	gl.glActiveTexture(activeTexture);

	GLuint curFBO = 0;
	gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&curFBO);
	
	GLint numCols = 8;
	gl.glGetIntegerv(eGL_MAX_COLOR_ATTACHMENTS, &numCols);

	GLuint curCol[32] = { 0 };
	GLuint curDepth = 0;
	GLuint curStencil = 0;

	RDCASSERT(numCols <= 32);

	// we should never bind the true default framebuffer - if the app did, we will have our fake bound
	RDCASSERT(curFBO != 0);

	{
		for(GLint i=0; i < numCols; i++)
			gl.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, GLenum(eGL_COLOR_ATTACHMENT0+i), eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&curCol[i]);
		gl.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&curDepth);
		gl.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&curStencil);
	}

	pipe.m_FB.FBO = rm->GetOriginalID(rm->GetID(FramebufferRes(curFBO)));
	create_array_uninit(pipe.m_FB.Color, numCols);
	for(GLint i=0; i < numCols; i++)
		pipe.m_FB.Color[i] = rm->GetOriginalID(rm->GetID(TextureRes(curCol[i])));

	pipe.m_FB.Depth = rm->GetOriginalID(rm->GetID(TextureRes(curDepth)));
	pipe.m_FB.Stencil = rm->GetOriginalID(rm->GetID(TextureRes(curStencil)));
}
Exemple #28
0
bool WrappedOpenGL::Serialise_glObjectLabel(SerialiserType &ser, GLenum identifier, GLuint name,
                                            GLsizei length, const GLchar *label)
{
  GLResource Resource;
  std::string Label;

  if(ser.IsWriting())
  {
    // we share implementations between KHR_debug and EXT_debug_label, however KHR_debug follows the
    // pattern elsewhere (e.g. in glShaderSource) of a length of -1 meaning indeterminate
    // NULL-terminated length, but EXT_debug_label takes length of 0 to mean that.
    GLsizei realLength = length;
    if(gl_CurChunk == GLChunk::glLabelObjectEXT && length == 0)
      realLength = -1;

    // if length is negative (after above twiddling), it's taken from strlen and the label must be
    // NULL-terminated
    if(realLength < 0)
      realLength = label ? (GLsizei)strlen(label) : 0;

    if(realLength == 0 || label == NULL)
      Label = "";
    else
      Label = std::string(label, label + realLength);

    switch(identifier)
    {
      case eGL_TEXTURE: Resource = TextureRes(GetCtx(), name); break;
      case eGL_BUFFER_OBJECT_EXT:
      case eGL_BUFFER: Resource = BufferRes(GetCtx(), name); break;
      case eGL_PROGRAM_OBJECT_EXT:
      case eGL_PROGRAM: Resource = ProgramRes(GetCtx(), name); break;
      case eGL_PROGRAM_PIPELINE_OBJECT_EXT:
      case eGL_PROGRAM_PIPELINE: Resource = ProgramPipeRes(GetCtx(), name); break;
      case eGL_VERTEX_ARRAY_OBJECT_EXT:
      case eGL_VERTEX_ARRAY: Resource = VertexArrayRes(GetCtx(), name); break;
      case eGL_SHADER_OBJECT_EXT:
      case eGL_SHADER: Resource = ShaderRes(GetCtx(), name); break;
      case eGL_QUERY_OBJECT_EXT:
      case eGL_QUERY: Resource = QueryRes(GetCtx(), name); break;
      case eGL_TRANSFORM_FEEDBACK: Resource = FeedbackRes(GetCtx(), name); break;
      case eGL_SAMPLER: Resource = SamplerRes(GetCtx(), name); break;
      case eGL_RENDERBUFFER: Resource = RenderbufferRes(GetCtx(), name); break;
      case eGL_FRAMEBUFFER: Resource = FramebufferRes(GetCtx(), name); break;
      default: RDCERR("Unhandled namespace in glObjectLabel");
    }
  }

  SERIALISE_ELEMENT(Resource);
  SERIALISE_ELEMENT(length);
  SERIALISE_ELEMENT(Label);

  SERIALISE_CHECK_READ_ERRORS();

  if(IsReplayingAndReading() && Resource.name)
  {
    ResourceId origId = GetResourceManager()->GetOriginalID(GetResourceManager()->GetID(Resource));

    GetResourceManager()->SetName(origId, Label);

    ResourceDescription &descr = GetReplay()->GetResourceDesc(origId);
    descr.SetCustomName(Label);
    AddResourceCurChunk(descr);
  }

  return true;
}
Exemple #29
0
bool WrappedOpenGL::Serialise_glObjectLabel(GLenum identifier, GLuint name, GLsizei length,
                                            const GLchar *label)
{
  ResourceId liveid;

  bool extvariant = false;

  string Label;
  if(m_State >= WRITING)
  {
    if(length == 0)
      Label = "";
    else
      Label = string(label, label + (length > 0 ? length : strlen(label)));

    switch(identifier)
    {
      case eGL_TEXTURE: liveid = GetResourceManager()->GetID(TextureRes(GetCtx(), name)); break;
      case eGL_BUFFER_OBJECT_EXT: extvariant = true;
      case eGL_BUFFER: liveid = GetResourceManager()->GetID(BufferRes(GetCtx(), name)); break;
      case eGL_PROGRAM_OBJECT_EXT: extvariant = true;
      case eGL_PROGRAM: liveid = GetResourceManager()->GetID(ProgramRes(GetCtx(), name)); break;
      case eGL_PROGRAM_PIPELINE_OBJECT_EXT: extvariant = true;
      case eGL_PROGRAM_PIPELINE:
        liveid = GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), name));
        break;
      case eGL_VERTEX_ARRAY_OBJECT_EXT: extvariant = true;
      case eGL_VERTEX_ARRAY:
        liveid = GetResourceManager()->GetID(VertexArrayRes(GetCtx(), name));
        break;
      case eGL_SHADER_OBJECT_EXT: extvariant = true;
      case eGL_SHADER: liveid = GetResourceManager()->GetID(ShaderRes(GetCtx(), name)); break;
      case eGL_QUERY_OBJECT_EXT: extvariant = true;
      case eGL_QUERY: liveid = GetResourceManager()->GetID(QueryRes(GetCtx(), name)); break;
      case eGL_TRANSFORM_FEEDBACK:
        liveid = GetResourceManager()->GetID(FeedbackRes(GetCtx(), name));
        break;
      case eGL_SAMPLER: liveid = GetResourceManager()->GetID(SamplerRes(GetCtx(), name)); break;
      case eGL_RENDERBUFFER:
        liveid = GetResourceManager()->GetID(RenderbufferRes(GetCtx(), name));
        break;
      case eGL_FRAMEBUFFER:
        liveid = GetResourceManager()->GetID(FramebufferRes(GetCtx(), name));
        break;
      default: RDCERR("Unhandled namespace in glObjectLabel");
    }
  }

  SERIALISE_ELEMENT(GLenum, Identifier, identifier);
  SERIALISE_ELEMENT(ResourceId, id, liveid);
  SERIALISE_ELEMENT(uint32_t, Length, length);
  SERIALISE_ELEMENT(bool, HasLabel, label != NULL);

  m_pSerialiser->SerialiseString("label", Label);

  if(m_State == READING && GetResourceManager()->HasLiveResource(id))
  {
    GLResource res = GetResourceManager()->GetLiveResource(id);

    if(extvariant && m_Real.glLabelObjectEXT)
      m_Real.glLabelObjectEXT(Identifier, res.name, Length, HasLabel ? Label.c_str() : NULL);
    else
      m_Real.glObjectLabel(Identifier, res.name, Length, HasLabel ? Label.c_str() : NULL);
  }

  return true;
}
Exemple #30
0
HANDLE WrappedOpenGL::wglDXRegisterObjectNV(HANDLE hDevice, void *dxObject, GLuint name,
                                            GLenum type, GLenum access)
{
  RDCASSERT(IsCaptureMode(m_State));

  ID3D11Resource *real = UnwrapDXResource(dxObject);

  if(real == NULL)
  {
    SetLastError(ERROR_OPEN_FAILED);
    return 0;
  }

  WrappedHANDLE *wrapped = new WrappedHANDLE();

  if(type == eGL_RENDERBUFFER)
    wrapped->res = RenderbufferRes(GetCtx(), name);
  else if(type == eGL_NONE)
    wrapped->res = BufferRes(GetCtx(), name);
  else
    wrapped->res = TextureRes(GetCtx(), name);

  GLResourceRecord *record = GetResourceManager()->GetResourceRecord(wrapped->res);

  if(!record)
  {
    RDCERR("Unrecognised object with type %x and name %u", type, name);
    delete wrapped;
    return NULL;
  }

  SERIALISE_TIME_CALL(wrapped->real =
                          m_Real.wglDXRegisterObjectNV(hDevice, real, name, type, access));

  {
    RDCASSERT(record);

    USE_SCRATCH_SERIALISER();
    SCOPED_SERIALISE_CHUNK(gl_CurChunk);
    Serialise_wglDXRegisterObjectNV(ser, wrapped->res, type, dxObject);

    record->AddChunk(scope.Get());
  }

  if(type != eGL_NONE)
  {
    ResourceFormat fmt;
    uint32_t width = 0, height = 0, depth = 0, mips = 0, layers = 0, samples = 0;
    GetDXTextureProperties(dxObject, fmt, width, height, depth, mips, layers, samples);

    // defined as arrays mostly for Coverity code analysis to stay calm about passing
    // them to the *TexParameter* functions
    GLint maxlevel[4] = {GLint(mips - 1), 0, 0, 0};

    m_Real.glTextureParameteriEXT(wrapped->res.name, type, eGL_TEXTURE_MAX_LEVEL, GLint(mips - 1));

    ResourceId texId = record->GetResourceID();
    m_Textures[texId].resource = wrapped->res;
    m_Textures[texId].curType = type;
    m_Textures[texId].width = width;
    m_Textures[texId].height = height;
    m_Textures[texId].depth = RDCMAX(depth, samples);
    m_Textures[texId].samples = samples;
    m_Textures[texId].dimension = 2;
    if(type == eGL_TEXTURE_1D || type == eGL_TEXTURE_1D_ARRAY)
      m_Textures[texId].dimension = 1;
    else if(type == eGL_TEXTURE_3D)
      m_Textures[texId].dimension = 3;

    m_Textures[texId].internalFormat = MakeGLFormat(fmt);
  }

  return wrapped;
}