Ejemplo n.º 1
0
PostVSMeshData GLReplay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage)
{
	PostVSMeshData ret;
	RDCEraseEl(ret);

	GLNOTIMP("GLReplay::GetPostVSBuffers");

	return ret;
}
Ejemplo n.º 2
0
bool GLReplay::IsOutputWindowVisible(uint64_t id)
{
	if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
		return false;

	GLNOTIMP("Optimisation missing - output window always returning true");

	return true;
}
Ejemplo n.º 3
0
ShaderReflection *GLReplay::GetShader(ResourceId id)
{
	WrappedOpenGL &gl = *m_pDriver;
	
	MakeCurrentReplayContext(&m_ReplayCtx);
	
	GLuint curProg = 0;
	gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg);
	
	auto &progDetails = m_pDriver->m_Programs[m_pDriver->GetResourceManager()->GetID(ProgramRes(curProg))];
	auto &shaderDetails = m_pDriver->m_Shaders[id];

	auto &refl = shaderDetails.reflection;

	// initialise reflection data
	// TODO: do this earlier. In glLinkProgram?
	if(refl.DebugInfo.files.count == 0)
	{
		refl.DebugInfo.entryFunc = "main";
		refl.DebugInfo.compileFlags = 0;
		create_array_uninit(refl.DebugInfo.files, shaderDetails.sources.size());
		for(size_t i=0; i < shaderDetails.sources.size(); i++)
		{
			refl.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i);
			refl.DebugInfo.files[i].second = shaderDetails.sources[i];
		}

		refl.Disassembly = "";

		vector<ShaderResource> resources;

		GLint numUniforms = 0;
		gl.glGetProgramInterfaceiv(curProg, eGL_UNIFORM, eGL_ACTIVE_RESOURCES, &numUniforms);

		const size_t numProps = 6;

		GLenum resProps[numProps] = {
			eGL_REFERENCED_BY_VERTEX_SHADER,
			
			eGL_TYPE, eGL_NAME_LENGTH, eGL_LOCATION, eGL_BLOCK_INDEX, eGL_ARRAY_SIZE,
		};

		if(shaderDetails.type == eGL_VERTEX_SHADER)          resProps[0] = eGL_REFERENCED_BY_VERTEX_SHADER;
		if(shaderDetails.type == eGL_TESS_CONTROL_SHADER)    resProps[0] = eGL_REFERENCED_BY_TESS_CONTROL_SHADER;
		if(shaderDetails.type == eGL_TESS_EVALUATION_SHADER) resProps[0] = eGL_REFERENCED_BY_TESS_EVALUATION_SHADER;
		if(shaderDetails.type == eGL_GEOMETRY_SHADER)        resProps[0] = eGL_REFERENCED_BY_GEOMETRY_SHADER;
		if(shaderDetails.type == eGL_FRAGMENT_SHADER)        resProps[0] = eGL_REFERENCED_BY_FRAGMENT_SHADER;
		if(shaderDetails.type == eGL_COMPUTE_SHADER)         resProps[0] = eGL_REFERENCED_BY_COMPUTE_SHADER;
		
		for(GLint u=0; u < numUniforms; u++)
		{
			GLint values[numProps];
			gl.glGetProgramResourceiv(curProg, eGL_UNIFORM, u, numProps, resProps, numProps, NULL, values);

			// skip if unused by this stage
			if(values[0] == GL_FALSE)
				continue;
			
			ShaderResource res;
			res.IsSampler = false; // no separate sampler objects in GL

			if(values[1] == GL_SAMPLER_2D)
			{
				res.IsSRV = true;
				res.IsTexture = true;
				res.IsUAV = false;
				res.resType = eResType_Texture2D;
				res.variableType.descriptor.name = "sampler2D";
				res.variableType.descriptor.rows = 1;
				res.variableType.descriptor.cols = 4;
				res.variableType.descriptor.elements = 1;
			}
			else if(values[1] == GL_INT_SAMPLER_1D)
			{
				res.IsSRV = true;
				res.IsTexture = true;
				res.IsUAV = false;
				res.resType = eResType_Texture1D;
				res.variableType.descriptor.name = "isampler1D";
				res.variableType.descriptor.rows = 1;
				res.variableType.descriptor.cols = 4;
				res.variableType.descriptor.elements = 1;
			}
			else
			{
				// fill in more sampler types
				continue;
			}

			res.variableAddress = values[3];

			create_array_uninit(res.name, values[2]+1);
			gl.glGetProgramResourceName(curProg, eGL_UNIFORM, u, values[2]+1, NULL, res.name.elems);
			res.name.count--; // trim off trailing null

			resources.push_back(res);
		}

		refl.Resources = resources;

		vector<ShaderConstant> globalUniforms;

		for(GLint u=0; u < numUniforms; u++)
		{
			GLint values[numProps];
			gl.glGetProgramResourceiv(curProg, eGL_UNIFORM, u, numProps, resProps, numProps, NULL, values);
			
			// skip if unused by this stage
			if(values[0] == GL_FALSE)
				continue;

			// don't look at block uniforms just yet
			if(values[4] != -1)
			{
				GLNOTIMP("Not fetching uniforms in UBOs (should become their own ConstantBlocks)");
				continue;
			}
			
			ShaderConstant var;
			
			if(values[1] == GL_FLOAT_VEC4)
			{
				var.type.descriptor.name = "vec4";
				var.type.descriptor.rows = 1;
				var.type.descriptor.cols = 4;
				var.type.descriptor.elements = values[5];
			}
			else if(values[1] == GL_FLOAT_VEC3)
			{
				var.type.descriptor.name = "vec3";
				var.type.descriptor.rows = 1;
				var.type.descriptor.cols = 3;
				var.type.descriptor.elements = values[5];
			}
			else if(values[1] == GL_FLOAT_MAT4)
			{
				var.type.descriptor.name = "mat4";
				var.type.descriptor.rows = 4;
				var.type.descriptor.cols = 4;
				var.type.descriptor.elements = values[5];
			}
			else
			{
				// fill in more uniform types
				continue;
			}

			var.reg.vec = values[3];
			var.reg.comp = 0;

			create_array_uninit(var.name, values[2]+1);
			gl.glGetProgramResourceName(curProg, eGL_UNIFORM, u, values[2]+1, NULL, var.name.elems);
			var.name.count--; // trim off trailing null

			if(strchr(var.name.elems, '.'))
			{
				GLNOTIMP("Variable contains . - structure not reconstructed");
			}

			globalUniforms.push_back(var);
		}

		vector<ConstantBlock> cbuffers;

		if(!globalUniforms.empty())
		{
			ConstantBlock globals;
			globals.name = "Globals";
			globals.bufferAddress = -1;
			globals.variables = globalUniforms;

			cbuffers.push_back(globals);
		}

		// here we would iterate over UNIFORM_BLOCKs or similar

		// TODO: fill in Interfaces with shader subroutines?
		// TODO: find a way of generating input/output signature.
		//       The only way I can think of doing this is to generate separable programs for each
		//       shader stage, but that requires modifying the glsl to redeclare built-in blocks if necessary.

		refl.ConstantBlocks = cbuffers;
	}

	// update samplers with latest uniform values
	for(int32_t i=0; i < refl.Resources.count; i++)
	{
		if(refl.Resources.elems[i].IsSRV && refl.Resources.elems[i].IsTexture)
			gl.glGetUniformiv(curProg, refl.Resources.elems[i].variableAddress, (GLint *)&refl.Resources.elems[i].bindPoint);
	}

	return &refl;
}
Ejemplo n.º 4
0
FetchBuffer GLReplay::GetBuffer(ResourceId id)
{
	FetchBuffer ret;
	
	MakeCurrentReplayContext(&m_ReplayCtx);
	
	auto &res = m_pDriver->m_Buffers[id];

	if(res.resource.Namespace == eResUnknown)
	{
		RDCERR("Details for invalid buffer id %llu requested", id);
		RDCEraseEl(ret);
		return ret;
	}
	
	WrappedOpenGL &gl = *m_pDriver;
	
	ret.ID = m_pDriver->GetResourceManager()->GetOriginalID(id);

	gl.glBindBuffer(res.curType, res.resource.name);

	ret.structureSize = 0;
	GLNOTIMP("Not fetching structure size (if there's an equivalent)");

	ret.creationFlags = 0;
	switch(res.curType)
	{
		case eGL_ARRAY_BUFFER:
			ret.creationFlags = eBufferCreate_VB;
			break;
		case eGL_ELEMENT_ARRAY_BUFFER:
			ret.creationFlags = eBufferCreate_IB;
			break;
		default:
			RDCERR("Unexpected buffer type %hs", ToStr::Get(res.curType).c_str());
	}

	GLint size;
	gl.glGetBufferParameteriv(res.curType, eGL_BUFFER_SIZE, &size);

	ret.byteSize = ret.length = (uint32_t)size;
	
	if(res.size == 0)
	{
		RDCWARN("BufferData::size didn't get filled out, setting at last minute");
		res.size = ret.byteSize;
	}

	string str = "";
	char name[128] = {0};
	gl.glGetObjectLabel(eGL_BUFFER, res.resource.name, 127, NULL, name);
	str = name;
	ret.customName = true;

	if(str == "")
	{
		ret.customName = false;
		str = StringFormat::Fmt("Buffer %llu", ret.ID);
	}

	ret.name = widen(str);

	return ret;
}
Ejemplo n.º 5
0
FetchTexture GLReplay::GetTexture(ResourceId id)
{
	FetchTexture tex;
	
	MakeCurrentReplayContext(&m_ReplayCtx);
	
	auto &res = m_pDriver->m_Textures[id];

	if(res.resource.Namespace == eResUnknown)
	{
		RDCERR("Details for invalid texture id %llu requested", id);
		RDCEraseEl(tex);
		return tex;
	}
	
	WrappedOpenGL &gl = *m_pDriver;
	
	tex.ID = m_pDriver->GetResourceManager()->GetOriginalID(id);

	gl.glBindTexture(res.curType, res.resource.name);

	// if I call this for levels 1, 2, .. etc. Can I get sizes that aren't mip dimensions?
	GLint width = 1, height = 1, depth = 1, samples=1;
	gl.glGetTexLevelParameteriv(res.curType, 0, eGL_TEXTURE_WIDTH, &width);
	gl.glGetTexLevelParameteriv(res.curType, 0, eGL_TEXTURE_HEIGHT, &height);
	gl.glGetTexLevelParameteriv(res.curType, 0, eGL_TEXTURE_DEPTH, &depth);
	gl.glGetTexLevelParameteriv(res.curType, 0, eGL_TEXTURE_SAMPLES, &samples);

	if(res.width == 0)
	{
		RDCWARN("TextureData::width didn't get filled out, setting at last minute");
		res.width = width;
	}
	if(res.height == 0)
	{
		RDCWARN("TextureData::height didn't get filled out, setting at last minute");
		res.height = height;
	}
	if(res.depth == 0)
	{
		RDCWARN("TextureData::depth didn't get filled out, setting at last minute");
		res.depth = depth;
	}

	// reasonably common defaults
	tex.msQual = 0;
	tex.msSamp = 1;
	tex.width = tex.height = tex.depth = tex.arraysize = 1;
	tex.cubemap = false;

	switch(res.curType)
	{
		case eGL_TEXTURE_1D:
		case eGL_TEXTURE_BUFFER:
			tex.dimension = 1;
			tex.width = (uint32_t)width;
			break;
		case eGL_TEXTURE_1D_ARRAY:
			tex.dimension = 1;
			tex.width = (uint32_t)width;
			tex.arraysize = depth;
			break;
		case eGL_TEXTURE_2D:
		case eGL_TEXTURE_RECTANGLE:
		case eGL_TEXTURE_2D_MULTISAMPLE:
		case eGL_TEXTURE_CUBE_MAP:
			tex.dimension = 2;
			tex.width = (uint32_t)width;
			tex.height = (uint32_t)height;
			tex.cubemap = (res.curType == eGL_TEXTURE_CUBE_MAP);
			tex.msSamp = (res.curType == eGL_TEXTURE_2D_MULTISAMPLE ? samples : 1);
			break;
		case eGL_TEXTURE_2D_ARRAY:
		case eGL_TEXTURE_2D_MULTISAMPLE_ARRAY:
		case eGL_TEXTURE_CUBE_MAP_ARRAY:
			tex.dimension = 2;
			tex.width = (uint32_t)width;
			tex.height = (uint32_t)height;
			tex.arraysize = depth;
			tex.cubemap = (res.curType == eGL_TEXTURE_CUBE_MAP_ARRAY);
			tex.msSamp = (res.curType == eGL_TEXTURE_2D_MULTISAMPLE_ARRAY ? samples : 1);
			break;
		case eGL_TEXTURE_3D:
			tex.dimension = 3;
			tex.width = (uint32_t)width;
			tex.height = (uint32_t)height;
			tex.depth = (uint32_t)depth;
			break;

		default:
			tex.dimension = 2;
			RDCERR("Unexpected texture enum %hs", ToStr::Get(res.curType).c_str());
	}
	
	GLint immut = 0;
	gl.glGetTexParameteriv(res.curType, eGL_TEXTURE_IMMUTABLE_FORMAT, &immut);
	
	if(immut)
	{
		gl.glGetTexParameteriv(res.curType, eGL_TEXTURE_IMMUTABLE_LEVELS, &immut);
		tex.mips = (uint32_t)immut;
	}
	else
	{
		// assuming complete texture
		GLint mips = 1;
		gl.glGetTexParameteriv(res.curType, eGL_TEXTURE_MAX_LEVEL, &mips);
		tex.mips = (uint32_t)mips;
	}

	tex.numSubresources = tex.mips*tex.arraysize;
	
	// surely this will be the same for each level... right? that would be insane if it wasn't
	GLint fmt = 0;
	gl.glGetTexLevelParameteriv(res.curType, 0, eGL_TEXTURE_INTERNAL_FORMAT, &fmt);

	tex.format = MakeResourceFormat(gl, res.curType, (GLenum)fmt);
	
	string str = "";
	char name[128] = {0};
	gl.glGetObjectLabel(eGL_TEXTURE, res.resource.name, 127, NULL, name);
	str = name;
	tex.customName = true;

	if(str == "")
	{
		tex.customName = false;
		str = StringFormat::Fmt("Texture%dD %llu", tex.dimension, tex.ID);
	}

	tex.name = widen(str);

	tex.creationFlags = eTextureCreate_SRV;
	if(tex.format.compType == eCompType_Depth)
		tex.creationFlags |= eTextureCreate_DSV;
	GLNOTIMP("creationFlags are not calculated yet");

	tex.byteSize = 0;
	GLNOTIMP("Not calculating bytesize");

	return tex;
}
Ejemplo n.º 6
0
vector<EventUsage> GLReplay::GetUsage(ResourceId id)
{
	GLNOTIMP("GetUsage");
	return vector<EventUsage>();
}
Ejemplo n.º 7
0
void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
{
	GLNOTIMP("GLReplay::InitPostVSBuffers");
}