예제 #1
0
bool WrappedOpenGL::Serialise_glCreateShaderProgramv(GLuint program, GLenum type, GLsizei count,
                                                     const GLchar *const *strings)
{
  SERIALISE_ELEMENT(GLenum, Type, type);
  SERIALISE_ELEMENT(int32_t, Count, count);
  SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ProgramRes(GetCtx(), program)));

  vector<string> src;

  for(int32_t i = 0; i < Count; i++)
  {
    string s;
    if(m_State >= WRITING)
      s = strings[i];
    m_pSerialiser->SerialiseString("Source", s);
    if(m_State < WRITING)
      src.push_back(s);
  }

  if(m_State == READING)
  {
    char **sources = new char *[Count];

    for(int32_t i = 0; i < Count; i++)
      sources[i] = &src[i][0];

    GLuint real = m_Real.glCreateShaderProgramv(Type, Count, sources);
    // we want a separate program that we can mess about with for making overlays
    // and relink without having to worry about restoring the 'real' program state.
    GLuint sepprog = MakeSeparableShaderProgram(*this, Type, src, NULL);

    delete[] sources;

    GLResource res = ProgramRes(GetCtx(), real);

    ResourceId liveId = m_ResourceManager->RegisterResource(res);

    auto &progDetails = m_Programs[liveId];

    progDetails.linked = true;
    progDetails.shaders.push_back(liveId);
    progDetails.stageShaders[ShaderIdx(Type)] = liveId;

    auto &shadDetails = m_Shaders[liveId];

    shadDetails.type = Type;
    shadDetails.sources.swap(src);
    shadDetails.prog = sepprog;

    shadDetails.Compile(*this);

    GetResourceManager()->AddLiveResource(id, res);
  }

  return true;
}
예제 #2
0
GLuint WrappedOpenGL::glCreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const *strings)
{
  GLuint real = m_Real.glCreateShaderProgramv(type, count, strings);

  GLResource res = ProgramRes(GetCtx(), real);
  ResourceId id = GetResourceManager()->RegisterResource(res);

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

    {
      SCOPED_SERIALISE_CONTEXT(CREATE_SHADERPROGRAM);
      Serialise_glCreateShaderProgramv(real, type, count, strings);

      chunk = scope.Get();
    }

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

    // we always want to mark programs as dirty so we can serialise their
    // locations as initial state (and form a remapping table)
    GetResourceManager()->MarkDirtyResource(id);

    record->AddChunk(chunk);
  }
  else
  {
    GetResourceManager()->AddLiveResource(id, res);

    vector<string> src;
    for(GLsizei i = 0; i < count; i++)
      src.push_back(strings[i]);

    GLuint sepprog = MakeSeparableShaderProgram(*this, type, src, NULL);

    auto &progDetails = m_Programs[id];

    progDetails.linked = true;
    progDetails.shaders.push_back(id);
    progDetails.stageShaders[ShaderIdx(type)] = id;

    auto &shadDetails = m_Shaders[id];

    shadDetails.type = type;
    shadDetails.sources.swap(src);
    shadDetails.prog = sepprog;

    shadDetails.Compile(*this);
  }

  return real;
}
예제 #3
0
bool WrappedOpenGL::Serialise_glCompileShader(GLuint shader)
{
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader)));
	
	if(m_State == READING)
	{
		ResourceId liveId = GetResourceManager()->GetLiveID(id);

		auto &shadDetails = m_Shaders[liveId];

		bool pointSizeUsed = false, clipDistanceUsed = false;
		if(shadDetails.type == eGL_VERTEX_SHADER) CheckVertexOutputUses(shadDetails.sources, pointSizeUsed, clipDistanceUsed);

		GLuint sepProg = MakeSeparableShaderProgram(m_Real, shadDetails.type, shadDetails.sources, NULL);

		if(sepProg == 0)
		{
			RDCERR("Couldn't make separable program for shader via patching - functionality will be broken.");
		}
		else
		{
			shadDetails.prog = sepProg;
			MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection, pointSizeUsed, clipDistanceUsed);

			string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.sources, shadDetails.spirv);
			if(!shadDetails.spirv.empty())
				DisassembleSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.spirv, s);

			shadDetails.reflection.Disassembly = s;

			create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size());
			for(size_t i=0; i < shadDetails.sources.size(); i++)
			{
				shadDetails.reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i);
				shadDetails.reflection.DebugInfo.files[i].second = shadDetails.sources[i];
			}
		}

		m_Real.glCompileShader(GetResourceManager()->GetLiveResource(id).name);
	}

	return true;
}
예제 #4
0
void WrappedOpenGL::ShaderData::Compile(WrappedOpenGL &gl)
{
  bool pointSizeUsed = false, clipDistanceUsed = false;
  if(type == eGL_VERTEX_SHADER)
    CheckVertexOutputUses(sources, pointSizeUsed, clipDistanceUsed);

  GLuint sepProg = prog;

  if(sepProg == 0)
    sepProg = MakeSeparableShaderProgram(gl, type, sources, NULL);

  if(sepProg == 0)
  {
    RDCERR(
        "Couldn't make separable program for shader via patching - functionality will be broken.");
  }
  else
  {
    prog = sepProg;
    MakeShaderReflection(gl.GetHookset(), type, sepProg, reflection, pointSizeUsed, clipDistanceUsed);

    vector<uint32_t> spirvwords;

    string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(type)), sources, spirvwords);
    if(!spirvwords.empty())
      ParseSPIRV(&spirvwords.front(), spirvwords.size(), spirv);

    // for classic GL, entry point is always main
    reflection.Disassembly = spirv.Disassemble("main");

    create_array_uninit(reflection.DebugInfo.files, sources.size());
    for(size_t i = 0; i < sources.size(); i++)
    {
      reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i);
      reflection.DebugInfo.files[i].second = sources[i];
    }
  }
}
예제 #5
0
bool WrappedOpenGL::Serialise_glCreateShaderProgramv(GLuint program, GLenum type, GLsizei count, const GLchar *const*strings)
{
	SERIALISE_ELEMENT(GLenum, Type, type);
	SERIALISE_ELEMENT(int32_t, Count, count);
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ProgramRes(GetCtx(), program)));

	vector<string> src;

	for(int32_t i=0; i < Count; i++)
	{
		string s;
		if(m_State >= WRITING) s = strings[i];
		m_pSerialiser->SerialiseString("Source", s);
		if(m_State < WRITING) src.push_back(s);
	}

	if(m_State == READING)
	{
		char **sources = new char*[Count];
		
		for(int32_t i=0; i < Count; i++)
			sources[i] = &src[i][0];

		GLuint real = m_Real.glCreateShaderProgramv(Type, Count, sources);
		// we want a separate program that we can mess about with for making overlays
		// and relink without having to worry about restoring the 'real' program state.
		GLuint sepprog = MakeSeparableShaderProgram(m_Real, Type, src, NULL);

		delete[] sources;
		
		GLResource res = ProgramRes(GetCtx(), real);

		ResourceId liveId = m_ResourceManager->RegisterResource(res);
	
		auto &progDetails = m_Programs[liveId];
	
		progDetails.linked = true;
		progDetails.shaders.push_back(liveId);
		progDetails.stageShaders[ShaderIdx(Type)] = liveId;

		auto &shadDetails = m_Shaders[liveId];

		bool pointSizeUsed = false, clipDistanceUsed = false;
		if(Type == eGL_VERTEX_SHADER) CheckVertexOutputUses(src, pointSizeUsed, clipDistanceUsed);

		shadDetails.type = Type;
		shadDetails.sources.swap(src);
		shadDetails.prog = sepprog;
		MakeShaderReflection(m_Real, Type, real, shadDetails.reflection, pointSizeUsed, clipDistanceUsed);

		string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.sources, shadDetails.spirv);
		if(!shadDetails.spirv.empty())
			DisassembleSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.spirv, s);

		shadDetails.reflection.Disassembly = s;

		create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size());
		for(size_t i=0; i < shadDetails.sources.size(); i++)
		{
			shadDetails.reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i);
			shadDetails.reflection.DebugInfo.files[i].second = shadDetails.sources[i];
		}

		GetResourceManager()->AddLiveResource(id, res);
	}

	return true;
}
예제 #6
0
bool WrappedOpenGL::Serialise_glCompileShaderIncludeARB(GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length)
{
	SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader)));
	SERIALISE_ELEMENT(int32_t, Count, count);

	vector<string> paths;

	for(int32_t i=0; i < Count; i++)
	{
		string s;
		if(path && path[i])
			s = length > 0 ? string(path[i], path[i] + length[i]) : string(path[i]);
		
		m_pSerialiser->SerialiseString("path", s);

		if(m_State == READING)
			paths.push_back(s);
	}
	
	if(m_State == READING)
	{
		size_t numStrings = paths.size();

		const char **pathstrings = new const char*[numStrings];
		for(size_t i=0; i < numStrings; i++)
			pathstrings[i] = paths[i].c_str();

		ResourceId liveId = GetResourceManager()->GetLiveID(id);

		auto &shadDetails = m_Shaders[liveId];
		
		shadDetails.includepaths.clear();
		shadDetails.includepaths.reserve(Count);

		for(int32_t i=0; i < Count; i++)
			shadDetails.includepaths.push_back(pathstrings[i]);

		bool pointSizeUsed = false, clipDistanceUsed = false;
		if(shadDetails.type == eGL_VERTEX_SHADER) CheckVertexOutputUses(shadDetails.sources, pointSizeUsed, clipDistanceUsed);

		GLuint sepProg = MakeSeparableShaderProgram(m_Real, shadDetails.type, shadDetails.sources, &paths);

		if(sepProg == 0)
		{
			RDCERR("Couldn't make separable program for shader via patching - functionality will be broken.");
		}
		else
		{
			shadDetails.prog = sepProg;
			MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection, pointSizeUsed, clipDistanceUsed);
			
			string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.sources, shadDetails.spirv);
			if(!shadDetails.spirv.empty())
				DisassembleSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.spirv, s);

			shadDetails.reflection.Disassembly = s;

			create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size());
			for(size_t i=0; i < shadDetails.sources.size(); i++)
			{
				shadDetails.reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i);
				shadDetails.reflection.DebugInfo.files[i].second = shadDetails.sources[i];
			}
		}

		m_Real.glCompileShaderIncludeARB(GetResourceManager()->GetLiveResource(id).name, Count, pathstrings, NULL);
		
		delete[] pathstrings;
	}

	return true;
}