FLightBuffer::FLightBuffer() { mBufferSize = INITIAL_BUFFER_SIZE; mByteSize = mBufferSize * sizeof(float); if (gl.flags & RFL_SHADER_STORAGE_BUFFER) { mBufferType = GL_SHADER_STORAGE_BUFFER; mBlockAlign = 0; mBlockSize = mBufferSize; } else { mBufferType = GL_UNIFORM_BUFFER; mBlockSize = gl.maxuniformblock / 16; if (mBlockSize > 2048) mBlockSize = 2048; // we don't really need a larger buffer mBlockAlign = mBlockSize / 2; } glGenBuffers(1, &mBufferId); glBindBufferBase(mBufferType, LIGHTBUF_BINDINGPOINT, mBufferId); glBindBuffer(mBufferType, mBufferId); // Note: Some older AMD drivers don't do that in glBindBufferBase, as they should. if (gl.flags & RFL_BUFFER_STORAGE) { glBufferStorage(mBufferType, mByteSize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); mBufferPointer = (float*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); } else { glBufferData(mBufferType, mByteSize, NULL, GL_DYNAMIC_DRAW); mBufferPointer = NULL; } Clear(); mLastMappedIndex = UINT_MAX; }
//---------------------------------------------------------------------------// void GpuBufferGL4::create( const GpuBufferCreationParams& clParameters, void* pInitialData /*= nullptr*/ ) { destroy(); ASSERT(clParameters.uElementSizeBytes > 0 && clParameters.uNumElements > 0, "Invalid buffer size specified"); GpuBufferCreationParams* pBaseParams = &m_clParameters; *pBaseParams = clParameters; GLenum eUsageTarget; GLenum eBindingQuery; eUsageTarget = Internal::mapBufferUsage(clParameters.ePrimaryUsageType, eBindingQuery); m_clParameters.eInitialBufferTargetGL = eUsageTarget; m_clParameters.eBindingQueryType = eBindingQuery; uint32 uRequestedAccessFlags = clParameters.uAccessFlags; uint32 uAccessFlagsGL = 0; if ((uRequestedAccessFlags & (uint) GpuResourceAccessFlags::READ) > 0) { uAccessFlagsGL |= GL_MAP_READ_BIT; } if ((uRequestedAccessFlags & (uint) GpuResourceAccessFlags::WRITE) > 0) { uAccessFlagsGL |= GL_MAP_WRITE_BIT; } if ((uRequestedAccessFlags & (uint) GpuResourceAccessFlags::DYNAMIC) > 0) { uAccessFlagsGL |= GL_DYNAMIC_STORAGE_BIT; } if ((uRequestedAccessFlags & (uint) GpuResourceAccessFlags::COHERENT) > 0) { uAccessFlagsGL |= GL_MAP_COHERENT_BIT; } if ((uRequestedAccessFlags & (uint) GpuResourceAccessFlags::PREFER_CPU_STORAGE) > 0) { uAccessFlagsGL |= GL_CLIENT_STORAGE_BIT; } if ((uRequestedAccessFlags & (uint) GpuResourceAccessFlags::PERSISTENT_LOCKABLE) > 0) { uAccessFlagsGL |= GL_MAP_PERSISTENT_BIT; } // Sanity-checks on the access flags (following the OpenGL 4.4 standard) if((uAccessFlagsGL & GL_MAP_PERSISTENT_BIT) > 0 && ((uAccessFlagsGL & GL_MAP_WRITE_BIT) == 0 && (uAccessFlagsGL & GL_MAP_READ_BIT) == 0)) { ASSERT(false, "A persistent buffer without CPU-access doesn't make sense"); } /*if ((uAccessFlagsGL & GL_MAP_COHERENT_BIT) > 0 && (uAccessFlagsGL & GL_MAP_PERSISTENT_BIT) == 0) { ASSERT(false, "Coherent buffers also need to be persistent"); } */ // Derive the appropriate multibuffering settings if (!m_clParameters.bIsMultiBuffered) { m_uDerivedInternalBufferCount = 1u; m_eMultiBufferStrategy = MultiBufferingStrategy::NONE; } else // Multibuffering is used { // Note: Here we assume that persistant mapping also means the buffer is // multibuffered internally using an offset... have to see if this is always desired if ( (uAccessFlagsGL & GL_MAP_PERSISTENT_BIT) > 0 ) { m_eMultiBufferStrategy = MultiBufferingStrategy::OFFSETS; m_uDerivedInternalBufferCount = 1u; } else { m_eMultiBufferStrategy = MultiBufferingStrategy::BUFFERS; m_uDerivedInternalBufferCount = MultiBuffering::kGpuMultiBufferingCount; } } // Create and allocate the buffer m_clParameters.uAccessFlagsGL = uAccessFlagsGL; m_clParameters.uTotalSizeBytes = clParameters.uNumElements * clParameters.uElementSizeBytes; // Retrieve the currently bound buffer to restore it later GLint originalBufferBinding; glGetIntegerv(eBindingQuery, &originalBufferBinding); if (m_eMultiBufferStrategy == MultiBufferingStrategy::NONE || m_eMultiBufferStrategy == MultiBufferingStrategy::BUFFERS) { for (uint32 i = 0; i < m_uDerivedInternalBufferCount; ++i) { uint32 uGlHandle; glGenBuffers(1, &uGlHandle); glBindBuffer(eUsageTarget, uGlHandle); glBufferStorage(eUsageTarget, m_clParameters.uTotalSizeBytes, pInitialData, uAccessFlagsGL); m_vGLhandles.push_back(uGlHandle); } } else // MultiBufferingStrategy::OFFSETS { uint32 uGlHandle; glGenBuffers(1, &uGlHandle); glBindBuffer(eUsageTarget, uGlHandle); // Allocate additional storage but update the initial data in substeps // (because multibuffering should be transparent for high-level and pInitialData is // assumed to point to a single-buffer data store) glBufferStorage(eUsageTarget, m_clParameters.uTotalSizeBytes * MultiBuffering::kGpuMultiBufferingCount, nullptr, uAccessFlagsGL); for (uint32 iBufferPart = 0; iBufferPart < MultiBuffering::kGpuMultiBufferingCount; ++iBufferPart) { glBufferSubData(eUsageTarget, iBufferPart * m_clParameters.uTotalSizeBytes, m_clParameters.uTotalSizeBytes, pInitialData ); } m_vGLhandles.push_back(uGlHandle); } // Restore the originally bound buffer glBindBuffer(eUsageTarget, static_cast<GLuint>(originalBufferBinding)); }
void piglit_init(int argc, char **argv) { static const char *vs_source = "#version 140\n" "in vec4 piglit_vertex;\n" "void main()\n" "{\n" " gl_Position = piglit_vertex;\n" "}\n"; static const char *fs_source = "#version 140\n" "uniform samplerBuffer s;\n" "uniform int offset;\n" "void main()\n" "{\n" " gl_FragColor = texelFetch(s, 0);\n" "}\n"; static const GLfloat verts[16] = { -1, -1, 0, -1, 0, 1, -1, 1, 0, -1, 1, -1, 1, 1, 0, 1 }; GLuint tex, tbo; GLuint prog; int vertex_location; GLuint vao, vbo; piglit_require_extension("GL_ARB_buffer_storage"); prog = piglit_build_simple_program(vs_source, fs_source); glUseProgram(prog); vertex_location = glGetAttribLocation(prog, "piglit_vertex"); glGenBuffers(1, &tbo); glBindBuffer(GL_TEXTURE_BUFFER, tbo); glBufferStorage(GL_TEXTURE_BUFFER, sizeof(red), NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_DYNAMIC_STORAGE_BIT); piglit_check_gl_error(GL_NO_ERROR); map = glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(red), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_BUFFER, tex); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo); glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_READ); glVertexAttribPointer(vertex_location, 2, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(vertex_location); }
int FLightBuffer::UploadLights(FDynLightData &data) { int size0 = data.arrays[0].Size()/4; int size1 = data.arrays[1].Size()/4; int size2 = data.arrays[2].Size()/4; int totalsize = size0 + size1 + size2 + 1; // pointless type casting because some compilers can't print enough warnings. if (mBlockAlign > 0 && (unsigned int)totalsize + (mIndex % mBlockAlign) > mBlockSize) { mIndex = ((mIndex + mBlockAlign) / mBlockAlign) * mBlockAlign; // can't be rendered all at once. if ((unsigned int)totalsize > mBlockSize) { int diff = totalsize - (int)mBlockSize; size2 -= diff; if (size2 < 0) { size1 += size2; size2 = 0; } if (size1 < 0) { size0 += size1; size1 = 0; } totalsize = size0 + size1 + size2 + 1; } } if (totalsize <= 1) return -1; if (mIndex + totalsize > mBufferSize/4) { // reallocate the buffer with twice the size unsigned int newbuffer; // first unmap the old buffer glBindBuffer(mBufferType, mBufferId); glUnmapBuffer(mBufferType); // create and bind the new buffer, bind the old one to a copy target (too bad that DSA is not yet supported well enough to omit this crap.) glGenBuffers(1, &newbuffer); glBindBufferBase(mBufferType, LIGHTBUF_BINDINGPOINT, newbuffer); glBindBuffer(mBufferType, newbuffer); // Note: Some older AMD drivers don't do that in glBindBufferBase, as they should. glBindBuffer(GL_COPY_READ_BUFFER, mBufferId); // create the new buffer's storage (twice as large as the old one) mBufferSize *= 2; mByteSize *= 2; if (gl.lightmethod == LM_DIRECT) { glBufferStorage(mBufferType, mByteSize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); mBufferPointer = (float*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); } else { glBufferData(mBufferType, mByteSize, NULL, GL_DYNAMIC_DRAW); mBufferPointer = (float*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT); } // copy contents and delete the old buffer. glCopyBufferSubData(GL_COPY_READ_BUFFER, mBufferType, 0, 0, mByteSize/2); glBindBuffer(GL_COPY_READ_BUFFER, 0); glDeleteBuffers(1, &mBufferId); mBufferId = newbuffer; } float *copyptr; assert(mBufferPointer != NULL); if (mBufferPointer == NULL) return -1; copyptr = mBufferPointer + mIndex * 4; float parmcnt[] = { 0, float(size0), float(size0 + size1), float(size0 + size1 + size2) }; memcpy(©ptr[0], parmcnt, 4 * sizeof(float)); memcpy(©ptr[4], &data.arrays[0][0], 4 * size0*sizeof(float)); memcpy(©ptr[4 + 4*size0], &data.arrays[1][0], 4 * size1*sizeof(float)); memcpy(©ptr[4 + 4*(size0 + size1)], &data.arrays[2][0], 4 * size2*sizeof(float)); unsigned int bufferindex = mIndex; mIndex += totalsize; draw_dlight += (totalsize-1) / 2; return bufferindex; }
bool InitScene() { SetWindowText(hwnd, TITLE); Quadron::qGLExtensions::QueryFeatures(); isGL4_4 = (Quadron::qGLExtensions::GLVersion >= Quadron::qGLExtensions::GL_4_4); // setup opengl glClearColor(0.0f, 0.125f, 0.3f, 1.0f); glClearDepth(1.0); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); if( !GLCreateMeshFromQM("../media/meshes/teapot.qm", &mesh) ) { MYERROR("Could not load mesh"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/blinnphong.vert", 0, "../media/shadersGL/blinnphong.frag", &effect1) ) { MYERROR("Could not load 'blinnphong' effect"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/uniformbuffer.vert", 0, "../media/shadersGL/uniformbuffer.frag", &effect2) ) { MYERROR("Could not load 'uniformbuffer' effect"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/basic2D.frag", &basic2D) ) { MYERROR("Could not load 'basic2D' shader"); return false; } // create framebuffer framebuffer = new OpenGLFramebuffer(screenwidth, screenheight); framebuffer->AttachTexture(GL_COLOR_ATTACHMENT0, GLFMT_A8B8G8R8, GL_NEAREST); framebuffer->AttachRenderbuffer(GL_DEPTH_STENCIL_ATTACHMENT, GLFMT_D24S8); if( !framebuffer->Validate() ) { MYERROR("Framebuffer validation failed"); return false; } // create uniform buffer effect2->SetUniformBlockBinding("VertexUniformData", 0); effect2->SetUniformBlockBinding("FragmentUniformData", 1); // simple uniform buffer glGenBuffers(1, &uniformbuffer1); glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer1); glBufferData(GL_UNIFORM_BUFFER, sizeof(EffectUniformBlock), NULL, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); // uniform ringbuffer glGenBuffers(1, &uniformbuffer2); glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer2); glBufferData(GL_UNIFORM_BUFFER, UNIFORM_COPIES * sizeof(EffectUniformBlock), NULL, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); if( isGL4_4 ) { // uniform storage buffer glGenBuffers(1, &uniformbuffer3); glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer3); glBufferStorage(GL_UNIFORM_BUFFER, UNIFORM_COPIES * sizeof(EffectUniformBlock), NULL, GL_DYNAMIC_STORAGE_BIT|GL_MAP_WRITE_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_COHERENT_BIT); glBindBuffer(GL_UNIFORM_BUFFER, 0); } memset(&uniformDTO, 0, sizeof(uniformDTO)); // render text GLCreateTexture(512, 512, 1, GLFMT_A8B8G8R8, &text1); if( isGL4_4 ) { glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer3); persistentdata = (EffectUniformBlock*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, UNIFORM_COPIES * sizeof(EffectUniformBlock), GL_MAP_WRITE_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_COHERENT_BIT); glBindBuffer(GL_UNIFORM_BUFFER, 0); assert(persistentdata != 0); GLRenderText( "1 - glUniformXX\n2 - UBO with glBufferSubData\n3 - UBO with glMapBufferRange\n4 - UBO with glFenceSync\n5 - UBO with persistent mapping", text1, 512, 512); } else { GLRenderText( "1 - glUniformXX\n2 - UBO with glBufferSubData\n3 - UBO with glMapBufferRange\n4 - UBO with glFenceSync", text1, 512, 512); } screenquad = new OpenGLScreenQuad(); // setup cameras basiccamera.SetAspect((float)screenwidth / screenheight); basiccamera.SetFov(GLDegreesToRadians(80)); basiccamera.SetClipPlanes(0.1f, 30.0f); basiccamera.SetDistance(10.0f); return true; }
static void testBufferStorage(void) { if (!GLAD_GL_VERSION_4_4 && !glfwExtensionSupported("GL_ARB_buffer_storage")) { fprintf(stderr, "error: GL_ARB_buffer_storage not supported\n"); glfwTerminate(); exit(EXIT_SKIP); } GLbitfield map_trace_explicit_bit = 0; if (glfwExtensionSupported("GL_VMWX_map_buffer_debug")) { glNotifyMappedBufferRangeVMWX = (PFNGLNOTIFYMAPPEDBUFFERRANGEVMWXPROC)glfwGetProcAddress("glNotifyMappedBufferRangeVMWX"); assert(glNotifyMappedBufferRangeVMWX); map_trace_explicit_bit = GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX; } GLuint buffer = 0; glGenBuffers(1, &buffer); glBindBuffer(target, buffer); GLsizeiptr size = 1000; void *data = malloc(size); memset(data, 0, size); while ((glGetError() != GL_NO_ERROR)) ; glBufferStorage(target, size, data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | map_trace_explicit_bit); free(data); GLenum error = glGetError(); switch (error) { case GL_NO_ERROR: break; case GL_OUT_OF_MEMORY: exit(EXIT_SKIP); default: exit(EXIT_FAILURE); } GLubyte *map; // straightforward mapping map = (GLubyte *)glMapBufferRange(target, 100, 100, GL_MAP_WRITE_BIT); memset(map, 1, 100); glUnmapBuffer(target); // persistent mapping w/ explicit flush map = (GLubyte *)glMapBufferRange(target, 200, 300, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); memset(map + 20, 2, 30); glFlushMappedBufferRange(target, 20, 30); memset(map + 50, 3, 50); glFlushMappedBufferRange(target, 50, 50); glUnmapBuffer(target); // persistent & coherent mapping map = (GLubyte *)glMapBufferRange(target, 500, 100, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | map_trace_explicit_bit); memset(map + 20, 4, 30); glNotifyMappedBufferRangeVMWX(map + 20, 30); memset(map + 50, 5, 50); glNotifyMappedBufferRangeVMWX(map + 50, 50); glUnmapBuffer(target); glBindBuffer(target, 0); glDeleteBuffers(1, &buffer); }
void piglit_init(int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "coherent")) { coherent = GL_TRUE; continue; } if (!strcmp(argv[i], "read")) { test = READ; continue; } if (!strcmp(argv[i], "draw")) { test = DRAW; continue; } if (!strcmp(argv[i], "client-storage")) { client_storage = GL_TRUE; continue; } printf("Unknown param: %s\n", argv[i]); piglit_report_result(PIGLIT_FAIL); } if (test == NONE) { puts("Wrong parameters."); piglit_report_result(PIGLIT_FAIL); } #ifdef PIGLIT_USE_OPENGL piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); piglit_require_gl_version(15); piglit_require_extension("GL_ARB_buffer_storage"); piglit_require_extension("GL_ARB_map_buffer_range"); if (test == READ) { piglit_require_extension("GL_ARB_copy_buffer"); piglit_require_extension("GL_ARB_sync"); } if (!coherent) { /* for MemoryBarrier */ piglit_require_extension("GL_ARB_shader_image_load_store"); } #else // PIGLIT_USE_OPENGL_ES3 GLuint program; GLuint vertex_index; piglit_require_extension("GL_EXT_buffer_storage"); /* Create program */ program = piglit_build_simple_program(vs_source, fs_source); glUseProgram(program); #endif glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferStorage(GL_ARRAY_BUFFER, BUF_SIZE, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0) | GL_DYNAMIC_STORAGE_BIT | (client_storage ? GL_CLIENT_STORAGE_BIT : 0)); piglit_check_gl_error(GL_NO_ERROR); map = glMapBufferRange(GL_ARRAY_BUFFER, 0, BUF_SIZE, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0)); piglit_check_gl_error(GL_NO_ERROR); if (!map) piglit_report_result(PIGLIT_FAIL); #ifdef PIGLIT_USE_OPENGL_ES3 /* Gen VAO */ glGenVertexArrays(1, &vao); glBindVertexArray(vao); /* Retrieve indices from vs */ vertex_index = glGetAttribLocation(program, "vertex"); /* Enable vertex attrib array */ glEnableVertexAttribArray(vertex_index); glVertexAttribPointer(vertex_index, 3, GL_FLOAT, GL_FALSE, 0, 0); piglit_check_gl_error(GL_NO_ERROR); #endif glBindBuffer(GL_ARRAY_BUFFER, 0); }
// -------------------------------------------------------------------------------------------------------------------- bool UntexturedObjectsGLBindlessIndirect::Init(const std::vector<UntexturedObjectsProblem::Vertex>& _vertices, const std::vector<UntexturedObjectsProblem::Index>& _indices, size_t _objectCount) { if (glBufferStorage == nullptr) { console::warn("Unable to initialize solution '%s', glBufferStorage() unavailable.", GetName().c_str()); return false; } if (glGetBufferParameterui64vNV == nullptr || glMakeBufferResidentNV == nullptr) { console::warn("Unable to initialize solution '%s', GL_NV_shader_buffer_load unavailable.", GetName().c_str()); return false; } if (!UntexturedObjectsSolution::Init(_vertices, _indices, _objectCount)) { return false; } // Program const char* kUniformNames[] = { "ViewProjection", "World", nullptr }; m_prog = CreateProgramT("cubes_gl_bindless_indirect_vs.glsl", "cubes_gl_bindless_indirect_fs.glsl", kUniformNames, &mUniformLocation); if (m_prog == 0) { console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str()); return false; } m_ibs.resize(_objectCount); m_ib_addrs.resize(_objectCount); m_ib_sizes.resize(_objectCount); m_vbs.resize(_objectCount); m_vbo_addrs.resize(_objectCount); m_vbo_sizes.resize(_objectCount); m_commands.resize(_objectCount); glGenBuffers(_objectCount, &*m_ibs.begin()); glGenBuffers(_objectCount, &*m_vbs.begin()); for (size_t u = 0; u < _objectCount; ++u) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibs[u]); glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(UntexturedObjectsProblem::Index), &*_indices.begin(), 0); glGetBufferParameterui64vNV(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_GPU_ADDRESS_NV, &m_ib_addrs[u]); glMakeBufferResidentNV(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); m_ib_sizes[u] = _indices.size() * sizeof(UntexturedObjectsProblem::Index); glBindBuffer(GL_ARRAY_BUFFER, m_vbs[u]); glBufferStorage(GL_ARRAY_BUFFER, _vertices.size() * sizeof(UntexturedObjectsProblem::Vertex), &*_vertices.begin(), 0); glGetBufferParameterui64vNV(GL_ARRAY_BUFFER, GL_BUFFER_GPU_ADDRESS_NV, &m_vbo_addrs[u]); glMakeBufferResidentNV(GL_ARRAY_BUFFER, GL_READ_ONLY); m_vbo_sizes[u] = _vertices.size() * sizeof(UntexturedObjectsProblem::Vertex); } glGenBuffers(1, &m_transform_buffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_transform_buffer); glBufferStorage(GL_SHADER_STORAGE_BUFFER, _objectCount * 64, nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT); m_transform_ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, _objectCount * 64, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); glGenBuffers(1, &m_cmd_buffer); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmd_buffer); glBufferStorage(GL_DRAW_INDIRECT_BUFFER, _objectCount * sizeof(Command), nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT); m_cmd_ptr = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, _objectCount * sizeof(Command), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); m_queries.resize(4); glGenQueries(kQueryCount, &*m_queries.begin()); return glGetError() == GL_NO_ERROR; }
/** Update shadowSplit values and make Cascade Bounding Box pointer valid. * The function aunches two compute kernel that generates an histogram of the depth buffer value (between 0 and 250 with increment of 0.25) * and get an axis aligned bounding box (from SunCamMatrix view) containing all depth buffer value. * It also retrieves the result from the previous computations (in a Round Robin fashion) and update CBB pointer. * \param width of the depth buffer * \param height of the depth buffer * TODO : The depth histogram part is commented out, needs to tweak it when I have some motivation */ void IrrDriver::UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, size_t height) { // Value that should be kept between multiple calls static GLuint ssbo[2]; static Histogram *Hist[2]; static GLsync LightcoordBBFence = 0; static size_t currentHist = 0; static GLuint ssboSplit[2]; static float tmpshadowSplit[5] = { 1., 5., 20., 50., 150. }; if (!LightcoordBBFence) { glGenBuffers(2, ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[0]); glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); CBB[0] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[1]); glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); CBB[1] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); /* glGenBuffers(2, ssboSplit); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[0]); glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); Hist[0] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[1]); glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); Hist[1] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);*/ } // Use bounding boxes from last frame if (LightcoordBBFence) { while (glClientWaitSync(LightcoordBBFence, GL_SYNC_FLUSH_COMMANDS_BIT, 0) != GL_ALREADY_SIGNALED); glDeleteSync(LightcoordBBFence); } /* { memcpy(shadowSplit, tmpshadowSplit, 5 * sizeof(float)); unsigned numpix = Hist[currentHist]->count; unsigned split = 0; unsigned i; for (i = 0; i < 1022; i++) { split += Hist[currentHist]->bin[i]; if (split > numpix / 2) break; } tmpshadowSplit[1] = (float)++i / 4.; for (; i < 1023; i++) { split += Hist[currentHist]->bin[i]; if (split > 3 * numpix / 4) break; } tmpshadowSplit[2] = (float)++i / 4.; for (; i < 1024; i++) { split += Hist[currentHist]->bin[i]; if (split > 7 * numpix / 8) break; } tmpshadowSplit[3] = (float)++i / 4.; for (; i < 1024; i++) { split += Hist[currentHist]->bin[i]; } tmpshadowSplit[0] = (float)(Hist[currentHist]->bin[1024] - 1) / 4.; tmpshadowSplit[4] = (float)(Hist[currentHist]->bin[1025] + 1) / 4.; printf("numpix is %d\n", numpix); printf("total : %d\n", split); printf("split 0 : %f\n", tmpshadowSplit[1]); printf("split 1 : %f\n", tmpshadowSplit[2]); printf("split 2 : %f\n", tmpshadowSplit[3]); printf("min %f max %f\n", tmpshadowSplit[0], tmpshadowSplit[4]); currentHist = (currentHist + 1) % 2; }*/ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo[currentCBB]); // glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboSplit[currentHist]); for (unsigned i = 0; i < 4; i++) { CBB[currentCBB][i].xmin = CBB[currentCBB][i].ymin = CBB[currentCBB][i].zmin = 1000; CBB[currentCBB][i].xmax = CBB[currentCBB][i].ymax = CBB[currentCBB][i].zmax = -1000; } // memset(Hist[currentHist], 0, sizeof(Histogram)); // Hist[currentHist]->mindepth = 3000; glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); glUseProgram(FullScreenShader::LightspaceBoundingBoxShader::getInstance()->Program); FullScreenShader::LightspaceBoundingBoxShader::getInstance()->SetTextureUnits(getDepthStencilTexture()); FullScreenShader::LightspaceBoundingBoxShader::getInstance()->setUniforms(m_suncam->getViewMatrix(), tmpshadowSplit[1], tmpshadowSplit[2], tmpshadowSplit[3], tmpshadowSplit[4]); glDispatchCompute((int)width / 64, (int)height / 64, 1); /* glUseProgram(FullScreenShader::DepthHistogramShader::getInstance()->Program); FullScreenShader::DepthHistogramShader::getInstance()->SetTextureUnits(getDepthStencilTexture()); FullScreenShader::DepthHistogramShader::getInstance()->setUniforms(); glDispatchCompute((int)width / 32, (int)height / 32, 1);*/ glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); LightcoordBBFence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); currentCBB = (currentCBB + 1) % 2; }
inline void buffer_storage(BufferType target, uint32 size, const void* data, BufferStorage flags) { ARC_GL_CLEAR_ERRORS(); glBufferStorage((GLenum)target, size, data, (GLbitfield)flags); ARC_GL_CHECK_FOR_ERRORS(); }
/** * TODO: Test if you can pass a NULL mesh to Geometry. */ RenderableGeometry *renderableGeometryNew(Geometry geometry) { RenderableGeometry *renderableGeometry = malloc(sizeof(RenderableGeometry)); renderableGeometry->indices = 0; renderableGeometry->aabb.min = vec3(0.0f, 0.0f, 0.0f); renderableGeometry->aabb.max = vec3(0.0f, 0.0f, 0.0f); glGenVertexArrays(1, &renderableGeometry->vao); glGenBuffers(4, renderableGeometry->vbo); Mesh *mesh = NULL; if (geometry.type == GEOMETRY_MESH) { mesh = geometry.mesh; } else if (geometry.type == GEOMETRY_PLANE) { // Generate mesh } else if (geometry.type == GEOMETRY_CUBE) { // Generate mesh } else if (geometry.type == GEOMETRY_SPHERE) { // Generate mesh } else if (geometry.type == GEOMETRY_CAPSULE) { // Generate mesh } else if (geometry.type == GEOMETRY_CYLINDER) { // Generate mesh } else if (geometry.type == GEOMETRY_RAY) { // Generate mesh } if (mesh != NULL) { renderableGeometry->indices = (GLsizei)mesh->indices.length; /** * Define VAO. */ glBindVertexArray(renderableGeometry->vao); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0); glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, 0); glVertexAttribFormat(2, 3, GL_FLOAT, GL_FALSE, 0); /** * Define VBOs. */ if (mesh->vertices.length > 0) { glBindBuffer(GL_ARRAY_BUFFER, renderableGeometry->vbo[0]); glBufferStorage(GL_ARRAY_BUFFER, mesh->vertices.length * sizeof(Vec3), (float*)mesh->vertices.data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); } if (mesh->uvs.length > 0) { glBindBuffer(GL_ARRAY_BUFFER, renderableGeometry->vbo[1]); glBufferStorage(GL_ARRAY_BUFFER, mesh->uvs.length * sizeof(Vec2), (float*)mesh->uvs.data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); } if (mesh->normals.length > 0) { glBindBuffer(GL_ARRAY_BUFFER, renderableGeometry->vbo[2]); glBufferStorage(GL_ARRAY_BUFFER, mesh->normals.length * sizeof(Vec3), (float*)mesh->normals.data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); } if (mesh->indices.length > 0) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderableGeometry->vbo[3]); glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, mesh->indices.length * sizeof(unsigned), (unsigned*)mesh->indices.data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); } glBindVertexBuffer(0, renderableGeometry->vbo[0], 0, sizeof(Vec3)); glBindVertexBuffer(1, renderableGeometry->vbo[1], 0, sizeof(Vec2)); glBindVertexBuffer(2, renderableGeometry->vbo[2], 0, sizeof(Vec3)); /** * Unbind. */ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } return renderableGeometry; }
Renderer::Renderer(const int width, const int height) : width(width), height(height), mvp{} { glDebugMessageCallback(gl_debug_callback, NULL); const int max_vertices {100}; const GLbitfield flags {GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT}; /* factor 3 comes from euler characteristic */ const size_t vbo_size {max_vertices * 3 * sizeof(GLfloat)}; const size_t ebo_size {max_vertices * sizeof(GLuint)}; const size_t vbo_lines_size {10 * 4 * sizeof(GLfloat)}; glGenBuffers(2, vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBufferStorage(GL_ARRAY_BUFFER, vbo_size, NULL, flags); vbo_mapped = glMapBufferRange(GL_ARRAY_BUFFER, 0, vbo_size, flags); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glBufferStorage(GL_ARRAY_BUFFER, vbo_lines_size, NULL, flags); vbo_lines_mapped = glMapBufferRange(GL_ARRAY_BUFFER, 0, vbo_lines_size, flags); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, ebo_size, NULL, flags); ebo_mapped = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0 , ebo_size, flags); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glGenVertexArrays(2, vao); glBindVertexArray(vao[0]); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); glEnableVertexAttribArray(0); glBindVertexArray(0); /* velocity VAO */ glBindVertexArray(vao[1]); glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); glEnableVertexAttribArray(0); glBindVertexArray(0); /* pass through shaders */ const std::string vert_data = read_file("data/main.vert"); const char *vert_data_ptr = vert_data.c_str(); vert_prog[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vert_data_ptr); const std::string frag_data = read_file("data/main.frag"); const char *frag_data_ptr = frag_data.c_str(); frag_prog[0] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &frag_data_ptr); glGenProgramPipelines(2, pipeline); glUseProgramStages(pipeline[0], GL_VERTEX_SHADER_BIT, vert_prog[0]); glUseProgramStages(pipeline[0], GL_FRAGMENT_SHADER_BIT, frag_prog[0]); /* debug arrows shaders */ const std::string frag_velocity = read_file("data/velocity.frag"); const char *frag_velocity_ptr = frag_velocity.c_str(); frag_prog[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &frag_velocity_ptr); glUseProgramStages(pipeline[1], GL_VERTEX_SHADER_BIT, vert_prog[0]); glUseProgramStages(pipeline[1], GL_FRAGMENT_SHADER_BIT, frag_prog[1]); /* set up uniforms */ mvp.view = {20.0f / width, 0.0f, 0.0f, 0.0f, 0.0f, 20.0f / height, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f}; glGenBuffers(1, &ubo); glBindBuffer(GL_UNIFORM_BUFFER, ubo); glBufferStorage(GL_UNIFORM_BUFFER, sizeof(mvp), &mvp, GL_DYNAMIC_STORAGE_BIT); glBindBuffer(GL_UNIFORM_BUFFER, 0); glUniformBlockBinding(vert_prog[0], glGetUniformBlockIndex(vert_prog[0], "MVP"), 0); glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, sizeof(mvp)); }
//============================================================================== void GlBuffer::create(GLenum target, U32 sizeInBytes, const void* dataPtr, GLbitfield flags) { ANKI_ASSERT(!isCreated()); if(target == GL_UNIFORM_BUFFER) { GLint64 maxBufferSize; glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxBufferSize); if(sizeInBytes > 16384) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the spec's min", sizeInBytes); } else if(sizeInBytes > (PtrSize)maxBufferSize) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the implementation's min (%u)", sizeInBytes, maxBufferSize); } } else if(target == GL_SHADER_STORAGE_BUFFER) { GLint64 maxBufferSize; glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxBufferSize); if(sizeInBytes > pow(2, 24)) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the spec's min", sizeInBytes); } else if(sizeInBytes > (PtrSize)maxBufferSize) { ANKI_LOGW("The size (%u) of the shader storage buffer is greater " "than the implementation's min (%u)", sizeInBytes, maxBufferSize); } } m_target = target; m_size = sizeInBytes; ANKI_ASSERT(m_size > 0 && "Unacceptable size"); // Create glGenBuffers(1, &m_glName); glBindBuffer(m_target, m_glName); glBufferStorage(m_target, m_size, dataPtr, flags); // Map if needed if((flags & GL_MAP_PERSISTENT_BIT) && (flags & GL_MAP_COHERENT_BIT)) { const GLbitfield mapbits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; m_persistentMapping = glMapBufferRange(m_target, 0, sizeInBytes, flags & mapbits); ANKI_ASSERT(m_persistentMapping != nullptr); } }
// -------------------------------------------------------------------------------------------------------------------- bool UntexturedObjectsGLBufferStorage::Init(const std::vector<UntexturedObjectsProblem::Vertex>& _vertices, const std::vector<UntexturedObjectsProblem::Index>& _indices, size_t _objectCount) { if (glBufferStorage == nullptr) { console::warn("Unable to initialize solution '%s', glBufferStorage() unavailable.", GetName().c_str()); return false; } if (!UntexturedObjectsSolution::Init(_vertices, _indices, _objectCount)) { return false; } if (mUseShaderDrawParameters && !HasExtension("GL_ARB_shader_draw_parameters")) { console::warn("Unable to initialize solution, ARB_shader_draw_parameters is required but not available."); return false; } // Program const char* kUniformNames[] = { "ViewProjection", nullptr }; m_prog = CreateProgramT("cubes_gl_buffer_storage_vs.glsl", "cubes_gl_buffer_storage_fs.glsl", mUseShaderDrawParameters ? std::string("#define USE_SHADER_DRAW_PARAMETERS 1\n") : std::string(""), kUniformNames, &mUniformLocation); if (m_prog == 0) { console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str()); return false; } glGenVertexArrays(1, &m_varray); glBindVertexArray(m_varray); // Buffers glGenBuffers(1, &m_vb); glBindBuffer(GL_ARRAY_BUFFER, m_vb); glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(UntexturedObjectsProblem::Vertex), &*_vertices.begin(), GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(UntexturedObjectsProblem::Vertex), (void*) offsetof(UntexturedObjectsProblem::Vertex, pos)); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(UntexturedObjectsProblem::Vertex), (void*) offsetof(UntexturedObjectsProblem::Vertex, color)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); // If we aren't using shader draw parameters, use the workaround instead. if (!mUseShaderDrawParameters) { std::vector<uint32_t> drawids(_objectCount); for (uint32_t i = 0; i < _objectCount; ++i) { drawids[i] = i; } glGenBuffers(1, &m_drawid); glBindBuffer(GL_ARRAY_BUFFER, m_drawid); glBufferData(GL_ARRAY_BUFFER, drawids.size() * sizeof(uint32_t), drawids.data(), GL_STATIC_DRAW); glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(uint32_t), 0); glVertexAttribDivisor(2, 1); glEnableVertexAttribArray(2); } glGenBuffers(1, &m_ib); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ib); glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(UntexturedObjectsProblem::Index), &*_indices.begin(), GL_STATIC_DRAW); glGenBuffers(1, &m_transform_buffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_transform_buffer); glBufferStorage(GL_SHADER_STORAGE_BUFFER, _objectCount * 64, nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT); m_transform_ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, _objectCount * 64, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); glGenBuffers(1, &m_cmd_buffer); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmd_buffer); glBufferStorage(GL_DRAW_INDIRECT_BUFFER, _objectCount * sizeof(DrawElementsIndirectCommand), nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_DYNAMIC_STORAGE_BIT); m_cmd_ptr = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, _objectCount * sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); // Set the command buffer size. m_commands.resize(_objectCount); return glGetError() == GL_NO_ERROR; }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL44_nglBufferStorage(JNIEnv *env, jclass clazz, jint target, jlong size, jlong data, jint flags, jlong function_pointer) { const GLvoid *data_address = (const GLvoid *)(intptr_t)data; glBufferStoragePROC glBufferStorage = (glBufferStoragePROC)((intptr_t)function_pointer); glBufferStorage(target, size, data_address, flags); }
//============================================================================== void BufferImpl::init( PtrSize size, BufferUsageBit usage, BufferAccessBit access) { ANKI_ASSERT(!isCreated()); m_usage = usage; m_access = access; /// // Check size // ANKI_ASSERT(size > 0 && "Unacceptable size"); // This is a guess, not very important since DSA doesn't care about it on // creation m_target = GL_ARRAY_BUFFER; if((usage & BufferUsageBit::UNIFORM) != BufferUsageBit::NONE) { GLint64 maxBufferSize; glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxBufferSize); if(size > 16384) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the spec's min", size); } else if(size > PtrSize(maxBufferSize)) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the implementation's min (%u)", size, maxBufferSize); } m_target = GL_UNIFORM_BUFFER; } if((usage & BufferUsageBit::STORAGE) != BufferUsageBit::NONE) { GLint64 maxBufferSize; glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxBufferSize); if(size > pow(2, 24)) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the spec's min", size); } else if(size > PtrSize(maxBufferSize)) { ANKI_LOGW("The size (%u) of the shader storage buffer is greater " "than the implementation's min (%u)", size, maxBufferSize); } m_target = GL_SHADER_STORAGE_BUFFER; } m_size = size; // // Determine the creation flags // GLbitfield flags = 0; Bool shouldMap = false; if((access & BufferAccessBit::CLIENT_WRITE) != BufferAccessBit::NONE) { flags |= GL_DYNAMIC_STORAGE_BIT; } if((access & BufferAccessBit::CLIENT_MAP_WRITE) != BufferAccessBit::NONE) { flags |= GL_MAP_WRITE_BIT; flags |= GL_MAP_PERSISTENT_BIT; flags |= GL_MAP_COHERENT_BIT; shouldMap = true; } if((access & BufferAccessBit::CLIENT_MAP_READ) != BufferAccessBit::NONE) { flags |= GL_MAP_READ_BIT; flags |= GL_MAP_PERSISTENT_BIT; flags |= GL_MAP_COHERENT_BIT; shouldMap = true; } // // Create // glGenBuffers(1, &m_glName); glBindBuffer(m_target, m_glName); glBufferStorage(m_target, size, nullptr, flags); // // Map // if(shouldMap) { const GLbitfield MAP_BITS = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; m_persistentMapping = glMapBufferRange(m_target, 0, size, flags & MAP_BITS); ANKI_ASSERT(m_persistentMapping != nullptr); } }
void OGLTexture1D::CreateHWResource(ArrayRef<ElementInitData> init_data, float4 const * clear_value_hint) { KFL_UNUSED(clear_value_hint); GLint glinternalFormat; GLenum glformat; GLenum gltype; OGLMapping::MappingFormat(glinternalFormat, glformat, gltype, format_); if (sample_count_ <= 1) { uint32_t const pbo_size = mipmap_start_offset_.back() * array_size_; if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access()) { glTextureParameteri(texture_, GL_TEXTURE_MAX_LEVEL, num_mip_maps_ - 1); glNamedBufferStorage(pbo_, pbo_size, nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT); uint32_t const w0 = this->Width(0); if (array_size_ > 1) { glTextureStorage2D(texture_, num_mip_maps_, glinternalFormat, w0, array_size_); } else { glTextureStorage1D(texture_, num_mip_maps_, glinternalFormat, w0); } if (!init_data.empty()) { for (uint32_t array_index = 0; array_index < array_size_; ++ array_index) { for (uint32_t level = 0; level < num_mip_maps_; ++ level) { uint32_t const w = this->Width(level); GLvoid const * data = init_data[array_index * num_mip_maps_ + level].data; if (IsCompressedFormat(format_)) { uint32_t const block_size = NumFormatBytes(format_) * 4; GLsizei const image_size = ((w + 3) / 4) * block_size; if (array_size_ > 1) { glCompressedTextureSubImage2D(texture_, level, 0, array_index, w, 1, glformat, image_size, data); } else { glCompressedTextureSubImage1D(texture_, level, 0, w, glformat, image_size, data); } } else { if (array_size_ > 1) { glTextureSubImage2D(texture_, level, 0, array_index, w, 1, glformat, gltype, data); } else { glTextureSubImage1D(texture_, level, 0, w, glformat, gltype, data); } } } } } } else { auto& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance()); re.BindTexture(0, target_type_, texture_); glTexParameteri(target_type_, GL_TEXTURE_MAX_LEVEL, num_mip_maps_ - 1); re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_); if (glloader_GL_VERSION_4_4() || glloader_GL_ARB_buffer_storage()) { glBufferStorage(GL_PIXEL_UNPACK_BUFFER, pbo_size, nullptr, GL_DYNAMIC_STORAGE_BIT); } else { glBufferData(GL_PIXEL_UNPACK_BUFFER, pbo_size, nullptr, GL_STREAM_COPY); } re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); if (glloader_GL_VERSION_4_2() || glloader_GL_ARB_texture_storage()) { uint32_t const w0 = this->Width(0); if (array_size_ > 1) { glTexStorage2D(target_type_, num_mip_maps_, glinternalFormat, w0, array_size_); } else { glTexStorage1D(target_type_, num_mip_maps_, glinternalFormat, w0); } if (!init_data.empty()) { for (uint32_t array_index = 0; array_index < array_size_; ++ array_index) { for (uint32_t level = 0; level < num_mip_maps_; ++ level) { uint32_t const w = this->Width(level); GLvoid const * data = init_data[array_index * num_mip_maps_ + level].data; if (IsCompressedFormat(format_)) { uint32_t const block_size = NumFormatBytes(format_) * 4; GLsizei const image_size = ((w + 3) / 4) * block_size; if (array_size_ > 1) { glCompressedTexSubImage2D(target_type_, level, 0, array_index, w, 1, glformat, image_size, data); } else { glCompressedTexSubImage1D(target_type_, level, 0, w, glformat, image_size, data); } } else { if (array_size_ > 1) { glTexSubImage2D(target_type_, level, 0, array_index, w, 1, glformat, gltype, data); } else { glTexSubImage1D(target_type_, level, 0, w, glformat, gltype, data); } } } } } } else { for (uint32_t array_index = 0; array_index < array_size_; ++ array_index) { for (uint32_t level = 0; level < num_mip_maps_; ++ level) { uint32_t const w = this->Width(level); if (IsCompressedFormat(format_)) { uint32_t const block_size = NumFormatBytes(format_) * 4; GLsizei const image_size = ((w + 3) / 4) * block_size; if (array_size_ > 1) { if (0 == array_index) { glCompressedTexImage2D(target_type_, level, glinternalFormat, w, array_size_, 0, image_size * array_size_, nullptr); } if (!init_data.empty()) { glCompressedTexSubImage2D(target_type_, level, 0, array_index, w, 1, glformat, image_size, init_data[array_index * num_mip_maps_ + level].data); } } else { glCompressedTexImage1D(target_type_, level, glinternalFormat, w, 0, image_size, init_data.empty() ? nullptr : init_data[array_index * num_mip_maps_ + level].data); } } else { if (array_size_ > 1) { if (0 == array_index) { glTexImage2D(target_type_, level, glinternalFormat, w, array_size_, 0, glformat, gltype, nullptr); } if (!init_data.empty()) { glTexSubImage2D(target_type_, level, 0, array_index, w, 1, glformat, gltype, init_data[array_index * num_mip_maps_ + level].data); } } else { glTexImage1D(target_type_, level, glinternalFormat, w, 0, glformat, gltype, init_data.empty() ? nullptr : init_data[array_index * num_mip_maps_ + level].data); } } } } } } } else { glBindRenderbuffer(GL_RENDERBUFFER, texture_); glRenderbufferStorageMultisample(GL_RENDERBUFFER, sample_count_, glinternalFormat, width_, 1); } hw_res_ready_ = true; }