/* Link a program with all currently attached shaders */ GLint Shader::LinkProgram(GLuint prog) { GLint status; RENDER_VERIFY(glLinkProgram(prog)); #ifdef __DAVAENGINE_DEBUG__ { GLchar log[4096] = {0}; GLsizei logLength = 0; RENDER_VERIFY(glGetProgramInfoLog(prog, 4096, &logLength, log)); if (logLength) { Logger::FrameworkDebug("Program link log:\n%s", log); } } #endif RENDER_VERIFY(glGetProgramiv(prog, GL_LINK_STATUS, &status)); if (status == GL_FALSE) Logger::Error("Failed to link program %d", prog); return status; }
void Shader::DeleteShadersInternal(BaseObject * caller, void * param, void *callerData) { DeleteShaderContainer * container = (DeleteShaderContainer*) param; DVASSERT(container); RENDER_VERIFY(glDetachShader(container->program, container->vertexShader)); RENDER_VERIFY(glDetachShader(container->program, container->fragmentShader)); RENDER_VERIFY(glDeleteShader(container->vertexShader)); RENDER_VERIFY(glDeleteShader(container->fragmentShader)); RENDER_VERIFY(glDeleteProgram(container->program)); SafeDelete(container); }
void Shader::Dump() { Logger::FrameworkDebug("Attributes: "); for (int32 k = 0; k < activeAttributes; ++k) { int32 flagIndex = GetAttributeIndexByName(attributeNames[k].c_str()); Logger::FrameworkDebug("Attribute: %s location: %d vertexFormatIndex:%x", attributeNames[k].c_str(), vertexFormatAttribIndeces[flagIndex], flagIndex); } RENDER_VERIFY(glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms)); Logger::FrameworkDebug("Uniforms: "); for (int32 k = 0; k < activeUniforms; ++k) { Uniform* currentUniform = GET_UNIFORM(k); //Logger::FrameworkDebug("shader uniform: %s size: %d type: %s", attributeName, size, VertexTypeStringFromEnum(type).c_str()); // uniformNames[k] = attributeName; // uniformLocations[k] = glGetUniformLocation(program, uniformNames[k].c_str()); // uniformIDs[k] = uniform; // uniformTypes[k] = (eUniformType)type; eUniform uniform = GetUniformByName(currentUniform->name.c_str()); Logger::FrameworkDebug("uniform: %s(%d) type: %s", currentUniform->name.c_str(), uniform, VertexTypeStringFromEnum(currentUniform->type).c_str()); } }
void Shader::Unbind() { if (activeProgram != 0) { RENDER_VERIFY(glUseProgram(0)); activeProgram = 0; } }
/* Create and compile a shader from the provided source(s) */ GLint Shader::CompileShader(GLuint *shader, GLenum type, GLint count, const GLchar * sources, const String & defines) { GLint status; //const GLchar *sources; *shader = glCreateShader(type); // create shader if (defines.length() == 0) { RENDER_VERIFY(glShaderSource(*shader, 1, &sources, &count)); // set source code in the shader }else { const GLchar * multipleSources[] = { defines.c_str(), sources, }; const GLint multipleCounts[] = { (GLint)defines.length(), count, }; RENDER_VERIFY(glShaderSource(*shader, 2, multipleSources, multipleCounts)); // set source code in the shader } RENDER_VERIFY(glCompileShader(*shader)); // compile shader #ifdef __DAVAENGINE_DEBUG__ { GLchar log[4096] = {0}; GLsizei logLength = 0; RENDER_VERIFY(glGetShaderInfoLog(*shader, 4096, &logLength, log)); if (logLength) { Logger::FrameworkDebug("Shader compile log:\n%s", log); } } #endif RENDER_VERIFY(glGetShaderiv(*shader, GL_COMPILE_STATUS, &status)); if (status == GL_FALSE) { Logger::Error("Failed to compile shader: status == GL_FALSE\n"); } return status; }
void Shader::SetUniformValueByIndex(int32 uniformIndex, const Matrix3 & matrix) { DVASSERT(uniformIndex >= 0 && uniformIndex < activeUniforms); Uniform* currentUniform = GET_UNIFORM(uniformIndex); if(currentUniform->ValidateCache(matrix) == false) { RENDER_VERIFY(glUniformMatrix3fv(currentUniform->location, 1, GL_FALSE, matrix.data)); } }
void Shader::SetUniformValueByIndex(int32 uniformIndex, const Vector4 & vector) { DVASSERT(uniformIndex >= 0 && uniformIndex < activeUniforms); Uniform* currentUniform = GET_UNIFORM(uniformIndex); if(currentUniform->ValidateCache(vector) == false) { RENDER_VERIFY(glUniform4fv(currentUniform->location, 1, &vector.x)); } }
void Shader::SetUniformColor4ByIndex(int32 uniformIndex, const Color & color) { DVASSERT(uniformIndex >= 0 && uniformIndex < activeUniforms); Uniform* currentUniform = GET_UNIFORM(uniformIndex); if(currentUniform->ValidateCacheColor4(color) == false) { RENDER_VERIFY(glUniform4fv(currentUniform->location, 1, &color.r)); } }
void Shader::SetUniformValueByIndex(int32 uniformIndex, float32 value) { DVASSERT(uniformIndex >= 0 && uniformIndex < activeUniforms); Uniform* currentUniform = GET_UNIFORM(uniformIndex); if(currentUniform->ValidateCache(value) == false) { RENDER_VERIFY(glUniform1f(currentUniform->location, value)); } }
void Shader::Bind() { if (activeProgram != program) { RENDER_VERIFY(glUseProgram(program)); activeProgram = program; } for (int32 k = 0; k < activeUniforms; ++k) { Uniform* currentUniform = GET_UNIFORM(k); switch (currentUniform->id) { case UNIFORM_MODEL_VIEW_PROJECTION_MATRIX: { const Matrix4 & modelViewProj = RenderManager::Instance()->GetUniformMatrix(RenderManager::UNIFORM_MATRIX_MODELVIEWPROJECTION); SetUniformValueByIndex(k, modelViewProj); break; } case UNIFORM_MODEL_VIEW_MATRIX: { const Matrix4 & modelView = RenderManager::Instance()->GetMatrix(RenderManager::MATRIX_MODELVIEW); SetUniformValueByIndex(k, modelView); break; } case UNIFORM_PROJECTION_MATRIX: { const Matrix4 & proj = RenderManager::Instance()->GetMatrix(RenderManager::MATRIX_PROJECTION); SetUniformValueByIndex(k, proj); break; } case UNIFORM_NORMAL_MATRIX: { const Matrix3 & normalMatrix = RenderManager::Instance()->GetNormalMatrix(); SetUniformValueByIndex(k, normalMatrix); break; } case UNIFORM_COLOR: { const Color & c = RenderManager::Instance()->GetColor(); SetUniformColor4ByIndex(k, c); break; } case UNIFORM_GLOBAL_TIME: { float32 globalTime = SystemTimer::Instance()->GetGlobalTime(); SetUniformValueByIndex(k, globalTime); }; default: break; } } }
void Texture::SetAsHardwareCursor(const Vector2 & hotSpot) { if (id) { LPDIRECT3DSURFACE9 textureMainSurface; HRESULT hr = id->GetSurfaceLevel(0, &textureMainSurface); RENDER_VERIFY(hr); // Check surface format // D3DSURFACE_DESC desc; ZeroMemory(&desc, sizeof(desc)); RENDER_VERIFY(textureMainSurface->GetDesc(&desc)); LPDIRECT3DDEVICE9 device = RenderManager::Instance()->GetD3DDevice(); hr = device->SetCursorProperties((UINT)hotSpot.x, (UINT)hotSpot.y, textureMainSurface); RENDER_VERIFY(hr); D3DSafeRelease(textureMainSurface); } }
void Texture::Invalidate() { if (isRenderTarget) { LPDIRECT3DDEVICE9 device = RenderManager::Instance()->GetD3DDevice(); id = CreateTextureNative(Vector2((float32)width, (float32)height), format, isRenderTarget, 0); if (saveTexture) { //Logger::FrameworkDebug("Restoring lost render target with path: %s size: %d x %d", relativePathname.c_str(), width, height); /* We add dirty rect because without it UpdateTexture updates texture only once. */ RENDER_VERIFY(saveTexture->AddDirtyRect(0)); RENDER_VERIFY(device->UpdateTexture(saveTexture, id)); // Here we do not release texture because after update we still should have it for future restores in case of fail of render device //D3DSafeRelease(saveTexture); } } }
void NMaterialInstance::BindUniforms() { for (uint32 uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex) { Shader::eUniformType uniformType = shader->GetUniformType(uniformIndex); UniformInfo uniformInfo = uniforms[uniformIndex]; if (uniformInfo.flags & SKIP_UNIFORM)continue; // Logger::Debug("Bind uniform: %s", shader->GetUniformName(uniformIndex).c_str()); uint8 * data = &uniformData[uniformInfo.shift]; switch(uniformType) { case Shader::UT_FLOAT: RENDER_VERIFY(glUniform1fv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (float*)data)); break; case Shader::UT_FLOAT_VEC2: RENDER_VERIFY(glUniform2fv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (float*)data)); break; case Shader::UT_FLOAT_VEC3: RENDER_VERIFY(glUniform3fv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (float*)data)); break; case Shader::UT_FLOAT_VEC4: RENDER_VERIFY(glUniform4fv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (float*)data)); break; case Shader::UT_INT: RENDER_VERIFY(glUniform1iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_INT_VEC2: RENDER_VERIFY(glUniform2iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_INT_VEC3: RENDER_VERIFY(glUniform3iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_INT_VEC4: RENDER_VERIFY(glUniform4iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_BOOL: RENDER_VERIFY(glUniform1iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_BOOL_VEC2: RENDER_VERIFY(glUniform2iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_BOOL_VEC3: RENDER_VERIFY(glUniform3iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_BOOL_VEC4: RENDER_VERIFY(glUniform4iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_FLOAT_MAT2: RENDER_VERIFY(glUniformMatrix2fv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, GL_FALSE, (float32*)data)); break; case Shader::UT_FLOAT_MAT3: RENDER_VERIFY(glUniformMatrix3fv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, GL_FALSE, (float32*)data)); break; case Shader::UT_FLOAT_MAT4: RENDER_VERIFY(glUniformMatrix4fv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, GL_FALSE, (float32*)data)); break; case Shader::UT_SAMPLER_2D: RENDER_VERIFY(glUniform1iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; case Shader::UT_SAMPLER_CUBE: RENDER_VERIFY(glUniform1iv(shader->GetUniformLocation(uniformIndex), uniformInfo.arraySize, (int32*)data)); break; }; } }
void Texture::SaveToSystemMemory() { if (isRenderTarget) { /* Do not save texture if autosave flag is false */ if (!renderTargetAutosave) return; HRESULT hr = RenderManager::Instance()->GetD3DDevice()->TestCooperativeLevel(); if (hr == D3DERR_DEVICELOST) { //if (!saveTexture) //Logger::FrameworkDebug("Trying to save to system memory rendertarget that was not saved before"); return; } // Render manager set this flag when you set sprite as render target. if (!renderTargetModified) return; // Release should be after check that renderTargetModified. D3DSafeRelease(saveTexture); LPDIRECT3DDEVICE9 device = RenderManager::Instance()->GetD3DDevice(); D3DSURFACE_DESC desc; id->GetLevelDesc(0, &desc); //Logger::FrameworkDebug("Saving render target to system memory: %s size: %d x %d format:%d", relativePathname.c_str(), width, height, desc.Format); /* HRESULT hr = device->CreateOffscreenPlainSurface(width, height, desc.Format, D3DPOOL_SYSTEMMEM, &saveSurface, NULL); DX_VERIFY(hr); */ hr = device->CreateTexture(width, height, 1/*means we create texture with 1 mipmap level*/, 0, desc.Format, D3DPOOL_SYSTEMMEM, &saveTexture, 0); RENDER_VERIFY(hr); LPDIRECT3DSURFACE9 renderTargetMainSurface; hr = id->GetSurfaceLevel(0, &renderTargetMainSurface); RENDER_VERIFY(hr); LPDIRECT3DSURFACE9 saveTextureMainSurface; hr = saveTexture->GetSurfaceLevel(0, &saveTextureMainSurface); RENDER_VERIFY(hr); hr = device->GetRenderTargetData(renderTargetMainSurface, saveTextureMainSurface); RENDER_VERIFY(hr); renderTargetModified = false; #if 0 //Image * image = new Image(); Image * image = image->Create(width, height, FORMAT_RGBA8888); D3DLOCKED_RECT rect; hr = saveTexture->LockRect(0, &rect, 0, 0); if (FAILED(hr)) { Logger::Error("[TextureDX9] Could not lock DirectX9 Texture."); return; } int32 pixelSizeInBits = GetPixelFormatSize(format); if (format == FORMAT_RGBA8888) { //int32 pitchInBytes = uint8 * destBits = (uint8*)image->GetData(); uint8 * sourceBits = (uint8*)rect.pBits; for (uint32 h = 0; h < height * width; ++h) { uint32 b = sourceBits[0]; uint32 g = sourceBits[1]; uint32 r = sourceBits[2]; uint32 a = sourceBits[3]; destBits[0] = (uint8)r; //sourceBits[3]; destBits[1] = (uint8)g; //sourceBits[0]; destBits[2] = (uint8)b;//sourceBits[1]; destBits[3] = (uint8)a; destBits += 4; sourceBits += 4; } } saveTexture->UnlockRect(0); image->Save(Format("FBO\\%s.png", relativePathname.c_str())); SafeRelease(image); #endif D3DSafeRelease(renderTargetMainSurface); D3DSafeRelease(saveTextureMainSurface); } }
void Shader::RecompileInternal(BaseObject * caller, void * param, void *callerData) { DVASSERT((vertexShader == 0) && (fragmentShader == 0) && (program == 0)); if (!CompileShader(&vertexShader, GL_VERTEX_SHADER, vertexShaderData->GetSize(), (GLchar*)vertexShaderData->GetPtr(), vertexShaderDefines)) { Logger::Error("Failed to compile vertex shader: %s", vertexShaderPath.GetAbsolutePathname().c_str()); return; } if (!CompileShader(&fragmentShader, GL_FRAGMENT_SHADER, fragmentShaderData->GetSize(), (GLchar*)fragmentShaderData->GetPtr(), fragmentShaderDefines)) { Logger::Error("Failed to compile fragment shader: %s", fragmentShaderPath.GetAbsolutePathname().c_str()); return; } program = glCreateProgram(); RENDER_VERIFY(glAttachShader(program, vertexShader)); RENDER_VERIFY(glAttachShader(program, fragmentShader)); if (!LinkProgram(program)) { Logger::Error("Failed to Link program for shader: %s", fragmentShaderPath.GetAbsolutePathname().c_str()); DeleteShaders(); return; } RENDER_VERIFY(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttributes)); char attributeName[512]; attributeNames = new FastName[activeAttributes]; for (int32 k = 0; k < activeAttributes; ++k) { GLint size; GLenum type; RENDER_VERIFY(glGetActiveAttrib(program, k, 512, 0, &size, &type, attributeName)); attributeNames[k] = attributeName; int32 flagIndex = GetAttributeIndexByName(attributeName); vertexFormatAttribIndeces[flagIndex] = glGetAttribLocation(program, attributeName); } RENDER_VERIFY(glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms)); SafeDeleteArray(uniformOffsets); SafeDeleteArray(uniformData); int32 totalSize = 0; uniformOffsets = new uint16[activeUniforms]; for (int32 k = 0; k < activeUniforms; ++k) { GLint size; GLenum type; RENDER_VERIFY(glGetActiveUniform(program, k, 512, 0, &size, &type, attributeName)); uniformOffsets[k] = (uint16)totalSize; int32 uniformDataSize = GetUniformTypeSize((eUniformType)type); totalSize += sizeof(Uniform) + (uniformDataSize * size); } uniformData = new uint8[totalSize]; for (int32 k = 0; k < activeUniforms; ++k) { GLint size = 0; GLenum type = 0; RENDER_VERIFY(glGetActiveUniform(program, k, 512, 0, &size, &type, attributeName)); Uniform* uniformStruct = GET_UNIFORM(k); new (&uniformStruct->name) FastName(); //VI: FastName is not a POD so a constructor should be called eUniform uniform = GetUniformByName(attributeName); uniformStruct->name = attributeName; uniformStruct->location = glGetUniformLocation(program, uniformStruct->name.c_str()); uniformStruct->id = uniform; uniformStruct->type = (eUniformType)type; uniformStruct->size = size; uniformStruct->cacheValueSize = GetUniformTypeSize((eUniformType)type) * size; uniformStruct->cacheValue = uniformData + uniformOffsets[k] + sizeof(Uniform); //VI: initialize cacheValue with value from shader switch(uniformStruct->type) { case UT_FLOAT: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); break; } case UT_FLOAT_VEC2: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); break; } case UT_FLOAT_VEC3: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); break; } case UT_FLOAT_VEC4: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); break; } case UT_INT: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_INT_VEC2: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_INT_VEC3: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_INT_VEC4: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_BOOL: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_BOOL_VEC2: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_BOOL_VEC3: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_BOOL_VEC4: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } //VI: Matrices are returned from the shader in column-major order so need to transpose the matrix. case UT_FLOAT_MAT2: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); Matrix2* m = (Matrix2*)uniformStruct->cacheValue; Matrix2 t; for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j) t._data[i][j] = m->_data[j][i]; *m = t; break; } case UT_FLOAT_MAT3: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); Matrix3* m = (Matrix3*)uniformStruct->cacheValue; Matrix3 t; for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) t._data[i][j] = m->_data[j][i]; *m = t; break; } case UT_FLOAT_MAT4: { RENDER_VERIFY(glGetUniformfv(program, uniformStruct->location, (float32*)uniformStruct->cacheValue)); Matrix4* m = (Matrix4*)uniformStruct->cacheValue; m->Transpose(); break; } case UT_SAMPLER_2D: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } case UT_SAMPLER_CUBE: { RENDER_VERIFY(glGetUniformiv(program, uniformStruct->location, (int32*)uniformStruct->cacheValue)); break; } } } }