Using Pixel buffer objects to update textures in OpenGl

Hello I looked into GL/GLAbstraction.jl package and as far as I see texture updating is done by glTexSubImage2D , yet why Pixel buffer objects are not used? Is there some reason?

Frankly I tried to implement the pixel buffer objects myself - yet I can not make it work - program do not give any errors just do not display anything

simple code that works

function updateTexture(data, textSpec::TextureSpec)
	glBindTexture(GL_TEXTURE_2D, textSpec.ID[]); 
	glTexSubImage2D(GL_TEXTURE_2D,0,0,0, textSpec.widthh, textSpec.heightt, GL_RED_INTEGER, textSpec.OpGlType, data);
end

code where I try to use pixel buffer objects - yet without success

First I define pixel buffers

preparePixelBufferStr="""
width -width of the image in  number of pixels 
height - height of the image in  number of pixels 
pboNumber - just states which PBO it is
return reference to the pixel buffer object that we use to upload this texture and data size calculated for this texture

"""
@doc preparePixelBufferStr
function preparePixelBuffer(juliaDataTyp::Type{juliaDataType},width,height,pboNumber)where{juliaDataType}
    DATA_SIZE = 8 * sizeof(juliaDataTyp) *width * height  # number of bytes our image will have so in 2D it will be width times height times number of bytes needed for used datatype we need to multiply by 8 becouse sizeof() return bytes instead of bits
    pbo = Ref(GLuint(pboNumber))  
    glGenBuffers(1, pbo)
    return (pbo,DATA_SIZE)
end

then try to use it as below

usePixelBuferAndUploadDataStr = """
adapted from http://www.songho.ca/opengl/gl_pbo.html
creates single pixel buffer of given type
pboID - id of the pixel buffer object that was prepared for some particular texture
textureId - reference to id of a texture that we want to bind to this PBO
juliaDataType -julia type that is representing datatype in 2 dimensional array representing ima
width -width of the image in  number of pixels 
height - height of the image in  number of pixels 
subImageDataType - variable used in glTexSubImage2D to tell open Glo what type of data is in texture
data one dimensional array o julia type and width*height length
DATA_SIZE - size of texture in bytes
"""
@doc usePixelBuferAndUploadDataStr
function usePixelBuferAndUploadData(
    juliaDataTyp::Type{juliaDataType}
                    ,pboID 
                    ,width
                    ,height
                    ,data
                    ,textureId
                    ,DATA_SIZE
                    ,subImageDataType = GL_SHORT
                
                    )where{juliaDataType}

    glBindTexture(GL_TEXTURE_2D,textureId[]); 
    # copy pixels from PBO to texture object
    # Use offset instead of pointer.
   # glTexSubImage2D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, GLsizei(width), GLsizei(height),  GL_RED_INTEGER, GL_SHORT, Ptr{juliaDataTyp}());
   
    glTexSubImage2D(GL_TEXTURE_2D,0,0,0, width, height, GL_RED_INTEGER, subImageDataType, Ptr{juliaDataType}());

  
    # bind the PBO
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID[]);


    # Note that glMapBuffer() causes sync issue.
    # If GPU is working with this buffer, glMapBuffer() will wait(stall)
    # until GPU to finish its job. To avoid waiting (idle), you can call
    # first glBufferData() with NULL pointer before glMapBuffer().
    # If you do that, the previous data in PBO will be discarded and
    # glMapBuffer() returns a new allocated pointer immediately
    # even if GPU is still working with the previous data.
    glBufferData(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE, Ptr{juliaDataType}(), GL_STREAM_DRAW);
    
    # map the buffer object into client's memory
    glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)
    
     
    ptr = Ptr{juliaDataType}(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY))
    # update data directly on the mapped buffer - this is internal function implemented below
    
    updatePixels(ptr,data,length(data));

    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); # release the mapped buffer
    
    # it is good idea to release PBOs with ID 0 after use.
    # Once bound with 0, all pixel operations are back to normal ways.
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);



end
updatePixelsStr = """
adapted from https://github.com/JuliaPlots/GLMakie.jl/blob/2717d812fdc66b283f63d5d97237e8d69e2c1f25/src/GLAbstraction/GLBuffer.jl from unsafe copy
"""
@doc updatePixelsStr
function updatePixels(ptr, data,length)
    for i=1:length
        unsafe_store!(ptr,data[i], i)
    end
end




So first I upload data of given type - I frequently use Int16 textures - then create pixel buffers - pass all to usePixelBuferAndUploadDataStr and then do simple rendering (just rendering onto the quad - swapping buffers… nothing fancy and as I said this part works)
Anybody have an idea How to make it work?