예제 #1
0
	void OGL4ShaderProgram::CollectUniformBlocks()
	{
		GLint count = 0;
		glGetProgramiv(m_program, GL_ACTIVE_UNIFORM_BLOCKS, &count);

		for(int i = 0; i < count; ++i)
		{
			char szName[1024];
			glGetActiveUniformBlockName(m_program, i, 1024, 0, szName);

			GLint bytes = 0;
			glGetActiveUniformBlockiv(m_program, i, GL_UNIFORM_BLOCK_DATA_SIZE, &bytes);
			
			OGL4BufferPtr pBuffer = std::make_shared<OGL4Buffer>();
			if(pBuffer->Create(BT_CONSTANT_BUFFER, bytes, nullptr, true) == false)
			{
				pBuffer->Release();
				pBuffer.reset();
				continue;
			}
			UniformBlock block;
			block.index = i;
			block.name = szName;
			block.pBuffer = pBuffer;

			m_uniformBlocks.push_back(block);
		}
	}
예제 #2
0
static void CopyShaderState_UniformBlocks(GLuint newProgID, GLuint oldProgID)
{
	if (!GLEW_ARB_uniform_buffer_object)
		return;

	GLsizei numUniformBlocks, maxNameLength;
	glGetProgramiv(oldProgID, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
	glGetProgramiv(oldProgID, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxNameLength);

	if (maxNameLength <= 0)
		return;

	std::string name(maxNameLength, 0);
	for (int i = 0; i < numUniformBlocks; ++i) {
		GLsizei nameLength = 0;
		glGetActiveUniformBlockName(oldProgID, i, maxNameLength, &nameLength, &name[0]);
		name[maxNameLength - 1] = 0;

		if (nameLength == 0)
			continue;

		GLuint oldLoc = glGetUniformBlockIndex(oldProgID, &name[0]);
		GLuint newLoc = glGetUniformBlockIndex(newProgID, &name[0]);

		if (oldLoc == GL_INVALID_INDEX || newLoc == GL_INVALID_INDEX)
			continue;

		GLint value;
		glGetActiveUniformBlockiv(oldProgID, oldLoc, GL_UNIFORM_BLOCK_BINDING, &value);
		glUniformBlockBinding(newProgID, newLoc, value);
	}
}
예제 #3
0
void RendererBasePimpl::InitDomainUniformBufferDecl(ShaderProgram * resource, unsigned int domain, GLuint program)
{
	if (glGetActiveUniformBlockiv)
	{
		char uniformblock_name[1000];
		GLint name_length;
		GLint block_binding;
		GLint block_data_size;
		GLint block_active_uniforms;
		GLint uniformblock_count;
		GLint referenced_by_vertex_shader;
		GLint referenced_by_geometry_shader;
		GLint referenced_by_fragment_shader;


		glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &uniformblock_count);
	
		for (int i = 0; i < uniformblock_count; ++i)
		{
			glGetActiveUniformBlockName(program, i, 1000, &name_length, uniformblock_name);

			GLint params;
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_BINDING, &block_binding);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_DATA_SIZE, &block_data_size);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &params);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &block_active_uniforms);
			std::vector<GLuint> uniform_indices(block_active_uniforms, 0);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, reinterpret_cast<GLint*>(&uniform_indices[0]));
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, &referenced_by_vertex_shader);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, &referenced_by_fragment_shader);

			std::vector<GLuint> uniform_offsets(block_active_uniforms, 0);
			glGetActiveUniformsiv(program, block_active_uniforms, &uniform_indices[0], GL_UNIFORM_OFFSET, reinterpret_cast<GLint*>(&uniform_offsets[0]));
			std::vector<GLuint> uniform_arraystrides(block_active_uniforms, 0);
			glGetActiveUniformsiv(program, block_active_uniforms, &uniform_indices[0], GL_UNIFORM_ARRAY_STRIDE, reinterpret_cast<GLint*>(&uniform_arraystrides[0]));
			std::vector<GLuint> uniform_matrixstrides(block_active_uniforms, 0);
			glGetActiveUniformsiv(program, block_active_uniforms, &uniform_indices[0], GL_UNIFORM_MATRIX_STRIDE, reinterpret_cast<GLint*>(&uniform_matrixstrides[0]));
			std::vector<GLuint> uniform_rowmajor(block_active_uniforms, 0);
			glGetActiveUniformsiv(program, block_active_uniforms, &uniform_indices[0], GL_UNIFORM_IS_ROW_MAJOR, reinterpret_cast<GLint*>(&uniform_rowmajor[0]));

			

			std::cout << "UniformBlock: " << uniformblock_name << "[" << i << "]" << std::endl;
			std::cout << "		Size: " << block_data_size << std::endl;
			std::cout << "		UniformCount: " << block_active_uniforms << std::endl;
			for (unsigned int p = 0; p < uniform_indices.size(); ++p)
			{
				std::cout << "	Param: " << uniform_indices[p] << std::endl;
				std::cout << "		Offset: " << uniform_offsets[p] << std::endl;
				std::cout << "		ArrayStrides: " << uniform_arraystrides[p] << std::endl;
				std::cout << "		MatrixStrides: " << uniform_matrixstrides[p] << std::endl;
				std::cout << "		RowMajor: " << uniform_rowmajor[p] << std::endl;
			}
			//std::cout << "	Location: " << glGetUniformLocation(pimpl->combined, uniformblock_name) << std::endl;
		}
	}
}
bool effect::create()
{
	_program = createProgram(&_shaders[0], _shaders.size());
	if (!_program)
		return false;

	std::vector<std::string> uniformNames;
	GLint numUniforms, maxLength;
	glGetProgramiv(_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
	glGetProgramiv(_program, GL_ACTIVE_UNIFORMS, &numUniforms);
	char* buf = new char[maxLength];
	for (int i = 0; i < numUniforms; ++i)
	{
		GLsizei size;
		glGetActiveUniformName(_program, i, maxLength, &size, buf);
		std::string name(buf);
		if (uniformNames.size() > 0 && uniformNames[i - 1] == name)
			break;
		else
			uniformNames.push_back(name);
	}
	delete[] buf;

	for (int i = 0; i < uniformNames.size(); ++i)
	{
		GLint uniformLocation = glGetUniformLocation(_program, uniformNames[i].c_str());
		if (uniformLocation != -1) _uniforms[uniformNames[i]] = uniformLocation;
	}

	std::vector<std::string> uniformBlockNames;
	glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxLength);
	glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniforms);
	buf = new char[maxLength];
	for (int i = 0; i < numUniforms; ++i)
	{
		GLsizei size;
		glGetActiveUniformBlockName(_program, i, maxLength, &size, buf);
		std::string name(buf);
		if (uniformBlockNames.size() > 0 && uniformBlockNames[i - 1] == name)
			break;
		else
			uniformBlockNames.push_back(name);
	}
	delete[] buf;

	for (int i = 0; i < uniformBlockNames.size(); ++i)
	{
		GLuint blockIndex = glGetUniformBlockIndex(_program, uniformBlockNames[i].c_str());
		glUniformBlockBinding(_program, blockIndex, i);
		_blockUniforms[uniformBlockNames[i]] = i;
	}

	return true;
}
예제 #5
0
std::string UniformBlock::getName() const
{
    if (m_identity.isName())
        return m_identity.name();

    GLint length = getActive(GL_UNIFORM_BLOCK_NAME_LENGTH);
    std::vector<char> name(length);

    glGetActiveUniformBlockName(m_program->id(), blockIndex(), length, nullptr, name.data());

    return std::string(name.data(), length);
}
예제 #6
0
파일: Program.cpp 프로젝트: dcbishop/dglw
UniformBlockList Program::getActiveUniformBlocks() const {
   UniformBlockList ul;

   // Get the number of active attributes
   GLint num_uniform_blocks;
   getProgram(Program::ActiveUniformBlocks, &num_uniform_blocks); // GL: 3.1

   // The the maximum size of the attribe name
   GLsizei max_name_length;
   getProgram(Program::ActiveUniformBlockMaxNameLength, &max_name_length);
   DEBUG_M("Num unifrom blocks %d", num_uniform_blocks);
   for(int ubo_index = 0; ubo_index < num_uniform_blocks; ubo_index++) {
      UniformBlockInfo ubi;

      getActiveUniformBlock(
         ubo_index,
         Program::UniformBlockActiveUniforms,
         &ubi.num_active_uniforms);

      GLsizei name_length;
      getActiveUniformBlock(
         ubo_index,
         Program::UniformBlockNameLength,
         &name_length);

      GLsizei written_name_length;
      std::vector<GLchar> block_name(name_length);
      glGetActiveUniformBlockName(
         getProgramId(),
         ubo_index,
         block_name.size(),
         &written_name_length,
         &block_name[0]
      );

      ubi.name = std::string(&block_name[0], written_name_length);

      getActiveUniformBlock(
         ubo_index,
         Program::UniformBlockBinding,
         &ubi.binding);

      std::vector<GLint> active_uniforms(ubi.num_active_uniforms);
      getActiveUniformBlock(
         ubo_index,
         Program::UniformBlockActiveUniformIndices,
         &active_uniforms[0]);

      ul.push_back(ubi);
   }
   return ul;
}
/* void glGetActiveUniformBlockName ( GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName ) */
static jstring
android_glGetActiveUniformBlockName_II
    (JNIEnv *_env, jobject _this, jint program, jint uniformBlockIndex) {
    GLint len = 0;
    glGetActiveUniformBlockiv((GLuint)program, (GLuint)uniformBlockIndex,
            GL_UNIFORM_BLOCK_NAME_LENGTH, &len);
    GLchar* name = (GLchar*)malloc(len);
    glGetActiveUniformBlockName((GLuint)program, (GLuint)uniformBlockIndex,
        len, NULL, name);
    jstring result = _env->NewStringUTF(name);
    free(name);
    return result;
}
예제 #8
0
파일: glshader.cpp 프로젝트: Toeplitz/poll
std::vector<std::string> GLshader::block_names_get()
{
  GLint numBlocks;
  GLint nameLen;

  std::vector <std::string> name_list;

  glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numBlocks);
  name_list.reserve(numBlocks);

  for (int blockIx = 0; blockIx < numBlocks; blockIx++) {
    glGetActiveUniformBlockiv(program, blockIx, GL_UNIFORM_BLOCK_NAME_LENGTH, &nameLen);
    std::vector <GLchar> name;
    name.resize(nameLen);
    glGetActiveUniformBlockName(program, blockIx, nameLen, NULL, &name[0]);
    name_list.push_back(std::string());
    name_list.back().assign(name.begin(), name.end() - 1);       //Remove the null terminator.
  }

  return name_list;
}
/* void glGetActiveUniformBlockName ( GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName ) */
static void
android_glGetActiveUniformBlockName_IILjava_nio_Buffer_2Ljava_nio_Buffer_2
    (JNIEnv* _env, jobject _this, jint program, jint uniformBlockIndex, jobject length_buf, jobject uniformBlockName_buf) {
    jint _exception = 0;
    const char* _exceptionType;
    const char* _exceptionMessage;
    jarray _lengthArray = (jarray)0;
    jint _lengthBufferOffset = (jint)0;
    GLsizei* _length = (GLsizei*)0;
    jint _lengthRemaining;
    jarray _nameArray = (jarray)0;
    jint _nameBufferOffset = (jint)0;
    GLchar* _name = (GLchar*)0;
    jint _nameRemaining;

    _length = (GLsizei*)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
    if (_length == NULL) {
        GLsizei* _lengthBase = (GLsizei*)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean*)0);
        _length = (GLsizei*)(_lengthBase + _lengthBufferOffset);
    }

    _name = (GLchar*)getPointer(_env, uniformBlockName_buf, &_nameArray, &_nameRemaining, &_nameBufferOffset);
    if (_name == NULL) {
        GLchar* _nameBase = (GLchar*)_env->GetPrimitiveArrayCritical(_nameArray, (jboolean*)0);
        _name = (GLchar*)(_nameBase + _nameBufferOffset);
    }

    glGetActiveUniformBlockName(
        (GLuint)program,
        (GLuint)uniformBlockIndex,
        (GLsizei)_nameRemaining,
        _length, _name
    );
    if (_nameArray) {
        releasePointer(_env, _nameArray, _name, JNI_TRUE);
    }
    if (_lengthArray) {
        releasePointer(_env, _lengthArray, _length, JNI_TRUE);
    }
}
예제 #10
0
파일: glshader.cpp 프로젝트: Toeplitz/poll
void GLshader::print_block_names()
{
  GLint numBlocks;
  GLint nameLen;
  GLint block_binding;
  GLint block_size;
  GLint ref_vertex;
  GLint ref_fragment;

  std::vector <std::string> name_list;

  glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numBlocks);
  name_list.reserve(numBlocks);

  std::cout << "Found " << numBlocks << " block(s) in shader" << std::endl;

  for (int blockIx = 0; blockIx < numBlocks; blockIx++) {
    glGetActiveUniformBlockiv(program, blockIx, GL_UNIFORM_BLOCK_NAME_LENGTH, &nameLen);
    std::vector <GLchar> name;
    name.resize(nameLen);
    glGetActiveUniformBlockName(program, blockIx, nameLen, NULL, &name[0]);
    name_list.push_back(std::string());
    name_list.back().assign(name.begin(), name.end() - 1);       //Remove the null terminator.
    glGetActiveUniformBlockiv(program, blockIx, GL_UNIFORM_BLOCK_BINDING, &block_binding);
    glGetActiveUniformBlockiv(program, blockIx, GL_UNIFORM_BLOCK_DATA_SIZE, &block_size);
    glGetActiveUniformBlockiv(program, blockIx, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, &ref_vertex);
    glGetActiveUniformBlockiv(program, blockIx, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, &ref_fragment);

    std::cout << "Name: " << name.data() << " block binding: " << block_binding << " block size: " << block_size << std::endl;
    std::cout << "ref vertex: " << ref_vertex << ", ref fragment: " << ref_fragment << std::endl;
  }

  for (unsigned int il = 0; il < name_list.size(); il++) {
    std::cout << "Block name: " << name_list[il] << ", index: " <<
      get_block_index(name_list[il]) << std::endl;
  }
}
예제 #11
0
bool ShaderProgram::Link()
{
    Release();

    if (!vertexShader_ || !pixelShader_ || !vertexShader_->GetGPUObjectName() || !pixelShader_->GetGPUObjectName())
        return false;

    object_.name_ = glCreateProgram();
    if (!object_.name_)
    {
        linkerOutput_ = "Could not create shader program";
        return false;
    }

    glAttachShader(object_.name_, vertexShader_->GetGPUObjectName());
    glAttachShader(object_.name_, pixelShader_->GetGPUObjectName());
    glLinkProgram(object_.name_);

    int linked, length;
    glGetProgramiv(object_.name_, GL_LINK_STATUS, &linked);
    if (!linked)
    {
        glGetProgramiv(object_.name_, GL_INFO_LOG_LENGTH, &length);
        linkerOutput_.Resize((unsigned)length);
        int outLength;
        glGetProgramInfoLog(object_.name_, length, &outLength, &linkerOutput_[0]);
        glDeleteProgram(object_.name_);
        object_.name_ = 0;
    }
    else
        linkerOutput_.Clear();

    if (!object_.name_)
        return false;

    const int MAX_NAME_LENGTH = 256;
    char nameBuffer[MAX_NAME_LENGTH];
    int attributeCount, uniformCount, elementCount, nameLength;
    GLenum type;

    glUseProgram(object_.name_);

    // Check for vertex attributes
    glGetProgramiv(object_.name_, GL_ACTIVE_ATTRIBUTES, &attributeCount);
    for (int i = 0; i < attributeCount; ++i)
    {
        glGetActiveAttrib(object_.name_, i, (GLsizei)MAX_NAME_LENGTH, &nameLength, &elementCount, &type, nameBuffer);

        String name = String(nameBuffer, nameLength);
        VertexElementSemantic semantic = MAX_VERTEX_ELEMENT_SEMANTICS;
        unsigned char semanticIndex = 0;

        // Go in reverse order so that "binormal" is detected before "normal"
        for (unsigned j = MAX_VERTEX_ELEMENT_SEMANTICS - 1; j < MAX_VERTEX_ELEMENT_SEMANTICS; --j)
        {
            if (name.Contains(ShaderVariation::elementSemanticNames[j], false))
            {
                semantic = (VertexElementSemantic)j;
                unsigned index = NumberPostfix(name);
                if (index != M_MAX_UNSIGNED)
                    semanticIndex = (unsigned char)index;
                break;
            }
        }

        if (semantic == MAX_VERTEX_ELEMENT_SEMANTICS)
        {
            URHO3D_LOGWARNING("Found vertex attribute " + name + " with no known semantic in shader program " +
                vertexShader_->GetFullName() + " " + pixelShader_->GetFullName());
            continue;
        }

        int location = glGetAttribLocation(object_.name_, name.CString());
        vertexAttributes_[MakePair((unsigned char)semantic, semanticIndex)] = location;
        usedVertexAttributes_ |= (1u << location);
    }

    // Check for constant buffers
#ifndef GL_ES_VERSION_2_0
    HashMap<unsigned, unsigned> blockToBinding;

    if (Graphics::GetGL3Support())
    {
        int numUniformBlocks = 0;

        glGetProgramiv(object_.name_, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
        for (int i = 0; i < numUniformBlocks; ++i)
        {
            glGetActiveUniformBlockName(object_.name_, (GLuint)i, MAX_NAME_LENGTH, &nameLength, nameBuffer);

            String name(nameBuffer, (unsigned)nameLength);

            unsigned blockIndex = glGetUniformBlockIndex(object_.name_, name.CString());
            unsigned group = M_MAX_UNSIGNED;

            // Try to recognize the use of the buffer from its name
            for (unsigned j = 0; j < MAX_SHADER_PARAMETER_GROUPS; ++j)
            {
                if (name.Contains(shaderParameterGroups[j], false))
                {
                    group = j;
                    break;
                }
            }

            // If name is not recognized, search for a digit in the name and use that as the group index
            if (group == M_MAX_UNSIGNED)
                group = NumberPostfix(name);

            if (group >= MAX_SHADER_PARAMETER_GROUPS)
            {
                URHO3D_LOGWARNING("Skipping unrecognized uniform block " + name + " in shader program " + vertexShader_->GetFullName() +
                           " " + pixelShader_->GetFullName());
                continue;
            }

            // Find total constant buffer data size
            int dataSize;
            glGetActiveUniformBlockiv(object_.name_, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &dataSize);
            if (!dataSize)
                continue;

            unsigned bindingIndex = group;
            // Vertex shader constant buffer bindings occupy slots starting from zero to maximum supported, pixel shader bindings
            // from that point onward
            ShaderType shaderType = VS;
            if (name.Contains("PS", false))
            {
                bindingIndex += MAX_SHADER_PARAMETER_GROUPS;
                shaderType = PS;
            }

            glUniformBlockBinding(object_.name_, blockIndex, bindingIndex);
            blockToBinding[blockIndex] = bindingIndex;

            constantBuffers_[bindingIndex] = graphics_->GetOrCreateConstantBuffer(shaderType, bindingIndex, (unsigned)dataSize);
        }
    }
#endif

    // Check for shader parameters and texture units
    glGetProgramiv(object_.name_, GL_ACTIVE_UNIFORMS, &uniformCount);
    for (int i = 0; i < uniformCount; ++i)
    {
        glGetActiveUniform(object_.name_, (GLuint)i, MAX_NAME_LENGTH, nullptr, &elementCount, &type, nameBuffer);
        int location = glGetUniformLocation(object_.name_, nameBuffer);

        // Check for array index included in the name and strip it
        String name(nameBuffer);
        unsigned index = name.Find('[');
        if (index != String::NPOS)
        {
            // If not the first index, skip
            if (name.Find("[0]", index) == String::NPOS)
                continue;

            name = name.Substring(0, index);
        }

        if (name[0] == 'c')
        {
            // Store constant uniform
            String paramName = name.Substring(1);
            ShaderParameter parameter{paramName, type, location};
            bool store = location >= 0;

#ifndef GL_ES_VERSION_2_0
            // If running OpenGL 3, the uniform may be inside a constant buffer
            if (parameter.location_ < 0 && Graphics::GetGL3Support())
            {
                int blockIndex, blockOffset;
                glGetActiveUniformsiv(object_.name_, 1, (const GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
                glGetActiveUniformsiv(object_.name_, 1, (const GLuint*)&i, GL_UNIFORM_OFFSET, &blockOffset);
                if (blockIndex >= 0)
                {
                    parameter.offset_ = blockOffset;
                    parameter.bufferPtr_ = constantBuffers_[blockToBinding[blockIndex]];
                    store = true;
                }
            }
#endif

            if (store)
                shaderParameters_[StringHash(paramName)] = parameter;
        }
        else if (location >= 0 && name[0] == 's')
        {
            // Set the samplers here so that they do not have to be set later
            unsigned unit = graphics_->GetTextureUnit(name.Substring(1));
            if (unit >= MAX_TEXTURE_UNITS)
                unit = NumberPostfix(name);

            if (unit < MAX_TEXTURE_UNITS)
            {
                useTextureUnits_[unit] = true;
                glUniform1iv(location, 1, reinterpret_cast<int*>(&unit));
            }
        }
    }

    // Rehash the parameter & vertex attributes maps to ensure minimal load factor
    vertexAttributes_.Rehash(NextPowerOfTwo(vertexAttributes_.Size()));
    shaderParameters_.Rehash(NextPowerOfTwo(shaderParameters_.Size()));

    return true;
}
/* void glGetActiveUniformBlockName ( GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName ) */
static void
android_glGetActiveUniformBlockName_III_3II_3BI
    (JNIEnv* _env, jobject _this, jint program, jint uniformBlockIndex, int bufSize, jintArray length_ref, jint lengthOffset, jbyteArray name_ref, jint nameOffset) {
    jint _exception = 0;
    const char* _exceptionType;
    const char* _exceptionMessage;
    GLsizei* _length_base = (GLsizei*)0;
    jint _lengthRemaining;
    GLsizei* _length = (GLsizei*)0;
    GLchar* _name_base = (GLchar*)0;
    jint _nameRemaining;
    GLchar* _name = (GLchar*)0;

    if (!length_ref) {
        _exception = 1;
        _exceptionType = "java/lang/IllegalArgumentException";
        _exceptionMessage = "length == null";
        goto exit;
    }
    if (lengthOffset < 0) {
        _exception = 1;
        _exceptionType = "java/lang/IllegalArgumentException";
        _exceptionMessage = "lengthOffset < 0";
        goto exit;
    }
    _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
    _length_base = (GLsizei*)_env->GetIntArrayElements(
            length_ref, (jboolean*)0);
    _length = _length_base + lengthOffset;

    if (!name_ref) {
        _exception = 1;
        _exceptionType = "java/lang/IllegalArgumentException";
        _exceptionMessage = "uniformBlockName == null";
        goto exit;
    }
    if (nameOffset < 0) {
        _exception = 1;
        _exceptionType = "java/lang/IllegalArgumentException";
        _exceptionMessage = "uniformBlockNameOffset < 0";
        goto exit;
    }
    _nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
    _name_base = (GLchar*)_env->GetByteArrayElements(
            name_ref, (jboolean*)0);
    _name = _name_base + nameOffset;

    glGetActiveUniformBlockName(
        (GLuint)program,
        (GLuint)uniformBlockIndex,
        (GLsizei)bufSize,
        (GLsizei*)_length,
        (GLchar*)_name
    );

exit:
    if (_name_base) {
        _env->ReleaseByteArrayElements(name_ref, (jbyte*)_name_base,
            _exception ? JNI_ABORT: 0);
    }
    if (_length_base) {
        _env->ReleaseIntArrayElements(length_ref, (jint*)_length_base,
            _exception ? JNI_ABORT: 0);
    }
    if (_exception) {
        jniThrowException(_env, _exceptionType, _exceptionMessage);
    }
}
	//---------------------------------------------------------------------
	void GLSLESProgramManagerCommon::extractUniforms(GLuint programObject, 
		const GpuConstantDefinitionMap* vertexConstantDefs, 
		const GpuConstantDefinitionMap* fragmentConstantDefs,
		GLUniformReferenceList& list, GLUniformBufferList& sharedList)
	{
		// Scan through the active uniforms and add them to the reference list
		GLint uniformCount = 0;
        GLint maxLength = 0;
		char* uniformName = NULL;
		#define uniformLength 200

		OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength));

        // If the max length of active uniforms is 0, then there are 0 active.
        // There won't be any to extract so we can return.
        if(maxLength == 0)
            return;

		uniformName = new char[maxLength + 1];
		GLUniformReference newGLUniformReference;

		// Get the number of active uniforms
		OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORMS, &uniformCount));

		// Loop over each of the active uniforms, and add them to the reference container
		// only do this for user defined uniforms, ignore built in gl state uniforms
		for (GLuint index = 0; index < (GLuint)uniformCount; index++)
		{
			GLint arraySize = 0;
			GLenum glType = GL_NONE;
			OGRE_CHECK_GL_ERROR(glGetActiveUniform(programObject, index, maxLength, NULL,
				&arraySize, &glType, uniformName));

			// Don't add built in uniforms
			newGLUniformReference.mLocation = glGetUniformLocation(programObject, uniformName);
			if (newGLUniformReference.mLocation >= 0)
			{
				// User defined uniform found, add it to the reference list
				String paramName = String( uniformName );

				// If the uniform name has a "[" in it then its an array element uniform.
				String::size_type arrayStart = paramName.find("[");
				if (arrayStart != String::npos)
				{
					// If not the first array element then skip it and continue to the next uniform
					if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0) continue;
					paramName = paramName.substr(0, arrayStart);
				}

				// Find out which params object this comes from
				bool foundSource = completeParamSource(paramName,
						vertexConstantDefs,	fragmentConstantDefs, newGLUniformReference);

				// Only add this parameter if we found the source
				if (foundSource)
				{
					assert(size_t (arraySize) == newGLUniformReference.mConstantDef->arraySize
							&& "GL doesn't agree with our array size!");
					list.push_back(newGLUniformReference);
				}

				// Don't bother adding individual array params, they will be
				// picked up in the 'parent' parameter can copied all at once
				// anyway, individual indexes are only needed for lookup from
				// user params
			} // end if
		} // end for
		
		if( uniformName != NULL ) 
		{
			delete[] uniformName;
		}

#if OGRE_NO_GLES3_SUPPORT == 0
        // Now deal with uniform blocks

        GLint blockCount = 0;

        OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_BLOCKS, &blockCount));

        for (int index = 0; index < blockCount; index++)
        {
            OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockName(programObject, index, uniformLength, NULL, uniformName));

            GpuSharedParametersPtr blockSharedParams = GpuProgramManager::getSingleton().getSharedParameters(uniformName);

            GLint blockSize, blockBinding;
            OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockiv(programObject, index, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize));
            OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockiv(programObject, index, GL_UNIFORM_BLOCK_BINDING, &blockBinding));
            HardwareUniformBufferSharedPtr newUniformBuffer = HardwareBufferManager::getSingleton().createUniformBuffer(blockSize, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, false, uniformName);

            GLES2HardwareUniformBuffer* hwGlBuffer = static_cast<GLES2HardwareUniformBuffer*>(newUniformBuffer.get());
            hwGlBuffer->setGLBufferBinding(blockBinding);
            sharedList.push_back(newUniformBuffer);
        }
#endif
    }
예제 #14
0
/**
 * Dump an uniform that belows to an uniform block.
 */
static void
dumpUniformBlock(StateWriter &writer,
                 GLint program,
                 GLint size,
                 GLenum type,
                 const GLchar *name,
                 GLuint index,
                 GLuint block_index)
{

    GLint offset = 0;
    GLint array_stride = 0;
    GLint matrix_stride = 0;
    GLint is_row_major = GL_FALSE;
    glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_OFFSET, &offset);
    glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
    glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
    glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_IS_ROW_MAJOR, &is_row_major);

    GLint slot = -1;
    glGetActiveUniformBlockiv(program, block_index, GL_UNIFORM_BLOCK_BINDING, &slot);
    if (slot == -1) {
        return;
    }

    AttribDesc desc(type, size, array_stride, matrix_stride, is_row_major);
    if (!desc) {
        return;
    }

    if (0) {
        GLint active_uniform_block_max_name_length = 0;
        glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &active_uniform_block_max_name_length);

        GLchar* block_name = new GLchar[active_uniform_block_max_name_length];

        GLint block_data_size = 0;
        glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_DATA_SIZE, &block_data_size);

        GLsizei length = 0;
        glGetActiveUniformBlockName(program, index, active_uniform_block_max_name_length, &length, block_name);

        std::cerr
            << "uniform `" << name << "`, size " << size << ", type " << enumToString(desc.type) << "\n"
            << "  block " << block_index << ", name `" << block_name << "`, size " << block_data_size << "; binding " << slot << "; \n"
            << "  offset " << offset << ", array stride " << array_stride << ", matrix stride " << matrix_stride << ", row_major " << is_row_major << "\n"
        ;

        delete [] block_name;
    }

    GLint ubo = 0;
    glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, slot, &ubo);
    GLint start = 0;
    glGetIntegeri_v(GL_UNIFORM_BUFFER_START, slot, &start);

    BufferMapping mapping;
    const GLbyte *raw_data = (const GLbyte *)mapping.map(GL_UNIFORM_BUFFER, ubo);
    if (raw_data) {
        std::string qualifiedName = resolveUniformName(name, size);

        dumpAttribArray(writer, qualifiedName, desc, raw_data + start + offset);
    }
}
예제 #15
0
bool ShaderProgram::Link()
{
    PROFILE(LinkShaderProgram);

    Release();

    if (!graphics || !graphics->IsInitialized())
    {
        LOGERROR("Can not link shader program without initialized Graphics subsystem");
        return false;
    }
    if (!vs || !ps)
    {
        LOGERROR("Shader(s) are null, can not link shader program");
        return false;
    }
    if (!vs->GLShader() || !ps->GLShader())
    {
        LOGERROR("Shaders have not been compiled, can not link shader program");
        return false;
    }

    const String& vsSourceCode = vs->Parent() ? vs->Parent()->SourceCode() : String::EMPTY;
    const String& psSourceCode = ps->Parent() ? ps->Parent()->SourceCode() : String::EMPTY;

    program = glCreateProgram();
    if (!program)
    {
        LOGERROR("Could not create shader program");
        return false;
    }

    glAttachShader(program, vs->GLShader());
    glAttachShader(program, ps->GLShader());
    glLinkProgram(program);

    int linked;
    glGetProgramiv(program, GL_LINK_STATUS, &linked);
    if (!linked)
    {
        int length, outLength;
        String errorString;

        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
        errorString.Resize(length);
        glGetProgramInfoLog(program, length, &outLength, &errorString[0]);
        glDeleteProgram(program);
        program = 0;

        LOGERRORF("Could not link shaders %s: %s", FullName().CString(), errorString.CString());
        return false;
    }

    LOGDEBUGF("Linked shaders %s", FullName().CString());

    glUseProgram(program);

    char nameBuffer[MAX_NAME_LENGTH];
    int numAttributes, numUniforms, numUniformBlocks, nameLength, numElements;
    GLenum type;

    attributes.Clear();

    glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &numAttributes);
    for (int i = 0; i < numAttributes; ++i)
    {
        glGetActiveAttrib(program, i, (GLsizei)MAX_NAME_LENGTH, &nameLength, &numElements, &type, nameBuffer);

        VertexAttribute newAttribute;
        newAttribute.name = String(nameBuffer, nameLength);
        newAttribute.semantic = SEM_POSITION;
        newAttribute.index = 0;

        for (size_t j = 0; elementSemanticNames[j]; ++j)
        {
            if (newAttribute.name.StartsWith(elementSemanticNames[j], false))
            {
                int index = NumberPostfix(newAttribute.name);
                if (index >= 0)
                    newAttribute.index = (unsigned char)index;
                break;
            }
            newAttribute.semantic = (ElementSemantic)(newAttribute.semantic + 1);
        }

        if (newAttribute.semantic == MAX_ELEMENT_SEMANTICS)
        {
            LOGWARNINGF("Found vertex attribute %s with no known semantic in shader program %s", newAttribute.name.CString(), FullName().CString());
            continue;
        }

        newAttribute.location = glGetAttribLocation(program, newAttribute.name.CString());
        attributes.Push(newAttribute);
    }

    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms);
    int numTextures = 0;
    for (int i = 0; i < numUniforms; ++i)
    {
        glGetActiveUniform(program, i, MAX_NAME_LENGTH, &nameLength, &numElements, &type, nameBuffer);

        String name(nameBuffer, nameLength);
        if (type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_SHADOW)
        {
            // Assign sampler uniforms to a texture unit according to the number appended to the sampler name
            int location = glGetUniformLocation(program, name.CString());
            int unit = NumberPostfix(name);
            // If no unit number specified, assign in appearance order starting from unit 0
            if (unit < 0)
                unit = numTextures;

            // Array samplers may have multiple elements, assign each sequentially
            if (numElements > 1)
            {
                Vector<int> units;
                for (int j = 0; j < numElements; ++j)
                    units.Push(unit++);
                glUniform1iv(location, numElements, &units[0]);
            }
            else
                glUniform1iv(location, 1, &unit);

            numTextures += numElements;
        }
    }

    glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
    for (int i = 0; i < numUniformBlocks; ++i)
    {
        glGetActiveUniformBlockName(program, i, (GLsizei)MAX_NAME_LENGTH, &nameLength, nameBuffer);

        // Determine whether uniform block belongs to vertex or pixel shader
        String name(nameBuffer, nameLength);
        bool foundVs = vsSourceCode.Contains(name);
        bool foundPs = psSourceCode.Contains(name);
        if (foundVs && foundPs)
        {
            LOGWARNINGF("Found uniform block %s in both vertex and pixel shader in shader program %s");
            continue;
        }

        // Vertex shader constant buffer bindings occupy slots starting from zero to maximum supported, pixel shader bindings
        // from that point onward
        unsigned blockIndex = glGetUniformBlockIndex(program, name.CString());

        int bindingIndex = NumberPostfix(name);
        // If no number postfix in the name, use the block index
        if (bindingIndex < 0)
            bindingIndex = blockIndex;
        if (foundPs)
            bindingIndex += (unsigned)graphics->NumVSConstantBuffers();

        glUniformBlockBinding(program, blockIndex, bindingIndex);
    }

    return true;
}
예제 #16
0
void
VSShaderLib::addBlocks() {

	int count, dataSize, actualLen, activeUnif, maxUniLength;
	int uniType, uniSize, uniOffset, uniMatStride, uniArrayStride, auxSize;
	char *name, *name2;

	glGetProgramiv(pProgram, GL_ACTIVE_UNIFORM_BLOCKS, &count);

	for (int i = 0; i < count; ++i) {
		// Get buffers name
		UniformBlock block;
		glGetActiveUniformBlockiv(pProgram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &actualLen);
		name = (char *)malloc(sizeof(char) * actualLen);
		glGetActiveUniformBlockName(pProgram, i, actualLen, NULL, name);

		bool newBlock=true;
		if (spBlocks.count(name)) {
			newBlock = false;
			block = spBlocks[name];
		}

		glGetActiveUniformBlockiv(pProgram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &dataSize);

		if (newBlock) {
			glGenBuffers(1, &block.buffer);
			glBindBuffer(GL_UNIFORM_BUFFER, block.buffer);
			glBufferData(GL_UNIFORM_BUFFER, dataSize, NULL, GL_DYNAMIC_DRAW);
			glUniformBlockBinding(pProgram, i, spBlockCount);
			glBindBufferRange(GL_UNIFORM_BUFFER, spBlockCount, block.buffer, 0, dataSize);
		}
		else {
			glBindBuffer(GL_UNIFORM_BUFFER, block.buffer);
			glUniformBlockBinding(pProgram, i, block.bindingIndex);
		}
		glGetActiveUniformBlockiv(pProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &activeUnif);

		unsigned int *indices;
		indices = (unsigned int *)malloc(sizeof(unsigned int) * activeUnif);
		glGetActiveUniformBlockiv(pProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, (int *)indices);
			
		glGetProgramiv(pProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniLength);
		name2 = (char *)malloc(sizeof(char) * maxUniLength);

		for (int k = 0; k < activeUnif; ++k) {
		
			myBlockUniform bUni;

			GLenum type;

			glGetActiveUniform(pProgram, indices[k], maxUniLength, &actualLen, &uniSize, &type, name2);

			glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_TYPE, &uniType);
			glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_SIZE, &uniSize);
			glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_OFFSET, &uniOffset);
			glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_MATRIX_STRIDE, &uniMatStride);
			glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_ARRAY_STRIDE, &uniArrayStride);
			
			if (uniArrayStride > 0)
				auxSize = uniArrayStride * uniSize;
				
			else if (uniMatStride > 0) {

				switch (uniType) {
				case GL_FLOAT_MAT2:
				case GL_FLOAT_MAT2x3:
				case GL_FLOAT_MAT2x4:
#ifndef __ANDROID_API__
				case GL_DOUBLE_MAT2:
				case GL_DOUBLE_MAT2x3:
				case GL_DOUBLE_MAT2x4:
					auxSize = 2 * uniMatStride;
					break;
#endif
				case GL_FLOAT_MAT3:
				case GL_FLOAT_MAT3x2:
				case GL_FLOAT_MAT3x4:
#ifndef __ANDROID_API__
				case GL_DOUBLE_MAT3:
				case GL_DOUBLE_MAT3x2:
				case GL_DOUBLE_MAT3x4:
#endif
					auxSize = 3 * uniMatStride;
					break;
				case GL_FLOAT_MAT4:
				case GL_FLOAT_MAT4x2:
				case GL_FLOAT_MAT4x3:
#ifndef __ANDROID_API__
				case GL_DOUBLE_MAT4:
				case GL_DOUBLE_MAT4x2:
				case GL_DOUBLE_MAT4x3:
#endif
					auxSize = 4 * uniMatStride;
					break;
				}
			}
			else
				auxSize = typeSize(uniType);

			bUni.offset = uniOffset;
			bUni.type = uniType;
			bUni.size = auxSize;
			bUni.arrayStride = uniArrayStride;

			block.uniformOffsets[name2] = bUni;


		}
		free(name2);
		if (newBlock) {
		block.size = dataSize;
		block.bindingIndex = spBlockCount;
		spBlockCount++;
		}
		spBlocks[name] = block;
	}
}
예제 #17
0
    //---------------------------------------------------------------------
    void GLSLProgramManagerCommon::extractUniforms(GLuint programObject, 
        const GpuConstantDefinitionMap* vertexConstantDefs,
        const GpuConstantDefinitionMap* geometryConstantDefs,
        const GpuConstantDefinitionMap* fragmentConstantDefs,
        const GpuConstantDefinitionMap* hullConstantDefs,
        const GpuConstantDefinitionMap* domainConstantDefs,
        const GpuConstantDefinitionMap* computeConstantDefs,
        GLUniformReferenceList& list, GLUniformBufferList& sharedList)
    {
        // Scan through the active uniforms and add them to the reference list
        GLint uniformCount = 0;
#define uniformLength 200
        //      GLint uniformLength = 0;
        //        glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformLength);

        char uniformName[uniformLength];
        GLUniformReference newGLUniformReference;

        // Get the number of active uniforms
        OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORMS, &uniformCount));

        // Loop over each of the active uniforms, and add them to the reference container
        // only do this for user defined uniforms, ignore built in gl state uniforms
        for (int index = 0; index < uniformCount; index++)
        {
            GLint arraySize;
            GLenum glType;
            OGRE_CHECK_GL_ERROR(glGetActiveUniform(programObject, index, uniformLength, NULL,
                                                   &arraySize, &glType, uniformName));

            // Don't add built in uniforms
            OGRE_CHECK_GL_ERROR(newGLUniformReference.mLocation = glGetUniformLocation(programObject, uniformName));
            if (newGLUniformReference.mLocation >= 0)
            {
                // User defined uniform found, add it to the reference list
                String paramName = String( uniformName );

                // Current ATI drivers (Catalyst 7.2 and earlier) and older NVidia drivers will include all array elements as uniforms but we only want the root array name and location
                // Also note that ATI Catalyst 6.8 to 7.2 there is a bug with glUniform that does not allow you to update a uniform array past the first uniform array element
                // ie you can't start updating an array starting at element 1, must always be element 0.

                // If the uniform name has a "[" in it then its an array element uniform.
                String::size_type arrayStart = paramName.find("[");
                if (arrayStart != String::npos)
                {
                    // if not the first array element then skip it and continue to the next uniform
                    if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0) continue;
                    paramName = paramName.substr(0, arrayStart);
                }

                // Find out which params object this comes from
                bool foundSource = completeParamSource(paramName,
                                                       vertexConstantDefs, geometryConstantDefs,
                                                       fragmentConstantDefs, hullConstantDefs,
                                                       domainConstantDefs, computeConstantDefs, newGLUniformReference);

                // Only add this parameter if we found the source
                if (foundSource)
                {
                    assert(size_t (arraySize) == newGLUniformReference.mConstantDef->arraySize
                           && "GL doesn't agree with our array size!");
                    list.push_back(newGLUniformReference);
                }

                // Don't bother adding individual array params, they will be
                // picked up in the 'parent' parameter can copied all at once
                // anyway, individual indexes are only needed for lookup from
                // user params
            } // end if
        } // end for

        // Now deal with uniform blocks

        GLint blockCount = 0;

        OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_BLOCKS, &blockCount));

        for (int index = 0; index < blockCount; index++)
        {
            OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockName(programObject, index, uniformLength, NULL, uniformName));

            GpuSharedParametersPtr blockSharedParams = GpuProgramManager::getSingleton().getSharedParameters(uniformName);

            GLint blockSize, blockBinding;
            OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockiv(programObject, index, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize));
            OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockiv(programObject, index, GL_UNIFORM_BLOCK_BINDING, &blockBinding));
            HardwareUniformBufferSharedPtr newUniformBuffer = HardwareBufferManager::getSingleton().createUniformBuffer(blockSize, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, false, uniformName);

            GL3PlusHardwareUniformBuffer* hwGlBuffer = static_cast<GL3PlusHardwareUniformBuffer*>(newUniformBuffer.get());
            hwGlBuffer->setGLBufferBinding(blockBinding);
            sharedList.push_back(newUniformBuffer);
        }
    }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL31_nglGetActiveUniformBlockName(JNIEnv *env, jclass clazz, jint program, jint uniformBlockIndex, jint bufSize, jlong length, jlong uniformBlockName, jlong function_pointer) {
	GLsizei *length_address = (GLsizei *)(intptr_t)length;
	GLchar *uniformBlockName_address = (GLchar *)(intptr_t)uniformBlockName;
	glGetActiveUniformBlockNamePROC glGetActiveUniformBlockName = (glGetActiveUniformBlockNamePROC)((intptr_t)function_pointer);
	glGetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length_address, uniformBlockName_address);
}
PIGLIT_GL_TEST_CONFIG_END

void
piglit_init(int argc, char **argv)
{
	int i;
	GLuint prog;
	const char *source =
		"#extension GL_ARB_uniform_buffer_object : enable\n"
		"uniform a { float u1; };\n"
		"uniform bbb { float u2; };\n"
		"uniform cc { float u3; };\n"
		"void main() {\n"
		"	gl_FragColor = vec4(u1 + u2 + u3);\n"
		"}\n";
	int blocks;
	bool pass = true;
	const char *names[3] = {"a", "bbb", "cc"};
	bool found[3] = {false, false, false};
	char no_write;
	char fill_char = 0xd0;

	piglit_require_extension("GL_ARB_uniform_buffer_object");

	prog = piglit_build_simple_program(NULL, source);

	glGetProgramiv(prog, GL_ACTIVE_UNIFORM_BLOCKS, &blocks);
	assert(blocks == 3);

	for (i = 0; i < blocks; i++) {
		GLint written_strlen = 0;
		GLint namelen = 9999;
		char name[1000];
		int name_index;

		/* This is the size including null terminator. */
		glGetActiveUniformBlockiv(prog, i, GL_UNIFORM_BLOCK_NAME_LENGTH,
					  &namelen);

		memset(name, 0xd0, sizeof(name));
		glGetActiveUniformBlockName(prog, i, sizeof(name),
					    &written_strlen, name);
		if (written_strlen >= sizeof(name) - 1) {
			fprintf(stderr,
				"return strlen %d, longer than the buffer size\n",
				written_strlen);
			pass = false;
			continue;
		} else if (name[written_strlen] != 0) {
			fprintf(stderr, "return name[%d] was %d, expected 0\n",
				written_strlen, name[written_strlen]);
			pass = false;
			continue;
		} else if (strlen(name) != written_strlen) {
			fprintf(stderr, "return strlen was %d, but \"%s\" "
				"has strlen %d\n", written_strlen, name,
				(int)strlen(name));
			pass = false;
			continue;
		}

		for (name_index = 0; name_index < ARRAY_SIZE(names); name_index++) {
			if (strcmp(names[name_index], name) == 0) {
				if (found[name_index]) {
					fprintf(stderr,
						"Uniform block \"%s\" "
						"returned twice.\n", name);
					pass = false;
				}
				found[name_index] = true;
				break;
			}
		}
		if (name_index == ARRAY_SIZE(names)) {
			fprintf(stderr,
				"block \"%s\" is not a known block name\n", name);
			pass = false;
			continue;
		}

		if (namelen != written_strlen + 1) {
			fprintf(stderr,
				"block \"%s\" had "
				"GL_UNIFORM_BLOCK_NAME_LENGTH %d, expected %d\n",
				name, namelen, written_strlen + 1);
			pass = false;
			continue;
		}

		/* Test for overflow by writing to a bufSize equal to
		 * strlen and checking if a null terminator or
		 * something landed past that.
		 */
		memset(name, fill_char, sizeof(name));
		glGetActiveUniformBlockName(prog, i, written_strlen,
					    NULL, name);
		if (name[written_strlen] != fill_char) {
			fprintf(stderr, "glGetActiveUniformName overflowed: "
				"name[%d] = 0x%02x instead of 0x%02x\n",
				written_strlen, name[written_strlen],
				fill_char);
			pass = false;
		}
	}

	no_write = fill_char;
	glGetActiveUniformBlockName(0xd0d0, 0, 1, NULL, &no_write);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;
	if (no_write != fill_char)
		pass = false;

	no_write = fill_char;
	glGetActiveUniformBlockName(prog, 0, -1, NULL, &no_write);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;
	if (no_write != fill_char)
		pass = false;

	no_write = fill_char;
	glGetActiveUniformBlockName(prog, blocks, 1, NULL, &no_write);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;
	if (no_write != fill_char)
		pass = false;

	glDeleteProgram(prog);

	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
}
예제 #20
0
파일: ogl_shader.cpp 프로젝트: Kingwl/ray
void
OGLShaderObject::_initActiveUniformBlock() noexcept
{
	GLint numUniformBlock = 0;
	GLint maxUniformBlockLength = 0;
	GLint maxUniformLength = 0;

	glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlock);
	glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxUniformBlockLength);
	glGetProgramiv(_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLength);

	if (numUniformBlock)
	{
		auto nameUniformBlock = make_scope<GLchar[]>(maxUniformBlockLength + 1);
		nameUniformBlock[maxUniformBlockLength] = 0;

		for (GLint i = 0; i < numUniformBlock; ++i)
		{
			GLsizei lengthUniformBlock;
			glGetActiveUniformBlockName(_program, (GLuint)i, maxUniformBlockLength, &lengthUniformBlock, nameUniformBlock.get());

			GLuint location = glGetUniformBlockIndex(_program, nameUniformBlock.get());
			if (location == GL_INVALID_INDEX)
				continue;

			glUniformBlockBinding(_program, location, location);

			GLint size;
			GLint count;

			glGetActiveUniformBlockiv(_program, location, GL_UNIFORM_BLOCK_DATA_SIZE, &size);
			glGetActiveUniformBlockiv(_program, location, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &count);

			if (count)
			{
				std::vector<GLint> indices(count);
				glGetActiveUniformBlockiv(_program, location, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices.data());

				std::vector<GLint> offset((std::size_t)count);
				std::vector<GLint> type((std::size_t)count);
				std::vector<GLint> datasize((std::size_t)count);
				std::vector<std::string> varlist((std::size_t)count);
				std::vector<GLchar> name(maxUniformLength);

				glGetActiveUniformsiv(_program, count, (GLuint*)&indices[0], GL_UNIFORM_OFFSET, &offset[0]);
				glGetActiveUniformsiv(_program, count, (GLuint*)&indices[0], GL_UNIFORM_TYPE, &type[0]);
				glGetActiveUniformsiv(_program, count, (GLuint*)&indices[0], GL_UNIFORM_SIZE, &datasize[0]);

				for (GLint j = 0; j < count; ++j)
				{
					GLsizei length = 0;
#if !defined(EGLAPI)
					glGetActiveUniformName(_program, indices[j], maxUniformLength, &length, name.data());
#else
					glGetActiveUniform(_program, indices[j], maxUniformLength, &length, &datasize[j], (GLenum*)&type[j], name.data());
#endif
					
					varlist[j].append(name.data(), length);
				}

				auto uniformblock = std::make_shared<ShaderUniform>();
				uniformblock->setName(nameUniformBlock.get());
				uniformblock->setType(ShaderVariantType::SPT_BUFFER);
				uniformblock->setLocation(location);

				_activeUniforms.push_back(uniformblock);
			}
		}
	}
}
//-----------------------------------------------------------------------------
void CPUTMaterialEffectOGL::ReadShaderSamplersAndTextures( GLuint shaderProgram, CPUTShaderParameters *pShaderParameter )
{
    GLint numActiveUniforms;
    GLint activeUniformMaxLength;
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &numActiveUniforms));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformMaxLength));
    
#ifndef CPUT_FOR_OGLES2
    GLint numActiveUniformBlocks;
    GLint activeUniformBlockMaxLength = 50;
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks));
#else
#warning "Need to do something with uniform blocks here"
#endif
	//
	// #### This parameter is currently unsupported by Intel OGL drivers.
	//
  //  GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &activeUniformBlockMaxLength));
    
    GLchar* uniformVariableName = new GLchar[activeUniformMaxLength];
    GLenum  dataType;
    GLint   size;
    for (int i = 0; i < numActiveUniforms; i++) {
        GL_CHECK(glGetActiveUniform(shaderProgram, i, activeUniformMaxLength, NULL, &size, &dataType, uniformVariableName));
        switch(dataType) {
#ifndef CPUT_FOR_OGLES
            case GL_SAMPLER_1D:
#endif
        case GL_SAMPLER_2D:
#ifndef CPUT_FOR_OGLES2
        case GL_SAMPLER_3D:
#endif
		case GL_SAMPLER_2D_SHADOW:
        case GL_SAMPLER_CUBE:
		        pShaderParameter->mpTextureParameterNames.push_back(uniformVariableName);
                pShaderParameter->mpTextureParameterLocations.push_back(glGetUniformLocation(shaderProgram, uniformVariableName));
                pShaderParameter->mTextureParameterCount++;
                break;
            default:
                // unsupported uniform type
            break;
        }
    }
	delete uniformVariableName;

#ifndef CPUT_FOR_OGLES2
    GLchar* uniformBlockName = new GLchar[activeUniformBlockMaxLength];
    for (int i = 0; i < numActiveUniformBlocks; i++) 
    {
        GL_CHECK(ES3_COMPAT(glGetActiveUniformBlockName(shaderProgram, i, activeUniformBlockMaxLength, NULL, uniformBlockName)));
        pShaderParameter->mConstantBufferParameterNames.push_back(uniformBlockName);
        pShaderParameter->mConstantBufferBindPoints.push_back(ES3_COMPAT(glGetUniformBlockIndex(shaderProgram, uniformBlockName)));
        pShaderParameter->mConstantBufferParameterCount++;
    }
    delete uniformBlockName;
#else
#warning "Need to do something with uniform blocks here"
#endif
/*    
    glUseProgram(0);
    
    GLchar activeUniformNames[10][100];
    GLchar activeUniformBlockNames[10][100];
    GLchar activeAttributeNames[10][100];
    GLint numActiveAttributes, activeAttributeMaxLength;
    GLint numActiveUniformBlocks, activeUniformBlockMaxLength;
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &numActiveUniforms));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformMaxLength));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &numActiveAttributes));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttributeMaxLength));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks));
    GL_CHECK(glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &activeUniformBlockMaxLength));
    
    GLsizei numBytesWritten;
    
    
     for (int i = 0; i < numActiveUniforms; i++) {
        GL_CHECK(glGetActiveUniform(shaderProgram, i, 100, &numBytesWritten, &size, &dataType, activeUniformNames[i]));
    }
    
    for (int i = 0; i < numActiveAttributes; i++) {
        GL_CHECK(glGetActiveAttrib(shaderProgram, i, 100, &numBytesWritten, &size, &dataType, activeAttributeNames[i]));
    }
    
    for (int i = 0; i < numActiveUniformBlocks; i++) {
 //       GL_CHECK(glGetActiveUniformBlock(shaderProgram, i, ));
    }

    CheckDebugLog2();
    
    GLuint g_gaussSampler;
    glGenSamplers(1, &g_gaussSampler);
    glSamplerParameteri(g_gaussSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glSamplerParameteri(g_gaussSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glSamplerParameteri(g_gaussSampler, GL_TEXTURE_WRAP_S, GL_REPEAT);

    GLuint TextureName = gli::createTexture2D("/home/q-dawg/Develop/projects/Framework/CPUT_Linux/SampleStartCPUT/Media/Teapot/Texture/checker_20x.dds");

    
    glBindTexture(GL_TEXTURE_2D, TextureName);
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ));
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ));
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ));
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ));
    GL_CHECK(glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT ));
    GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
    
    GLint diffuseTextureLocation = glGetUniformLocation(shaderProgram, "diffuseTex");
    CheckDebugLog2();
    glUseProgram(mShaderProgram);
    glUniform1i(diffuseTextureLocation, 0);
    CheckDebugLog2();
    GL_CHECK(glActiveTexture(GL_TEXTURE0 + 0));
    GL_CHECK(glBindTexture(GL_TEXTURE_2D, TextureName));
    glUseProgram(0);
*/    
}
예제 #22
0
int main()
{
  EmscriptenWebGLContextAttributes attrs;
  emscripten_webgl_init_context_attributes(&attrs);

  attrs.enableExtensionsByDefault = 1;
  attrs.majorVersion = 2;
  attrs.minorVersion = 0;

  EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context( 0, &attrs );
  if (!context)
  {
    printf("Skipped: WebGL 2 is not supported.\n");
#ifdef REPORT_RESULT
    REPORT_RESULT();
#endif
    return 0;
  }
  emscripten_webgl_make_context_current(context);

  const char *vertexShader =
    "#version 300 es\n"
    "uniform Block1a {\n"
    "  uniform mat4 var1;\n"
    "  uniform vec4 variable2;\n"
    "} block1bb;\n"
    "uniform Block2ccc {\n"
    "  uniform mat4 var1;\n"
    "  uniform vec4 variable2;\n"
    "} block2dddd;\n"
    "void main() {\n"
    "  gl_Position = block1bb.var1*block1bb.variable2 + block2dddd.var1*block2dddd.variable2;\n"
    "}\n";

    const char *fragmentShader = 
    "#version 300 es\n"
    "precision lowp float;\n"
    "  uniform Block3eeeee {\n"
    "  uniform vec4 var1;\n"
    "  uniform vec4 variable2;\n" 
    "} block3ffffff;\n"   // Append characters of different lengths to test name string lengths.
    "out vec4 outColor;\n"
    "void main() {\n"
    "  outColor = block3ffffff.var1 + block3ffffff.variable2;\n"
    "}\n";

  GLuint vs = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vs, 1, &vertexShader, NULL);
  glCompileShader(vs);
  int ok = 0;
  glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
  if (!ok) {
    printf("Shader compilation error with vertex\n");
    GLint infoLen = 0;
    glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen);
    if (infoLen > 1)
    {
       char* infoLog = (char *)malloc(sizeof(char) * infoLen+1);
       glGetShaderInfoLog(vs, infoLen, NULL, infoLog);
       printf("Error compiling shader:\n%s\n", infoLog);            
    }
  }

  GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fs, 1, &fragmentShader, NULL);
  glCompileShader(fs);
  glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
  if (!ok) {
    printf("Shader compilation error with fragment\n");
    GLint infoLen = 0;
    glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen);
    if (infoLen > 1)
    {
       char* infoLog = (char *)malloc(sizeof(char) * infoLen+1);
       glGetShaderInfoLog(vs, infoLen, NULL, infoLog);
       printf("Error compiling shader:\n%s\n", infoLog);            
    }
  }

  GLuint program = glCreateProgram();

  glAttachShader(program, vs);
  glAttachShader(program, fs);
  glLinkProgram(program);
  glGetProgramiv(program, GL_LINK_STATUS, &ok);
  assert(ok);

  int maxLength = 0;
  glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxLength);
  printf("GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: %d\n", maxLength);
  assert(maxLength == 12);

  GLint numActiveUniformBlocks = -1;
  glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks);
  assert(numActiveUniformBlocks == 3);

  // Dump all active uniform buffer blocks of the current program.
  for(int i = 0; i < numActiveUniformBlocks; ++i)
  {
    char str[256] = {};
    GLsizei length = -1;
    glGetActiveUniformBlockName(program, i, 255, &length, str);
    assert(length > 0);
    printf("Active uniform block at index %d: %s\n", i, str);
    
    GLint param = -1;
#define DUMPUNIFORMBLOCKSTATUS(stat) glGetActiveUniformBlockiv(program, i, stat, &param); printf("%s: %d\n", #stat, param);
    DUMPUNIFORMBLOCKSTATUS(GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER);
    DUMPUNIFORMBLOCKSTATUS(GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER);
    DUMPUNIFORMBLOCKSTATUS(GL_UNIFORM_BLOCK_BINDING);
    DUMPUNIFORMBLOCKSTATUS(GL_UNIFORM_BLOCK_DATA_SIZE);
    DUMPUNIFORMBLOCKSTATUS(GL_UNIFORM_BLOCK_NAME_LENGTH);
    DUMPUNIFORMBLOCKSTATUS(GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS);
    GLint indices[16] = {};
    glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices);
    for(size_t i = 0; i < param; ++i)
      printf("offset for index %d: %d\n", i, indices[i]);
  }

#ifdef REPORT_RESULT
  REPORT_RESULT();
#endif
  return 0;
}
예제 #23
0
void RendererBasePimpl::InitDomainUniformAndSamplers(ShaderProgram * resource, unsigned int domain, GLuint program)
{


	char uniform_name[1000];
	GLsizei name_length;
	GLint uniform_size;
	GLenum uniform_type;
	GLint uniform_count;

	GLuint uniform_location;
	glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniform_count);

	std::vector<std::pair<std::string, int> > uniform_names;
	std::vector<std::pair<std::string, int> > sampler_names;
	std::vector<UniformParam> uniform_vector;
	std::vector<GLuint> uniform_locations;
	std::vector<SamplerParam> sampler_vector;
	std::vector<GLuint> sampler_locations;

	unsigned int next_offset = 0;

	for (int i = 0; i < uniform_count; ++i)
	{
		glGetActiveUniform(program, i, 1000, &name_length, &uniform_size, &uniform_type, uniform_name);
		uniform_location = glGetUniformLocation(program, uniform_name);

		unsigned char rows = 1;
		unsigned char columns = 1;
		unsigned char type = 0;
		bool sampler = false;
		GetTypeInfo(uniform_type, type, rows, columns, sampler);
		if (sampler)
		{
			sampler_names.push_back(std::make_pair(uniform_name, sampler_names.size()));
			sampler_vector.push_back(SamplerParam());
			sampler_vector.back().type = type;
			sampler_locations.push_back(uniform_location);
		}
		else
		{
			uniform_names.push_back(std::make_pair(uniform_name, uniform_names.size()));
			uniform_vector.push_back(UniformParam());
			uniform_vector.back().array_length = uniform_size;
			uniform_vector.back().row_major = false;
			uniform_vector.back().type = type;
			uniform_vector.back().rows = rows;
			uniform_vector.back().columns = columns;
			uniform_vector.back().uniform_buffer_index = 0;
			uniform_vector.back().uniform_buffer_offset = next_offset;
			uniform_vector.back().uniform_buffer_array_stride = 0;
			uniform_vector.back().uniform_buffer_matrix_stride = rows > 1 ? rows : 0;
			uniform_locations.push_back(uniform_location);
			switch(type)
			{
				case DT_FLOAT:
					next_offset = next_offset + (sizeof(float) * rows * columns * uniform_size);
					break;
				default:
					std::cout << "Other types not supported yet." << std::endl;
					break;
			}
		}
	}

	std::sort(uniform_names.begin(), uniform_names.end());
	std::sort(sampler_names.begin(), sampler_names.end());

	resource->uniforms.Set(uniform_names.size());
	resource->samplers.Set(sampler_names.size());

	GLint uniformblock_count = 0;
	if (GLEW_ARB_uniform_buffer_object)
	{
		char uniformblock_name[1000];
		GLint name_length;
		GLint block_binding;
		GLint block_data_size;
		GLint block_active_uniforms;
		

		glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &uniformblock_count);

		resource->uniform_blocks.Set(uniform_names.size() > 0 ? uniformblock_count + 1 : uniformblock_count); //Add one because we make "no ubo" as 0 index.
	
		unsigned int total_uniforms_in_blocks = 0;
		for (int i = 0; i < uniformblock_count; ++i)
		{
			glGetActiveUniformBlockName(program, i, 1000, &name_length, uniformblock_name);

			GLint params;
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_BINDING, &block_binding);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_DATA_SIZE, &block_data_size);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &params);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &block_active_uniforms);
			std::vector<GLuint> uniform_indices(block_active_uniforms, 0);
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, reinterpret_cast<GLint*>(&uniform_indices[0]));

			std::vector<GLuint> uniform_offsets(block_active_uniforms, 0);
			glGetActiveUniformsiv(program, block_active_uniforms, &uniform_indices[0], GL_UNIFORM_OFFSET, reinterpret_cast<GLint*>(&uniform_offsets[0]));
			std::vector<GLuint> uniform_arraystrides(block_active_uniforms, 0);
			glGetActiveUniformsiv(program, block_active_uniforms, &uniform_indices[0], GL_UNIFORM_ARRAY_STRIDE, reinterpret_cast<GLint*>(&uniform_arraystrides[0]));
			std::vector<GLuint> uniform_matrixstrides(block_active_uniforms, 0);
			glGetActiveUniformsiv(program, block_active_uniforms, &uniform_indices[0], GL_UNIFORM_MATRIX_STRIDE, reinterpret_cast<GLint*>(&uniform_matrixstrides[0]));
			std::vector<GLuint> uniform_rowmajor(block_active_uniforms, 0);
			glGetActiveUniformsiv(program, block_active_uniforms, &uniform_indices[0], GL_UNIFORM_IS_ROW_MAJOR, reinterpret_cast<GLint*>(&uniform_rowmajor[0]));

			
			unsigned int block_index = uniform_names.size() > 0 ? (i + 1) : i;//Add one because we make "no ubo" as 0 index.
			resource->uniform_blocks[block_index].name = uniformblock_name;
			resource->uniform_blocks[block_index].byte_count = block_data_size;
			resource->uniform_blocks[block_index].uniform_indices.Set(block_active_uniforms);
			total_uniforms_in_blocks += block_active_uniforms;
			for (unsigned int p = 0; p < uniform_indices.size(); ++p)
			{
				uniform_vector[uniform_indices[p]].uniform_buffer_index = block_index;
				uniform_vector[uniform_indices[p]].uniform_buffer_offset = uniform_offsets[p];
				uniform_vector[uniform_indices[p]].uniform_buffer_array_stride = uniform_arraystrides[p];
				uniform_vector[uniform_indices[p]].uniform_buffer_matrix_stride = uniform_matrixstrides[p];
				uniform_vector[uniform_indices[p]].row_major = uniform_rowmajor[p];
			}
			//std::cout << "	Location: " << glGetUniformLocation(pimpl->combined, uniformblock_name) << std::endl;
		}
		resource->uniform_blocks[0].uniform_indices.Set(uniform_names.size() - total_uniforms_in_blocks);
	}
	else
	{
		if (uniform_names.size() > 0) 
		{
			resource->uniform_blocks.Set(1);
			resource->uniform_blocks[0].uniform_indices.Set(uniform_names.size());
		}
	}

	if (uniform_names.size() > 0)
	{
		std::vector<unsigned int> block_param_count(resource->uniform_blocks.GetSize(), 0);
		unsigned int block_zero_size = 0;
		//Loop through all uniforms sorted by names.
		for (unsigned int i = 0; i < uniform_names.size(); ++i)
		{
			//Set uniform info in ShaderProgram.domains[domain].uniforms.
			int index = uniform_names[i].second;
			resource->uniforms[i] = uniform_vector[index];
			resource->uniforms[i].name = uniform_names[i].first;

			//Put index in the parameter's block in ShaderProgram.domains[domain].uniform_blocks.
			int uniform_block_index = uniform_vector[index].uniform_buffer_index;
			resource->uniform_blocks[uniform_block_index].uniform_indices[block_param_count[uniform_block_index]] = i;
			block_param_count[uniform_block_index] += 1;

			//For block zero, calculate size.
			if (uniform_block_index == 0)
			{
				block_zero_size = std::max<unsigned int>(
					block_zero_size, 
					uniform_vector[index].uniform_buffer_offset + uniform_vector[index].rows * uniform_vector[index].columns * sizeof(float) * uniform_vector[index].array_length); //Only for DT_FLOAT. Fix later.
			}
		}
		resource->uniform_blocks[0].byte_count = block_zero_size;
	}


	for (unsigned int i = 0; i < sampler_names.size(); ++i)
	{
		int index = sampler_names[i].second;
		resource->samplers[i] = sampler_vector[index];
		resource->samplers[i].name = sampler_names[i].first;
	}

	ShaderProgramPimpl * program_pimpl = (ShaderProgramPimpl *) resource->PRIVATE;
	program_pimpl->uniform_locations.Set(uniform_names.size());
	program_pimpl->sampler_locations.Set(sampler_names.size());
	program_pimpl->sampler_units.Set(sampler_names.size());
	program_pimpl->block_bind_points.Set(uniform_names.size() > 0 ? (uniformblock_count + 1) : uniformblock_count);
	program_pimpl->bound_uniform_buffers.Set(uniformblock_count + 1, 0);
}
예제 #24
0
bool ShaderProgram::Link()
{
    Release();

    if (!vertexShader_ || !pixelShader_ || !vertexShader_->GetGPUObject() || !pixelShader_->GetGPUObject())
        return false;

    object_ = glCreateProgram();
    if (!object_)
    {
        linkerOutput_ = "Could not create shader program";
        return false;
    }

    // Bind vertex attribute locations to ensure they are the same in all shaders
    // Note: this is not the same order as in VertexBuffer, instead a remapping is used to ensure everything except cube texture
    // coordinates fit to the first 8 for better GLES2 device compatibility
    glBindAttribLocation(object_, 0, "iPos");
    glBindAttribLocation(object_, 1, "iNormal");
    glBindAttribLocation(object_, 2, "iColor");
    glBindAttribLocation(object_, 3, "iTexCoord");
    glBindAttribLocation(object_, 4, "iTexCoord2");
    glBindAttribLocation(object_, 5, "iTangent");
    glBindAttribLocation(object_, 6, "iBlendWeights");
    glBindAttribLocation(object_, 7, "iBlendIndices");
    glBindAttribLocation(object_, 8, "iCubeTexCoord");
    glBindAttribLocation(object_, 9, "iCubeTexCoord2");
#if !defined(GL_ES_VERSION_2_0) || defined(__EMSCRIPTEN__)
    glBindAttribLocation(object_, 10, "iInstanceMatrix1");
    glBindAttribLocation(object_, 11, "iInstanceMatrix2");
    glBindAttribLocation(object_, 12, "iInstanceMatrix3");
#endif

    glAttachShader(object_, vertexShader_->GetGPUObject());
    glAttachShader(object_, pixelShader_->GetGPUObject());
    glLinkProgram(object_);

    int linked, length;
    glGetProgramiv(object_, GL_LINK_STATUS, &linked);
    if (!linked)
    {
        glGetProgramiv(object_, GL_INFO_LOG_LENGTH, &length);
        linkerOutput_.Resize((unsigned)length);
        int outLength;
        glGetProgramInfoLog(object_, length, &outLength, &linkerOutput_[0]);
        glDeleteProgram(object_);
        object_ = 0;
    }
    else
        linkerOutput_.Clear();

    if (!object_)
        return false;

    const int MAX_PARAMETER_NAME_LENGTH = 256;
    char uniformName[MAX_PARAMETER_NAME_LENGTH];
    int uniformCount;

    glUseProgram(object_);
    glGetProgramiv(object_, GL_ACTIVE_UNIFORMS, &uniformCount);

    // Check for constant buffers
#ifndef GL_ES_VERSION_2_0
    HashMap<unsigned, unsigned> blockToBinding;

    if (Graphics::GetGL3Support())
    {
        int numUniformBlocks = 0;

        glGetProgramiv(object_, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
        for (int i = 0; i < numUniformBlocks; ++i)
        {
            int nameLength;
            glGetActiveUniformBlockName(object_, (GLuint)i, MAX_PARAMETER_NAME_LENGTH, &nameLength, uniformName);

            String name(uniformName, (unsigned)nameLength);

            unsigned blockIndex = glGetUniformBlockIndex(object_, name.CString());
            unsigned group = M_MAX_UNSIGNED;

            // Try to recognize the use of the buffer from its name
            for (unsigned j = 0; j < MAX_SHADER_PARAMETER_GROUPS; ++j)
            {
                if (name.Contains(shaderParameterGroups[j], false))
                {
                    group = j;
                    break;
                }
            }

            // If name is not recognized, search for a digit in the name and use that as the group index
            if (group == M_MAX_UNSIGNED)
            {
                for (unsigned j = 1; j < name.Length(); ++j)
                {
                    if (name[j] >= '0' && name[j] <= '5')
                    {
                        group = name[j] - '0';
                        break;
                    }
                }
            }

            if (group >= MAX_SHADER_PARAMETER_GROUPS)
            {
                URHO3D_LOGWARNING("Skipping unrecognized uniform block " + name + " in shader program " + vertexShader_->GetFullName() +
                           " " + pixelShader_->GetFullName());
                continue;
            }

            // Find total constant buffer data size
            int dataSize;
            glGetActiveUniformBlockiv(object_, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &dataSize);
            if (!dataSize)
                continue;

            unsigned bindingIndex = group;
            // Vertex shader constant buffer bindings occupy slots starting from zero to maximum supported, pixel shader bindings
            // from that point onward
            if (name.Contains("PS", false))
                bindingIndex += MAX_SHADER_PARAMETER_GROUPS;

            glUniformBlockBinding(object_, blockIndex, bindingIndex);
            blockToBinding[blockIndex] = bindingIndex;

            constantBuffers_[bindingIndex] = graphics_->GetOrCreateConstantBuffer(bindingIndex, (unsigned)dataSize);
        }
    }
#endif

    // Check for shader parameters and texture units
    for (int i = 0; i < uniformCount; ++i)
    {
        unsigned type;
        int count;

        glGetActiveUniform(object_, (GLuint)i, MAX_PARAMETER_NAME_LENGTH, 0, &count, &type, uniformName);
        int location = glGetUniformLocation(object_, uniformName);

        // Check for array index included in the name and strip it
        String name(uniformName);
        unsigned index = name.Find('[');
        if (index != String::NPOS)
        {
            // If not the first index, skip
            if (name.Find("[0]", index) == String::NPOS)
                continue;

            name = name.Substring(0, index);
        }

        if (name[0] == 'c')
        {
            // Store constant uniform
            String paramName = name.Substring(1);
            ShaderParameter newParam;
            newParam.type_ = type;
            newParam.location_ = location;

#ifndef GL_ES_VERSION_2_0
            // If running OpenGL 3, the uniform may be inside a constant buffer
            if (newParam.location_ < 0 && Graphics::GetGL3Support())
            {
                int blockIndex, blockOffset;
                glGetActiveUniformsiv(object_, 1, (const GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
                glGetActiveUniformsiv(object_, 1, (const GLuint*)&i, GL_UNIFORM_OFFSET, &blockOffset);
                if (blockIndex >= 0)
                {
                    newParam.location_ = blockOffset;
                    newParam.bufferPtr_ = constantBuffers_[blockToBinding[blockIndex]];
                }
            }
#endif

            if (newParam.location_ >= 0)
                shaderParameters_[StringHash(paramName)] = newParam;
        }
        else if (location >= 0 && name[0] == 's')
        {
            // Set the samplers here so that they do not have to be set later
            int unit = graphics_->GetTextureUnit(name.Substring(1));
            if (unit >= MAX_TEXTURE_UNITS)
            {
                // If texture unit name is not recognized, search for a digit in the name and use that as the unit index
                for (unsigned j = 1; j < name.Length(); ++j)
                {
                    if (name[j] >= '0' && name[j] <= '9')
                    {
                        unit = name[j] - '0';
                        break;
                    }
                }
            }

            if (unit < MAX_TEXTURE_UNITS)
            {
                useTextureUnit_[unit] = true;
                glUniform1iv(location, 1, &unit);
            }
        }
    }

    // Rehash the parameter map to ensure minimal load factor
    shaderParameters_.Rehash(NextPowerOfTwo(shaderParameters_.Size()));

    return true;
}
예제 #25
0
	bool initProgram()
	{
		bool Validated = true;

		compiler Compiler;
	
		// Create program
		if(Validated)
		{
			compiler Compiler;
			GLuint VertShaderName = Compiler.create(GL_VERTEX_SHADER, getDataDirectory() + VERT_SHADER_SOURCE, "--version 150 --profile core");
			GLuint FragShaderName = Compiler.create(GL_FRAGMENT_SHADER, getDataDirectory() + FRAG_SHADER_SOURCE, "--version 150 --profile core");

			ProgramName = glCreateProgram();
			glAttachShader(ProgramName, VertShaderName);
			glAttachShader(ProgramName, FragShaderName);

			glBindAttribLocation(ProgramName, semantic::attr::POSITION, "Position");
			glBindFragDataLocation(ProgramName, semantic::frag::COLOR, "Color");
			glLinkProgram(ProgramName);

			Validated = Validated && Compiler.check();
			Validated = Validated && Compiler.checkProgram(ProgramName);
		}

		// Get variables locations
		if(Validated)
		{
			UniformMaterial = glGetUniformBlockIndex(ProgramName, "material");
			UniformTransform = glGetUniformBlockIndex(ProgramName, "transform");

			glUniformBlockBinding(ProgramName, UniformTransform, semantic::uniform::TRANSFORM0);
			glUniformBlockBinding(ProgramName, UniformMaterial, semantic::uniform::MATERIAL);
		}

		GLint ActiveUniformBlocks(0);
		glGetProgramiv(ProgramName, GL_ACTIVE_UNIFORM_BLOCKS, &ActiveUniformBlocks);

		for(GLint i = 0; i < ActiveUniformBlocks; ++i)
		{
			char Name[128];
			memset(Name, '\0', sizeof(Name));
			GLsizei Length(0);

			glGetActiveUniformBlockName(ProgramName, i, GLsizei(sizeof(Name)), &Length, Name);

			std::string StringName(Name);

			Validated = Validated && (StringName == std::string("material") || StringName == std::string("transform"));
		}

		GLint ActiveUniform(0);
		glGetProgramiv(ProgramName, GL_ACTIVE_UNIFORMS, &ActiveUniform);

		for(GLint i = 0; i < ActiveUniformBlocks; ++i)
		{
			char Name[128];
			memset(Name, '\0', sizeof(Name));
			GLsizei Length(0);

			glGetActiveUniformName(ProgramName, i, GLsizei(sizeof(Name)), &Length, Name);

			std::string StringName(Name);

			Validated = Validated && (
				StringName == std::string("material.Diffuse") || 
				StringName == std::string("transform.MVP"));
		}
	
		return Validated && this->checkError("initProgram");
	}
예제 #26
0
PIGLIT_GL_TEST_CONFIG_END

void
piglit_init(int argc, char **argv)
{
	bool pass = true;
	unsigned int i;
	GLuint vs, gs, fs, prog;
	const char *vs_source =
		"%s"
		"uniform vs { float v; };\n"
		"uniform vsgs { float vg; };\n"
		"uniform vsfs { float vf; };\n"
		"uniform vsgsfs { float vgf; };\n"
		"void main() {\n"
		"	gl_Position = vec4(v + vg + vf + vgf);\n"
		"}\n";

	const char *gs_source =
		"%s"
		"layout(triangles) in;\n"
		"layout(triangle_strip, max_vertices=3) out;\n"
		"uniform gs { float g; };\n"
		"uniform vsgs { float vg; };\n"
		"uniform gsfs { float gf; };\n"
		"uniform vsgsfs { float vgf; };\n"
		"void main() {\n"
		"	for(int i = 0; i < 3; i++) {\n"
		"		gl_Position = vec4(g + vg + gf + vgf);\n"
		"		EmitVertex();\n"
		"	}\n"
		"}\n";

	const char *fs_source =
		"%s"
		"uniform fs { float f; };\n"
		"uniform vsfs { float vf; };\n"
		"uniform gsfs { float gf; };\n"
		"uniform vsgsfs { float vgf; };\n"
		"void main() {\n"
		"	gl_FragColor = vec4(f + vf + gf + vgf);\n"
		"}\n";

	char name[10];
	bool use_gs = piglit_get_gl_version() >= 32;
	const char *header;
	char *temp_source;
	int num_uniforms_used = 0;

	if (use_gs) {
		header = "#version 150\n";
	} else {
		header = "#extension GL_ARB_uniform_buffer_object : enable\n";
		piglit_require_extension("GL_ARB_uniform_buffer_object");
	}

	prog = glCreateProgram();

	asprintf(&temp_source, vs_source, header);
	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, temp_source);
	glAttachShader(prog, vs);
	free(temp_source);

	if (use_gs) {
		asprintf(&temp_source, gs_source, header);
		gs = piglit_compile_shader_text(GL_GEOMETRY_SHADER, temp_source);
		glAttachShader(prog, gs);
		free(temp_source);
	}

	asprintf(&temp_source, fs_source, header);
	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, temp_source);
	glAttachShader(prog, fs);
	free(temp_source);

	glLinkProgram(prog);
	if (!piglit_link_check_status(prog)) {
		piglit_report_result(PIGLIT_FAIL);
	}

	if (use_gs) {
		num_uniforms_used = 7;
		printf("            v g f\n");
	} else {
		num_uniforms_used = 6;
		printf("            v f\n");
	}

	for (i = 0; i < num_uniforms_used; i++) {
		GLint ref_vs = 0, ref_gs = 0, ref_fs = 0;
		bool block_fail = false;

		glGetActiveUniformBlockName(prog, i, sizeof(name), NULL, name);

		glGetActiveUniformBlockiv(prog, i,
					  GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
					  &ref_vs);
		if (use_gs) {
			glGetActiveUniformBlockiv(prog, i,
						  GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER,
						  &ref_gs);
		}
		glGetActiveUniformBlockiv(prog, i,
					  GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,
					  &ref_fs);

		if (use_gs) {
			printf("%10s: %d %d %d", name, ref_vs, ref_gs, ref_fs);
		} else {
			printf("%10s: %d %d", name, ref_vs, ref_fs);
		}

		if ((strstr(name, "vs") != 0) != ref_vs)
			block_fail = true;
		if (use_gs) {
			if ((strstr(name, "gs") != 0) != ref_gs)
				block_fail = true;
		}
		if ((strstr(name, "fs") != 0) != ref_fs)
			block_fail = true;

		if (block_fail) {
			printf(" FAIL");
			pass = false;
		}

		printf("\n");
	}

	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
}
예제 #27
0
파일: shader.cpp 프로젝트: a2flo/a2elight
/*! adds a shader object
 */
shader_object* shader::add_shader_src(const string& identifier, const string& option, ext::GLSL_VERSION glsl_version, const char* vs_text, const char* gs_text, const char* fs_text) {
	// success flag (if it's 1 (true), we successfully created a shader object)
	int success;
	GLchar info_log[A2E_SHADER_LOG_SIZE];
	
	if(gs_text != nullptr && strcmp(gs_text, "") == 0) gs_text = nullptr;
	
	// create a new shader object if none exists for this identifier
	if(shaders.count(identifier) == 0) {
		shaders[identifier] = new shader_object(identifier);
	}
	
	// add a new program object to this shader
	shaders[identifier]->programs.push_back(new shader_object::internal_shader_object());
	if(option != "") {
		shaders[identifier]->options[option] = shaders[identifier]->programs.back();
	}
	shader_object::internal_shader_object& shd_obj = *shaders[identifier]->programs.back();
	shaders[identifier]->glsl_version = std::max(shaders[identifier]->glsl_version, glsl_version);
	
	// create the vertex shader object
	shd_obj.vertex_shader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(shd_obj.vertex_shader, 1, (GLchar const**)&vs_text, nullptr);
	glCompileShader(shd_obj.vertex_shader);
	glGetShaderiv(shd_obj.vertex_shader, GL_COMPILE_STATUS, &success);
	if(!success) {
		glGetShaderInfoLog(shd_obj.vertex_shader, A2E_SHADER_LOG_SIZE, nullptr, info_log);
		log_error("Error in vertex shader \"%s/%s\" compilation!", identifier, option);
		log_pretty_print(info_log, vs_text);
		return 0;
	}
	
#if !defined(FLOOR_IOS)
	// create the geometry shader object
	if(gs_text != nullptr && strcmp(gs_text, "") != 0) {
		shd_obj.geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
		glShaderSource(shd_obj.geometry_shader, 1, (GLchar const**)&gs_text, nullptr);
		glCompileShader(shd_obj.geometry_shader);
		glGetShaderiv(shd_obj.geometry_shader, GL_COMPILE_STATUS, &success);
		if(!success) {
			glGetShaderInfoLog(shd_obj.geometry_shader, A2E_SHADER_LOG_SIZE, nullptr, info_log);
			log_error("Error in geometry shader \"%s/%s\" compilation!", identifier, option);
			log_pretty_print(info_log, gs_text);
			return 0;
		}
	}
	else shd_obj.geometry_shader = 0;
#else
	if(gs_text != nullptr && strcmp(gs_text, "") != 0) {
		log_error("geometry shaders are not supported in OpenGL ES 2.0 or 3.0!");
	}
	shd_obj.geometry_shader = 0;
#endif
	
	// create the fragment shader object
	shd_obj.fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(shd_obj.fragment_shader, 1, (GLchar const**)&fs_text, nullptr);
	glCompileShader(shd_obj.fragment_shader);
	glGetShaderiv(shd_obj.fragment_shader, GL_COMPILE_STATUS, &success);
	if(!success) {
		glGetShaderInfoLog(shd_obj.fragment_shader, A2E_SHADER_LOG_SIZE, nullptr, info_log);
		log_error("Error in fragment shader \"%s/%s\" compilation!", identifier, option);
		log_pretty_print(info_log, fs_text);
		return 0;
	}
	
	// create the program object
	shd_obj.program = glCreateProgram();
	// attach the vertex and fragment shader progam to it
	glAttachShader(shd_obj.program, shd_obj.vertex_shader);
	glAttachShader(shd_obj.program, shd_obj.fragment_shader);
	if(gs_text != nullptr) {
		glAttachShader(shd_obj.program, shd_obj.geometry_shader);
	}

	// WIP: program binary
#if defined(A2E_DEBUG_PROGRAM_BINARY)
#if defined(__APPLE__)
	{
		fstream progcode_vs("/tmp/a2e_shd_code_vs.glsl", fstream::out);
		progcode_vs << vs_text << endl;
		progcode_vs.close();
		if(shd_obj.geometry_shader != 0) {
			fstream progcode_gs("/tmp/a2e_shd_code_gs.glsl", fstream::out);
			progcode_gs << gs_text << endl;
			progcode_gs.close();
		}
		fstream progcode_fs("/tmp/a2e_shd_code_fs.glsl", fstream::out);
		progcode_fs << fs_text << endl;
		progcode_fs.close();
		
		string output_vs = "", output_gs = "", output_fs = "";
		core::system("cgc -profile gp4vp -strict -oglsl /tmp/a2e_shd_code_vs.glsl 2>&1", output_vs);
		if(shd_obj.geometry_shader != 0) {
			core::system("cgc -profile gp4gp -strict -oglsl -po POINT /tmp/a2e_shd_code_gs.glsl 2>&1", output_gs);
		}
		core::system("cgc -profile gp4fp -strict -oglsl /tmp/a2e_shd_code_fs.glsl 2>&1", output_fs);
		
		system("rm /tmp/a2e_shd_code_vs.glsl");
		if(shd_obj.geometry_shader != 0) {
			system("rm /tmp/a2e_shd_code_gs.glsl");
		}
		system("rm /tmp/a2e_shd_code_fs.glsl");
		
		//
		shader_debug::add(identifier, option, output_vs, output_gs, output_fs);
	}
#else
	if(exts->is_ext_supported("GL_ARB_get_program_binary")) glProgramParameteri(shd_obj.program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
#endif
#endif
	
	// now link the program object
	glLinkProgram(shd_obj.program);
	glGetProgramiv(shd_obj.program, GL_LINK_STATUS, &success);
	if(!success) {
		glGetProgramInfoLog(shd_obj.program, A2E_SHADER_LOG_SIZE, nullptr, info_log);
		log_error("Error in program \"%s/%s\" linkage!\nInfo log: %s", identifier, option, info_log);
		return 0;
	}
	glUseProgram(shd_obj.program);
	
	// bind frag data locations (frag_color, frag_color_2, frag_color_3, ...)
	bool fd_relink = false;
#if !defined(FLOOR_IOS)
	const unsigned int max_draw_buffers = exts->get_max_draw_buffers();
	for(unsigned int i = 0; i < max_draw_buffers; i++) {
		string name = "frag_color";
		if(i >= 1) name += "_"+to_string(i+1);
		const GLint location = glGetFragDataLocation(shd_obj.program, name.c_str());
		
		// check if the frag color exists and must be bound to a different location
		if(location >= 0 && i != (GLuint)location) {
			// if so, bind it to the correct location
			glBindFragDataLocation(shd_obj.program, i, name.c_str());
			fd_relink = true;
		}
	}
#else
	// NOTE: MRTs are not support in OpenGL ES 2.0
	// in OpenGL ES 3.0 the locations are already set in the shader
#endif
	if(fd_relink) {
		// program must be linked again after the frag data locations were modified
		// (double-linkage sucks, but there's no other way in opengl 3.2 ...)
		glLinkProgram(shd_obj.program);
	}
	
	// WIP: program binary
#if defined(A2E_DEBUG_PROGRAM_BINARY)
#if !defined(__APPLE__)
	if(exts->is_ext_supported("GL_ARB_get_program_binary")) {
		GLint binary_length = 0;
		glGetProgramiv(shd_obj.program, GL_PROGRAM_BINARY_LENGTH, &binary_length);

		unsigned char* binary = new unsigned char[binary_length];
		GLenum binary_format = 0;
		glGetProgramBinary(shd_obj.program, binary_length, nullptr, &binary_format, binary);

		string binary_fname = "shader_binary_"+identifier+"_"+to_string(shaders[identifier]->programs.size()-1)+".dat";
		f->open_file(binary_fname.c_str(), file_io::OT_WRITE_BINARY);
		f->write_block((const char*)binary, binary_length, false);
		f->close_file();

		delete [] binary;
	}
#endif
#endif
	
	// grab number and names of all attributes and uniforms and get their locations (needs to be done before validation, b/c we have to set sampler locations)
	GLint attr_count = 0, uni_count = 0, max_attr_len = 0, max_uni_len = 0;
	GLint var_location = 0;
	GLint var_size = 0;
	GLenum var_type = 0;
	
	glGetProgramiv(shd_obj.program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_len);
	glGetProgramiv(shd_obj.program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uni_len);
	glGetProgramiv(shd_obj.program, GL_ACTIVE_ATTRIBUTES, &attr_count);
	glGetProgramiv(shd_obj.program, GL_ACTIVE_UNIFORMS, &uni_count);
	max_attr_len+=2;
	max_uni_len+=2;
	
#if !defined(FLOOR_IOS) || defined(PLATFORM_X64)
	GLint uni_block_count = 0, max_uni_block_len = 0;
	glGetProgramiv(shd_obj.program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_uni_block_len);
	glGetProgramiv(shd_obj.program, GL_ACTIVE_UNIFORM_BLOCKS, &uni_block_count);
	max_uni_block_len+=2;
#endif
		
	// note: this may report weird attribute/uniform names (and locations), if uniforms/attributes are optimized away by the compiler
	
	bool print_debug_info = false;
	//if(identifier == "SIMPLE") {
	/*if(identifier == "FONT") {
		print_debug_info = true;
		cout << endl << "## " << identifier << "::" << option << endl;
	}*/
	
	GLchar* attr_name = new GLchar[(size_t)max_attr_len];
	if(print_debug_info) log_undecorated("## shader: %s", identifier);
	if(print_debug_info) log_undecorated("GL_ACTIVE_ATTRIBUTES: %u", attr_count);
	for(GLuint attr = 0; attr < (GLuint)attr_count; attr++) {
		memset(attr_name, 0, (size_t)max_attr_len);
		glGetActiveAttrib(shd_obj.program, attr, max_attr_len-1, nullptr, &var_size, &var_type, attr_name);
		var_location = glGetAttribLocation(shd_obj.program, attr_name);
		if(var_location < 0) {
			if(print_debug_info) log_error("Warning: could not get location for attribute \"%s\" in shader #%s/%s!", attr_name, identifier, option);
			continue;
		}
		if(print_debug_info) log_undecorated("attribute #%u: %s", var_location, attr_name);
		
		string attribute_name = attr_name;
		if(attribute_name.find("[") != string::npos) attribute_name = attribute_name.substr(0, attribute_name.find("["));
		shd_obj.attributes.insert(make_pair(attribute_name,
											shader_object::internal_shader_object::shader_variable((size_t)var_location, (size_t)var_size, var_type)));
	}
	delete [] attr_name;
	
	GLchar* uni_name = new GLchar[(size_t)max_uni_len];
	if(print_debug_info) log_undecorated("GL_ACTIVE_UNIFORMS: %u", uni_count);
	for(GLuint uniform = 0; uniform < (GLuint)uni_count; uniform++) {
		memset(uni_name, 0, (size_t)max_uni_len);
		glGetActiveUniform(shd_obj.program, uniform, max_uni_len-1, nullptr, &var_size, &var_type, uni_name);
		var_location = glGetUniformLocation(shd_obj.program, uni_name);
		if(var_location < 0) {
			if(print_debug_info) log_error("Warning: could not get location for uniform \"%s\" in shader #%s/%s!", uni_name, identifier, option);
			continue;
		}
		if(print_debug_info) log_undecorated("uniform #%u: %s", var_location, uni_name);
		string uniform_name = uni_name;
		if(uniform_name.find("[") != string::npos) uniform_name = uniform_name.substr(0, uniform_name.find("["));
		shd_obj.uniforms.insert(make_pair(uniform_name,
										  shader_object::internal_shader_object::shader_variable((size_t)var_location, (size_t)var_size, var_type)));
		
		// if the uniform is a sampler, add it to the sampler mapping (with increasing id/num)
		if(shader_class::is_gl_sampler_type(var_type)) {
			shd_obj.samplers.insert(make_pair(uniform_name, shd_obj.samplers.size()));
			
			// while we are at it, also set the sampler location to a dummy value (this has to be done to satisfy program validation)
			glUniform1i(var_location, (GLint)shd_obj.samplers.size()-1);
		}
	}
	delete [] uni_name;
	
#if !defined(FLOOR_IOS) || defined(PLATFORM_X64)
	GLchar* uni_block_name = new GLchar[(size_t)max_uni_block_len];
	if(print_debug_info) log_undecorated("GL_ACTIVE_UNIFORM_BLOCKS: %u", uni_block_count);
	for(GLuint block = 0; block < (GLuint)uni_block_count; block++) {
		memset(uni_block_name, 0, (size_t)max_uni_block_len);
		glGetActiveUniformBlockName(shd_obj.program, (GLuint)block, max_uni_block_len-1, nullptr, uni_block_name);
		
		GLuint block_index = glGetUniformBlockIndex(shd_obj.program, uni_block_name);
		if(block_index == GL_INVALID_INDEX) {
			if(print_debug_info) log_error("Warning: could not get index for uniform block \"%s\" in shader #%s/%s!", uni_block_name, identifier, option);
			continue;
		}
		
		GLint data_size = 0;
		glGetActiveUniformBlockiv(shd_obj.program, block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &data_size);
		if(print_debug_info) log_undecorated("uniform block #%u (size: %u): %s",
									 block_index, data_size, uni_block_name);
		const string uniform_block_name = uni_block_name;
		
		shd_obj.blocks.insert(make_pair(uniform_block_name,
										shader_object::internal_shader_object::shader_variable(block_index, (size_t)data_size, GL_UNIFORM_BUFFER)));
		
		// TODO: handle samplers?
	}
	delete [] uni_block_name;
#endif
	
	// validate the program object
	glValidateProgram(shd_obj.program);
	glGetProgramiv(shd_obj.program, GL_VALIDATE_STATUS, &success);
	if(!success) {
		glGetProgramInfoLog(shd_obj.program, A2E_SHADER_LOG_SIZE, nullptr, info_log);
		log_error("Error in program \"%s/%s\" validation!\nInfo log: %s", identifier, option, info_log);
		return 0;
	}
	else {
		glGetProgramInfoLog(shd_obj.program, A2E_SHADER_LOG_SIZE, nullptr, info_log);
		
		// check if shader will run in software (if so, print out a debug message)
		if(strstr((const char*)info_log, (const char*)"software") != nullptr) {
			log_debug("program \"%s/%s\" validation: %s", identifier, option, info_log);
		}
	}
	
	//
	glUseProgram(0);

	return shaders[identifier];
}