Skip to content

Commit

Permalink
[GL] Make retrieval of program binary more robust
Browse files Browse the repository at this point in the history
* Added check if any binary formats are supported before
trying to query the binary. MacOS happens to support the
extension but does not actually support any formats.

* Avoid using GetError for checking if retrieval is successful.
On no error contexts there no errors might be generated.
Instead we check if the written length is correct.
  • Loading branch information
hyazinthh committed Dec 11, 2023
1 parent d5b2dff commit ec9300b
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 18 deletions.
7 changes: 7 additions & 0 deletions src/Aardvark.Rendering.GL/Core/Context.fs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ type Context(runtime : IRuntime, createContext : unit -> ContextHandle) as this

let mutable maxComputeWorkGroupInvocations : Option<int> = None

let mutable numProgramBinaryFormats : Option<int> = None

let mutable shaderCachePath : Option<string> = Some defaultShaderCachePath

let formatSampleCounts = FastConcurrentDict()
Expand Down Expand Up @@ -311,6 +313,11 @@ type Context(runtime : IRuntime, createContext : unit -> ContextHandle) as this
GL.GetInteger(GetPName.MaxComputeWorkGroupInvocations)
)

member x.NumProgramBinaryFormats =
getOrQuery &numProgramBinaryFormats (fun _ ->
GL.GetInteger(GetPName.NumProgramBinaryFormats)
)

member internal x.ImportMemoryBlock(external : ExternalMemoryBlock) =
sharedMemoryManager.Import external

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,20 @@ module ARB_get_program_binary =
if GL.ARB_get_program_binary then
GL.GetProgramBinary(program, bufSize, &length, &binaryFormat, binary)
else
failwith "glGetProgramBinary is not available."
failwith "glGetProgramBinary is not available."

static member GetProgramBinary(program : int, length : int) =
let data : byte[] = Array.zeroCreate length
let mutable format = Unchecked.defaultof<BinaryFormat>
let mutable returnedLength = length
GL.Dispatch.GetProgramBinary(program, length, &returnedLength, &format, data)

if returnedLength = length then
data, format
else
null, format

static member GetProgramBinaryLength(program : int) =
let mutable result = 0
GL.GetProgram(program, GetProgramParameterName.ProgramBinaryLength, &result)
result
37 changes: 20 additions & 17 deletions src/Aardvark.Rendering.GL/Resources/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,10 @@ module ProgramExtensions =
GL.Check "could not create program"

try
if GL.ARB_get_program_binary then
GL.ProgramParameter(handle, ProgramParameterName.ProgramBinaryRetrievableHint, 1)
GL.Check "could not set program binary retrievable hint"

for s in shaders do
GL.AttachShader(handle, s.Handle)
GL.Check "could not attach shader to program"
Expand Down Expand Up @@ -634,29 +638,28 @@ module ProgramExtensions =
module Program =

let tryGetBinary (program : Program) =
if GL.ARB_get_program_binary then
GL.GetError() |> ignore
if GL.ARB_get_program_binary && program.Context.NumProgramBinaryFormats > 0 then
let length = GL.Dispatch.GetProgramBinaryLength program.Handle
GL.Check "failed to get program binary length"

let mutable length = 0
GL.GetProgram(program.Handle, GetProgramParameterName.ProgramBinaryLength, &length)
if length > 0 then
let data, format = GL.Dispatch.GetProgramBinary(program.Handle, length)
GL.Check "failed to get program binary"

let err = GL.GetError()
if err <> ErrorCode.NoError then
Log.warn "[GL] Failed to query program binary length: %A" err
None
else
let data : byte[] = Array.zeroCreate length
let mutable format = Unchecked.defaultof<BinaryFormat>
GL.GetProgramBinary(program.Handle, length, &length, &format, data)

let err = GL.GetError()
if err <> ErrorCode.NoError then
Log.warn "[GL] Failed to retrieve program binary: %A" err
if isNull data then
Log.warn "[GL] Failed to retrieve program binary"
None
else
Some (format, data)
else
Log.warn "[GL] Program binary length is zero bytes"
None
else
Report.Line(4, "[GL] Cannot read shader cache because GL_ARB_get_program_binary is not supported")
let reason =
if GL.ARB_get_program_binary then "no binary formats are supported"
else "GL_ARB_get_program_binary is not supported"

Report.Line(4, $"[GL] Cannot read shader cache because {reason}")
None

let ofShaderCacheEntry (context : Context) (fixBindings : bool) (entry : ShaderCacheEntry) =
Expand Down

0 comments on commit ec9300b

Please sign in to comment.