inline void draw(const Pack & pack) { drawArraysInstanced( pack.mode, pack.first, pack.count, pack.primcount ); }
void DrawExecution::perform() { m_glStateManager.enableTextureCubeMapSeamless(true); // Apply State applyDepthState(); applyBlendState(); applyCullState(); applyRasterizerState(); applyStencilState(); applyViewport(); gl::glUseProgram(m_drawImpl.program->glProgramName); // Setup texture units for (auto b = 0u; b < m_drawImpl.samplers.size(); b++) { auto & sampler = m_drawImpl.samplers[b]; auto * texture = sampler.texture; Assert(texture, ""); if (texture->glName == 0) { texture->allocate(); } gl::glActiveTexture(gl::GL_TEXTURE0 + b); gl::glBindTexture(texture->type, texture->glName); gl::glTexParameteri(texture->type, gl::GL_TEXTURE_BASE_LEVEL, texture->baseLevel); gl::glTexParameteri(texture->type, gl::GL_TEXTURE_MAX_LEVEL, texture->maxLevel); gl::glBindSampler(b, sampler.glSampler.name()); gl::glSamplerParameteri(sampler.glSampler.name(), gl::GL_TEXTURE_MIN_FILTER, (gl::GLint)texture->minFilter); gl::glSamplerParameteri(sampler.glSampler.name(), gl::GL_TEXTURE_MAG_FILTER, (gl::GLint)texture->maxFilter); gl::glUniform1i(sampler.location, b); } // Setup RenderTarget / Framebuffer Assert(m_drawImpl.framebuffer.m_impl.get(), ""); m_drawImpl.framebuffer.m_impl->bind(m_glStateManager); // Set uniforms { /* TODO Port to GLStateManager */ for (auto & uniform : m_drawImpl.uniforms) { Assert(uniform.isAssigned, "Uniform " + m_drawImpl.program->interface.uniformByLocation(uniform.location)->name() + " not set"); Assert(uniform.count > 0, ""); auto count = uniform.count; auto * data = uniform.blob.ptr(); auto location = uniform.location; switch (TypeToGLType(uniform.type)) { case gl::GL_INT: gl::glUniform1iv(location, count, ((const gl::GLint*)data)); break; case gl::GL_UNSIGNED_INT: gl::glUniform1uiv(location, count, ((const gl::GLuint*)data)); break; case gl::GL_INT_VEC2: { auto idata = (const gl::GLint*)data; gl::glUniform2iv(location, count, idata); break; } case gl::GL_FLOAT: gl::glUniform1fv(location, count, ((const gl::GLfloat*)data)); break; case gl::GL_FLOAT_VEC2: { auto fdata = (const gl::GLfloat*)data; gl::glUniform2fv(location, count, fdata); break; } case gl::GL_FLOAT_VEC3: { auto fdata = (const gl::GLfloat*)data; gl::glUniform3fv(location, count, fdata); break; } case gl::GL_FLOAT_VEC4: { auto fdata = (const gl::GLfloat*)data; gl::glUniform4fv(location, count, fdata); break; } case gl::GL_FLOAT_MAT4: gl::glUniformMatrix4fv(location, count, gl::GL_FALSE, (const gl::GLfloat*)data); break; default: Fail(std::string("Not implemented for type ") + uniform.type.name()); } } } // Set uniform buffers { for (auto b = 0; b < m_drawImpl.uniformBuffers.size(); b++) { auto & binding = m_drawImpl.uniformBuffers[b]; Assert(binding.engaged(), "UniformBuffer " + m_drawImpl.program->interface.uniformBlocks()[b].name() + " not bound"); auto & buffer = *binding.get().buffer; auto size = buffer.count * buffer.layout.stride(); Assert(size > binding.get().begin, "begin beyond buffer bounds"); gl::glUniformBlockBinding(m_drawImpl.program->glProgramName, b, b); gl::glBindBufferRange(gl::GL_UNIFORM_BUFFER, b, buffer.glName, binding.get().begin, buffer.layout.stride()); } } // Dispatch draw if (m_drawImpl.indexBuffer) { if (!m_drawImpl.instanceBuffers.empty()) { drawElementsInstanced(); } else { drawElements(); } } else { if (!m_drawImpl.instanceBuffers.empty()) { drawArraysInstanced(); } else { drawArrays(); } } }