Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2019
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.46 KB | None | 0 0
  1. #include "gpu_program_opengl.h"
  2.  
  3. namespace eq {
  4.  
  5. namespace render {
  6.  
  7. namespace gl {
  8.  
  9. GPUProgramOpenGL::GPUProgramOpenGL(std::shared_ptr<const GLContext> gl_context,
  10.     std::shared_ptr<const GLContext> gl_context_aux,
  11.     std::shared_ptr<Synchronized<resource::ResourceManager<GLShaderGLSL>>> gl_shader_glsl_manager) :
  12.     m_gl_context(gl_context), m_gl_context_aux(gl_context_aux),
  13.     m_gl_shader_glsl_manager(gl_shader_glsl_manager) {
  14.    
  15.     std::unique_lock contextLock(*m_gl_context_aux, std::defer_lock);
  16.     if (m_gl_context->GetHandle() != GLContext::GetCurrent())
  17.         contextLock.lock();
  18.  
  19.     const_cast<std::unique_ptr<const GLProgram>&>(m_gl_program) = std::make_unique<GLProgram>();
  20. }
  21.  
  22. GPUProgramOpenGL::~GPUProgramOpenGL() {
  23.  
  24.     std::unique_lock contextLock(*m_gl_context_aux, std::defer_lock);
  25.     if (m_gl_context->GetHandle() != GLContext::GetCurrent())
  26.         contextLock.lock();
  27.  
  28.     const_cast<std::unique_ptr<const GLProgram>&>(m_gl_program).reset();
  29. }
  30.  
  31. void GPUProgramOpenGL::SetUniformData(const UniformData& uniform_data)  {
  32.  
  33.     GLint current_program = 0;
  34.     GL_ASSERT(glGetIntegerv(GL_CURRENT_PROGRAM, &current_program))
  35.     if (m_gl_program->GetProgram() != current_program)
  36.         GL_ASSERT(glUseProgram(m_gl_program->GetProgram()))
  37.  
  38.     SetUniform(uniform_data.uniform, (void*)uniform_data.data.data());
  39. }
  40.  
  41. void GPUProgramOpenGL::SetUniformData(const std::vector<UniformData>& uniform_data_vector)  {
  42.  
  43.     GLint current_program = 0;
  44.     GL_ASSERT(glGetIntegerv(GL_CURRENT_PROGRAM, &current_program))
  45.     if (m_gl_program->GetProgram() != current_program)
  46.         GL_ASSERT(glUseProgram(m_gl_program->GetProgram()))
  47.  
  48.     for (const auto& uniform_data : uniform_data_vector)
  49.         SetUniform(uniform_data.uniform, (void*)uniform_data.data.data());
  50. }
  51.  
  52. void GPUProgramOpenGL::SetUniformData(const UniformDataView& uniform_data_view) {
  53.  
  54.     GLint current_program = 0;
  55.     GL_ASSERT(glGetIntegerv(GL_CURRENT_PROGRAM, &current_program))
  56.     if (m_gl_program->GetProgram() != current_program)
  57.         GL_ASSERT(glUseProgram(m_gl_program->GetProgram()))
  58.  
  59.     SetUniform(uniform_data_view.uniform, uniform_data_view.data);
  60. }
  61.  
  62. void GPUProgramOpenGL::SetUniformData(const std::vector<UniformDataView>& uniform_data_view_vector) {
  63.  
  64.     GLint current_program = 0;
  65.     GL_ASSERT(glGetIntegerv(GL_CURRENT_PROGRAM, &current_program))
  66.     if (m_gl_program->GetProgram() != current_program)
  67.         GL_ASSERT(glUseProgram(m_gl_program->GetProgram()))
  68.  
  69.     for (const auto& uniform_data_view : uniform_data_view_vector)
  70.         SetUniform(uniform_data_view.uniform, uniform_data_view.data);
  71. }
  72.  
  73. void GPUProgramOpenGL::SetUniformBuffer(const std::shared_ptr<UniformBuffer> uniform_buffer, size_t offset, size_t size) {
  74.  
  75.     GLint current_program = 0;
  76.     GL_ASSERT(glGetIntegerv(GL_CURRENT_PROGRAM, &current_program))
  77.     if (m_gl_program->GetProgram() != current_program)
  78.         GL_ASSERT(glUseProgram(m_gl_program->GetProgram()))
  79.  
  80.     GLuint binding = 0;
  81.  
  82.     for (auto& uniform_block : m_uniform_block_map) {
  83.         if (uniform_block.second.name == uniform_buffer->GetUniformBlock().name) {
  84.             auto visitor = std::make_unique<MemoryBufferVisitorSetActive>(m_gl_context.get(), GL_UNIFORM_BUFFER, binding, 0, size ? size : uniform_buffer->GetMemoryBuffer()->GetSize());
  85.             uniform_buffer->GetMemoryBuffer()->Accept(visitor.get());
  86.             GL_ASSERT(glUniformBlockBinding(m_gl_program->GetProgram(), uniform_block.second.id, binding))
  87.         }
  88.         binding++;
  89.     }
  90. }
  91.  
  92. void GPUProgramOpenGL::SetUniformBuffer(const std::vector<std::shared_ptr<UniformBuffer>>& uniformBufferVector) {
  93.     for (auto& uniformBuffer : uniformBufferVector)
  94.         SetUniformBuffer(uniformBuffer);
  95. }
  96.  
  97. void GPUProgramOpenGL::SetUniformData(const UniformGroup& uniformGroup) {
  98.     SetUniformData(uniformGroup.uniform_data_vector);
  99.     SetUniformData(uniformGroup.uniform_data_view_vector);
  100.     SetUniformBuffer(uniformGroup.uniform_buffer_vector);
  101. }
  102.  
  103. void GPUProgramOpenGL::Load(const resource::ResourceName& resource_name) {
  104.  
  105.     GPUProgram::Load(resource_name);
  106.  
  107.     auto istream = SingletonFilesystem::GetInstance()->Get().MakeUniqueIstream(resource_name.filename);
  108.  
  109.     std::istreambuf_iterator<char> eos;
  110.     std::string xml_text(std::istreambuf_iterator<char>(*istream), eos);
  111.  
  112.     rapidxml::xml_document<> xml_doc;
  113.     xml_doc.parse<0>(const_cast<char*>(xml_text.c_str()));
  114.  
  115.     auto xml_root_node = xml_doc.first_node();
  116.  
  117.     std::map<GLenum, std::vector<std::string>> shader_names_map;
  118.  
  119.     std::string_view xml_root_node_name(xml_root_node->name());
  120.  
  121.     if (xml_root_node_name == "GPUProgram") {
  122.  
  123.         auto xml_program_node = xml_root_node->first_node("Program");
  124.         if (xml_program_node) {
  125.  
  126.             auto xml_opengl_node = xml_program_node->first_node("OpenGL");
  127.             if (xml_opengl_node) {
  128.  
  129.                 auto xml_glsl_node = xml_opengl_node->first_node("GLSL");
  130.                 if (xml_glsl_node) {
  131.  
  132.                     for (auto xml_glsl_child_node = xml_glsl_node->first_node(); xml_glsl_child_node; xml_glsl_child_node = xml_glsl_child_node->next_sibling()) {
  133.  
  134.                         std::string_view xml_glsl_child_node_name(xml_glsl_child_node->name());
  135.  
  136.                         if (xml_glsl_child_node_name == "VertexShader") {
  137.                             auto xml_name_attribute = xml_glsl_child_node->first_attribute("name");
  138.                             if (xml_name_attribute)
  139.                                 shader_names_map[GL_VERTEX_SHADER].push_back(xml_name_attribute->value());
  140.                         }
  141.                         else if (xml_glsl_child_node_name == "FragmentShader") {
  142.                             auto xml_name_attribute = xml_glsl_child_node->first_attribute("name");
  143.                             if (xml_name_attribute)
  144.                                 shader_names_map[GL_FRAGMENT_SHADER].push_back(xml_name_attribute->value());
  145.                         }
  146.                         else if (xml_glsl_child_node_name == "GeometryShader") {
  147.                             auto xml_name_attribute = xml_glsl_child_node->first_attribute("name");
  148.                             if (xml_name_attribute)
  149.                                 shader_names_map[GL_GEOMETRY_SHADER].push_back(xml_name_attribute->value());
  150.                         }
  151.                         else if (xml_glsl_child_node_name == "TesselationControlShader") {
  152.                             auto xml_name_attribute = xml_glsl_child_node->first_attribute("name");
  153.                             if (xml_name_attribute)
  154.                                 shader_names_map[GL_TESS_CONTROL_SHADER].push_back(xml_name_attribute->value());
  155.                         }
  156.                         else if (xml_glsl_child_node_name == "TesselationEvaluationShader") {
  157.                             auto xml_name_attribute = xml_glsl_child_node->first_attribute("name");
  158.                             if (xml_name_attribute)
  159.                                 shader_names_map[GL_TESS_EVALUATION_SHADER].push_back(xml_name_attribute->value());
  160.                         }
  161.                     }
  162.                 }
  163.             }
  164.         }
  165.     }
  166.  
  167.     auto gl_shader_glsl_manager = m_gl_shader_glsl_manager.lock();
  168.  
  169.     if (gl_shader_glsl_manager) {
  170.  
  171.         for (const auto& shader_names : shader_names_map) {
  172.             for (const auto& shader_name : shader_names.second) {
  173.  
  174.                 resource::ResourceFuture<GLShaderGLSL> gl_shader_resource;
  175.  
  176.                 {
  177.                     std::lock_guard<typename std::decay<decltype(gl_shader_glsl_manager->GetLockable())>::type> manager_lock(gl_shader_glsl_manager->GetLockable());
  178.                     gl_shader_resource = gl_shader_glsl_manager->Get().GetResource({
  179.                         std::wstring(std::begin(shader_name), std::end(shader_name)) },
  180.                         std::make_tuple(m_gl_context, m_gl_context_aux, shader_names.first));
  181.                 }
  182.  
  183.                 std::unique_lock context_lock(*m_gl_context_aux, std::defer_lock);
  184.                 if (m_gl_context->GetHandle() != GLContext::GetCurrent())
  185.                     context_lock.lock();
  186.  
  187.                 m_gl_program->AttachShader(gl_shader_resource.get()->GetShader());
  188.             }
  189.         }
  190.  
  191.         std::unique_lock context_lock(*m_gl_context_aux, std::defer_lock);
  192.         if (m_gl_context->GetHandle() != GLContext::GetCurrent())
  193.             context_lock.lock();
  194.  
  195.         std::string link_log;
  196.         auto linkResult = m_gl_program->Link(link_log);
  197.  
  198.         for (auto attribute : m_vertex_attributes_layout_in.attributes) {
  199.             if (attribute.first.id == -1) {
  200.                 GL_ASSERT(attribute.first.id = glGetAttribLocation(m_gl_program->GetProgram(), attribute.first.name.c_str()))
  201.             }
  202.         }
  203.  
  204.         std::sort(m_vertex_attributes_layout_in.attributes.begin(), m_vertex_attributes_layout_in.attributes.end(),
  205.             [](const std::pair<VertexAttribute, size_t>& a1, const std::pair<VertexAttribute, size_t>& a2) { return a1.first.id < a2.first.id; });
  206.  
  207.         for (auto& uniform : m_uniform_map) {
  208.             if (uniform.second.id == -1) {
  209.                 GL_ASSERT(uniform.second.id = glGetUniformLocation(m_gl_program->GetProgram(), uniform.second.name.c_str()))
  210.                 if (uniform.second.id == -1) {
  211.                     auto logger = SingletonLogger::GetInstance();
  212.                     std::lock_guard<typename std::decay<decltype(logger->GetLockable())>::type> logger_lock(logger->GetLockable());
  213.                     logger->Get().LogMessage({ LoggerMessageType::WARNING, L"Uniform variable [" + std::wstring(std::begin(uniform.second.name),std::end(uniform.second.name)) + L"] was not found in " + resource_name.filename + L" GLSL Program" });
  214.                 }
  215.                 /*
  216.                 else {
  217.                     GLsizei length = 0; GLint size = 0; GLenum type = 0;
  218.                     GLchar name[256];
  219.                     glGetActiveUniform(m_glProgram->GetProgram(), uniform.id, 256, &length, &size, &type, name);
  220.                 }
  221.                 */
  222.             }
  223.         }
  224.  
  225.         for (auto& uniform_block : m_uniform_block_map) {
  226.  
  227.             if (uniform_block.second.id == -1)
  228.                 GL_ASSERT(uniform_block.second.id = glGetUniformBlockIndex(m_gl_program->GetProgram(), uniform_block.second.name.c_str()))
  229.  
  230.             if (uniform_block.second.id == -1) {
  231.                 auto logger = SingletonLogger::GetInstance();
  232.                 std::lock_guard<typename std::decay<decltype(logger->GetLockable())>::type> logger_lock(logger->GetLockable());
  233.                 logger->Get().LogMessage({ LoggerMessageType::WARNING, L"UniformBlock variable [" + std::wstring(std::begin(uniform_block.second.name),std::end(uniform_block.second.name)) + L"] was not found in " + resource_name.filename + L" GLSL Program" });
  234.             }
  235.  
  236.             else {
  237.                 GLint size;
  238.                 GL_ASSERT(glGetActiveUniformBlockiv(m_gl_program->GetProgram(), uniform_block.second.id, GL_UNIFORM_BLOCK_DATA_SIZE, &size))
  239.                 uniform_block.second.size = size;
  240.  
  241.                 for (auto& uniform : uniform_block.second.uniform_map) {
  242.                     GLuint index;
  243.                     std::string name = uniform_block.second.name + "." + uniform.second.first.name;
  244.                     auto np = name.c_str();
  245.                     GL_ASSERT(glGetUniformIndices(m_gl_program->GetProgram(), 1, &np, &index))
  246.  
  247.                     uniform.second.first.id = index;
  248.                     GLint offset;
  249.                     GL_ASSERT(glGetActiveUniformsiv(m_gl_program->GetProgram(), 1, &index, GL_UNIFORM_OFFSET, &offset))
  250.                     uniform.second.second = offset;
  251.                 }          
  252.             }
  253.         }
  254.  
  255.         auto logger = SingletonLogger::GetInstance();
  256.         std::lock_guard<typename std::decay<decltype(logger->GetLockable())>::type> logger_lock(logger->GetLockable());
  257.  
  258.         if (linkResult)
  259.             logger->Get().LogMessage({ LoggerMessageType::INFORMATION, L"GLSL Program " + resource_name.filename + L" linked successfully." });
  260.         else
  261.             logger->Get().LogMessage({ LoggerMessageType::WARNING, L"GLSL Program " + resource_name.filename + L" failed to link. Linking error : \n" + std::wstring(std::begin(link_log), std::end(link_log)) });
  262.     }
  263. }
  264.  
  265. std::shared_ptr<const GLContext> GPUProgramOpenGL::GetGLContext() const {
  266.  
  267.     return m_gl_context;
  268. }
  269.  
  270. const GLProgram* GPUProgramOpenGL::GetGLProgram() const {
  271.  
  272.     return m_gl_program.get();
  273. }
  274.  
  275. void GPUProgramOpenGL::SetUniform(const Uniform& uniform, void* data) {
  276.  
  277.     GLint location = uniform.id;
  278.     if (uniform.id == -1)
  279.         GL_ASSERT(location = glGetUniformLocation(m_gl_program->GetProgram(), uniform.name.c_str()))
  280.  
  281.     if (location != -1) {
  282.  
  283.         switch (uniform.type) {
  284.  
  285.         case UniformType::INT32:
  286.             GL_ASSERT(glUniform1iv(location, (GLsizei)uniform.count, reinterpret_cast<const GLint*>(data)))
  287.             break;
  288.         case UniformType::FLOAT:
  289.             GL_ASSERT(glUniform1fv(location, (GLsizei)uniform.count, reinterpret_cast<const GLfloat*>(data)))
  290.             break;
  291.         case UniformType::VEC2INT32:
  292.             GL_ASSERT(glUniform2iv(location, (GLsizei)uniform.count, reinterpret_cast<const GLint*>(data)))
  293.             break;
  294.         case UniformType::VEC2FLOAT:
  295.             GL_ASSERT(glUniform2fv(location, (GLsizei)uniform.count, reinterpret_cast<const GLfloat*>(data)))
  296.             break;
  297.         case UniformType::VEC3INT32:
  298.             GL_ASSERT(glUniform3iv(location, (GLsizei)uniform.count, reinterpret_cast<const GLint*>(data)))
  299.             break;
  300.         case UniformType::VEC3FLOAT:
  301.             GL_ASSERT(glUniform3fv(location, (GLsizei)uniform.count, reinterpret_cast<const GLfloat*>(data)))
  302.             break;
  303.         case UniformType::VEC4INT32:
  304.             GL_ASSERT(glUniform4iv(location, (GLsizei)uniform.count, reinterpret_cast<const GLint*>(data)))
  305.             break;
  306.         case UniformType::VEC4FLOAT:
  307.             GL_ASSERT(glUniform4fv(location, (GLsizei)uniform.count, reinterpret_cast<const GLfloat*>(data)))
  308.             break;
  309.         case UniformType::MAT3:
  310.             GL_ASSERT(glUniformMatrix3fv(location, (GLsizei)uniform.count, GL_FALSE, reinterpret_cast<const GLfloat*>(data)))
  311.             break;
  312.         case UniformType::MAT4:
  313.             GL_ASSERT(glUniformMatrix4fv(location, (GLsizei)uniform.count, GL_FALSE, reinterpret_cast<const GLfloat*>(data)))
  314.             break;
  315.         }
  316.     }
  317. }
  318.  
  319. void GPUProgramOpenGL::MemoryBufferVisitorSetActive::Visit(MemoryBuffer* memory_buffer) {
  320.  
  321.  
  322. }
  323.  
  324. void GPUProgramOpenGL::MemoryBufferVisitorSetActive::Visit(sr::MemoryBufferSoftware* memory_buffer) {
  325.  
  326. }
  327.  
  328. void GPUProgramOpenGL::MemoryBufferVisitorSetActive::Visit(MemoryBufferOpenGL* memory_buffer) {
  329.     if (memory_buffer->GetGLContext().get() == m_gl_context) {
  330.  
  331.         GLenum pname;
  332.  
  333.         switch (m_target) {
  334.         case GL_UNIFORM_BUFFER:
  335.             pname = GL_UNIFORM_BUFFER_BINDING;
  336.             break;
  337.         default:
  338.             assert(false);
  339.         }
  340.  
  341.         GLuint buffer;
  342.         GL_ASSERT(glGetIntegeri_v(pname, m_index, (GLint*)&buffer))
  343.  
  344.         if (buffer != memory_buffer->GetGLBuffer()->GetBuffer())
  345.             //GL_ASSERT(glBindBufferBase(m_target, m_index, memoryBuffer->GetGLBuffer()->GetBuffer()));
  346.             GL_ASSERT(glBindBufferRange(m_target, m_index, memory_buffer->GetGLBuffer()->GetBuffer(), m_offset, m_size))
  347.     }
  348. }
  349.  
  350. } // namespace gl
  351.  
  352. } // namespace render
  353.  
  354. } // namespace eq
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement