Skip to content

Commit

Permalink
use dedicated framebuffers
Browse files Browse the repository at this point in the history
  • Loading branch information
ffreyer committed Dec 24, 2024
1 parent b2f9992 commit 9abac6d
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 115 deletions.
2 changes: 1 addition & 1 deletion GLMakie/src/GLAbstraction/GLAbstraction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export getAttributesInfo
include("GLFrameBuffer.jl")
export GLRenderbuffer
export GLFramebuffer
export attach_colorbuffer, attach_depthbuffer, attach_stencilbuffer
export attach_colorbuffer, attach_depthbuffer, attach_stencilbuffer, attach_depthstencilbuffer
export get_attachment, get_buffer
export check_framebuffer

Expand Down
8 changes: 6 additions & 2 deletions GLMakie/src/GLAbstraction/GLFrameBuffer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ function bind(fb::GLFramebuffer)
glBindFramebuffer(GL_FRAMEBUFFER, fb.id)
return
end
unbind(::GLFramebuffer) = glBindFramebuffer(GL_FRAMEBUFFER, 0)

function unsafe_free(x::GLFramebuffer)
# don't free if already freed
Expand Down Expand Up @@ -113,6 +114,7 @@ end
attach_colorbuffer(fb::GLFramebuffer, key::Symbol, buffer) = attach(fb, key, buffer, get_next_colorbuffer_attachment(fb))
attach_depthbuffer(fb::GLFramebuffer, key::Symbol, buffer) = attach(fb, key, buffer, GL_DEPTH_ATTACHMENT)
attach_stencilbuffer(fb::GLFramebuffer, key::Symbol, buffer) = attach(fb, key, buffer, GL_STENCIL_ATTACHMENT)
attach_depthstencilbuffer(fb::GLFramebuffer, key::Symbol, buffer) = attach(fb, key, buffer, GL_DEPTH_STENCIL_ATTACHMENT)

function attach(fb::GLFramebuffer, key::Symbol, buffer, attachment::GLenum)
haskey(fb, key) && error("Cannot attach $key to Framebuffer because it is already set.")
Expand All @@ -121,6 +123,8 @@ function attach(fb::GLFramebuffer, key::Symbol, buffer, attachment::GLenum)
type = "depth"
elseif attachment == GL_STENCIL_ATTACHMENT
type = "stencil"
elseif attachment == GL_DEPTH_STENCIL_ATTACHMENT
type = "depth-stencil"
else
type = "color"
end
Expand Down Expand Up @@ -178,7 +182,7 @@ function Base.show(io::IO, fb::GLFramebuffer)
X, Y = fb.size
print(io, "$X×$Y GLFrameBuffer(:")
join(io, string.(keys(fb.buffers)), ", :")
print(io, ")")
print(io, ") with id ", fb.id)
end

function attachment_enum_to_string(x::GLenum)
Expand All @@ -190,7 +194,7 @@ end

function Base.show(io::IO, ::MIME"text/plain", fb::GLFramebuffer)
X, Y = fb.size
print(io, "$X×$Y GLFrameBuffer()")
print(io, "$X×$Y GLFrameBuffer() with id ", fb.id)

ks = collect(keys(fb.buffers))
key_strings = [":$k" for k in ks]
Expand Down
90 changes: 67 additions & 23 deletions GLMakie/src/glwindow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,30 @@ end
Base.convert(::Type{SelectionID{T}}, s::SelectionID) where T = SelectionID{T}(T(s.id), T(s.index))
Base.zero(::Type{GLMakie.SelectionID{T}}) where T = SelectionID{T}(T(0), T(0))

mutable struct Framebuffer
mutable struct FramebufferFactory
fb::GLFramebuffer
buffers::Dict{Symbol, Texture} # TODO: temp, should be unnamed collection
render_buffer_ids::Vector{GLuint}
children::Vector{GLFramebuffer} # TODO: how else can we handle resizing?
end

# it's guaranteed, that they all have the same size
# forwards... for now
Base.size(fb::Framebuffer) = size(fb.fb)
Base.haskey(fb::Framebuffer, key::Symbol) = haskey(fb.fb, key)
GLAbstraction.get_attachment(fb::Framebuffer, key::Symbol) = get_attachment(fb.fb, key)
GLAbstraction.get_buffer(fb::Framebuffer, key::Symbol) = get_buffer(fb.fb, key)
GLAbstraction.bind(fb::Framebuffer) = GLAbstraction.bind(fb.fb)
GLAbstraction.attach_colorbuffer(fb::Framebuffer, key, val) = GLAbstraction.attach_colorbuffer(fb.fb, key, val)
function getfallback_attachment(fb::Framebuffer, key::Symbol, fallback_key::Symbol)
haskey(fb, key) ? get_attachment(fb, key) : get_attachment(fb, fallback_key)
end
function getfallback_buffer(fb::Framebuffer, key::Symbol, fallback_key::Symbol)
haskey(fb, key) ? get_buffer(fb, key) : get_buffer(fb, fallback_key)
end
# TODO: forwards... for now
Base.size(fb::FramebufferFactory) = size(fb.fb)
Base.haskey(fb::FramebufferFactory, key::Symbol) = haskey(fb.buffers, key)
GLAbstraction.get_buffer(fb::FramebufferFactory, key::Symbol) = fb.buffers[key]
GLAbstraction.bind(fb::FramebufferFactory) = GLAbstraction.bind(fb.fb)

function Base.resize!(fb::FramebufferFactory, w::Int, h::Int)
foreach(tex -> GLAbstraction.resize_nocopy!(tex, (w, h)), values(fb.buffers))
resize!(fb.fb, w, h)
filter!(fb -> fb.id != 0, fb.children) # TODO: is this ok?
foreach(fb -> resize!(fb, w, h), fb.children)
return
end

Makie.@noconstprop function Framebuffer(fb_size::NTuple{2, Int})
# Create framebuffer
fb = GLFramebuffer(fb_size)

Makie.@noconstprop function FramebufferFactory(fb_size::NTuple{2, Int})
# Buffers we always need
# Holds the image that eventually gets displayed
color_buffer = Texture(
Expand All @@ -59,20 +58,65 @@ Makie.@noconstprop function Framebuffer(fb_size::NTuple{2, Int})
N0f8, fb_size, minfilter = :nearest, x_repeat = :clamp_to_edge
)

buffers = Dict{Symbol, Texture}(
:color => color_buffer,
:objectid => objectid_buffer,
:HDR_color => HDR_color_buffer,
:OIT_weight => OIT_weight_buffer,
:depth_stencil => depth_buffer,
)

# Create render framebuffer
fb = GLFramebuffer(fb_size)

# attach buffers
color_attachment = attach_colorbuffer(fb, :color, color_buffer)
objectid_attachment = attach_colorbuffer(fb, :objectid, objectid_buffer)
attach_colorbuffer(fb, :HDR_color, HDR_color_buffer)
attach_colorbuffer(fb, :OIT_weight, OIT_weight_buffer)
attach_depthbuffer(fb, :depth, depth_buffer)
attach_stencilbuffer(fb, :stencil, depth_buffer)
attach_depthstencilbuffer(fb, :depth_stencil, depth_buffer)
attach_colorbuffer(fb, :HDR_color, HDR_color_buffer) # TODO: framebuffer for RenderPlots
attach_colorbuffer(fb, :OIT_weight, OIT_weight_buffer) # TODO: framebuffer for RenderPlots

check_framebuffer()

return FramebufferFactory(fb, buffers, [color_attachment, objectid_attachment], GLFramebuffer[])
end

# TODO: temporary
function Base.push!(factory::FramebufferFactory, kv::Pair{Symbol, <: Texture})
if haskey(factory.buffers, kv[1])
@error("Pushed buffer $(kv[1]) already assigned.")
return
end
push!(factory.buffers, kv)
return
end

function generate_framebuffer(factory::FramebufferFactory, names...)
filter!(fb -> fb.id != 0, factory.children) # cleanup?

parse_arg(name::Symbol) = name => name
parse_arg(p::Pair{Symbol, Symbol}) = p
parse_arg(x::Any) = error("$x not accepted")

fb = GLFramebuffer(size(factory.fb))
attach_depthstencilbuffer(fb, :depth_stencil, factory.buffers[:depth_stencil])

for arg in names
lookup, name = parse_arg(arg)
haskey(factory.buffers, lookup) || error("Add buffers yourself for now")
haskey(fb, name) && error("Can't add duplicate buffer $lookup => $name")
in(lookup, [:depth, :stencil]) && error("Depth and stencil always exist under the same name.")

attach_colorbuffer(fb, name, factory.buffers[lookup])
end

check_framebuffer()

return Framebuffer(fb, [color_attachment, objectid_attachment])
push!(factory.children, fb)

return fb
end

Base.resize!(fb::Framebuffer, w::Int, h::Int) = resize!(fb.fb, w, h)


struct MonitorProperties
Expand Down
8 changes: 4 additions & 4 deletions GLMakie/src/picking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
function pick_native(screen::Screen, rect::Rect2i)
isopen(screen) || return Matrix{SelectionID{Int}}(undef, 0, 0)
ShaderAbstractions.switch_context!(screen.glscreen)
fb = screen.framebuffer
fb = screen.framebuffer_factory
buff = get_buffer(fb, :objectid)
GLAbstraction.bind(fb)
glReadBuffer(GL_COLOR_ATTACHMENT1)
Expand All @@ -27,7 +27,7 @@ end
function pick_native(screen::Screen, xy::Vec{2, Float64})
isopen(screen) || return SelectionID{Int}(0, 0)
ShaderAbstractions.switch_context!(screen.glscreen)
fb = screen.framebuffer
fb = screen.framebuffer_factory
buff = get_buffer(fb, :objectid)
GLAbstraction.bind(fb)
glReadBuffer(GL_COLOR_ATTACHMENT1)
Expand Down Expand Up @@ -70,7 +70,7 @@ function Makie.pick_closest(scene::Scene, screen::Screen, xy, range)
w, h = size(screen.scene) # unitless dimensions
((1.0 <= xy[1] <= w) && (1.0 <= xy[2] <= h)) || return (nothing, 0)

fb = screen.framebuffer
fb = screen.framebuffer_factory
ppu = screen.px_per_unit[]
w, h = size(fb) # pixel dimensions
x0, y0 = max.(1, floor.(Int, ppu .* (xy .- range)))
Expand Down Expand Up @@ -111,7 +111,7 @@ function Makie.pick_sorted(scene::Scene, screen::Screen, xy, range)
return Tuple{AbstractPlot, Int}[]
end

fb = screen.framebuffer
fb = screen.framebuffer_factory
ppu = screen.px_per_unit[]
w, h = size(fb) # pixel dimensions
x0, y0 = max.(1, floor.(Int, ppu .* (xy .- range)))
Expand Down
Loading

0 comments on commit 9abac6d

Please sign in to comment.