37 return gl46core::UseProgramStageMask::GL_NONE_BIT;
44 U64 _linkLogRetrievalTime{ 0u };
45 std::array<
U64,
to_base(ShaderType::COUNT)> _stageCompileTime{};
46 std::array<
U64,
to_base(ShaderType::COUNT)> _stageCompileLogRetrievalTime{};
74 const U64 ret = timer.get();
79 TimingData timingData{};
98 _handle = gl46core::glCreateProgram();
99 gl46core::glProgramParameteri(_handle, gl46core::GL_PROGRAM_BINARY_RETRIEVABLE_HINT, gl46core::GL_FALSE);
100 gl46core::glProgramParameteri(_handle, gl46core::GL_PROGRAM_SEPARABLE, gl46core::GL_TRUE);
109 bool shouldLink =
false;
118 assert(!data._compiled);
126 DIVIDE_ASSERT(shader != 0u && !data._sourceCodeSpirV.empty() && !data._sourceCodeGLSL.empty());
128 if constexpr(g_useSPIRVBinaryCode)
131 gl46core::glShaderBinary(1, &shader, gl46core::GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, data._sourceCodeSpirV.data(), (gl46core::GLsizei)(data._sourceCodeSpirV.size() *
sizeof(
SpvWord)));
132 gl46core::glSpecializeShader(shader,
"main", 0,
nullptr,
nullptr);
137 const char* src = data._sourceCodeGLSL.c_str();
138 gl46core::glShaderSource(shader, 1u, &src,
nullptr);
139 gl46core::glCompileShader(shader);
144 timingData._stageCompileTime[
to_base(data._type)] += getTimerAndReset(timers[1]);
150 gl46core::GLboolean compiled = 0;
151 gl46core::glGetShaderiv(shader, gl46core::GL_COMPILE_STATUS, &compiled);
152 if (compiled == gl46core::GL_FALSE)
155 gl46core::GLint logSize = 0;
156 gl46core::glGetShaderiv(shader, gl46core::GL_INFO_LOG_LENGTH, &logSize);
157 string validationBuffer;
158 validationBuffer.resize(
to_size(logSize) );
160 gl46core::glGetShaderInfoLog(shader, logSize, &logSize, &validationBuffer[0]);
161 if (validationBuffer.size() > g_validationBufferMaxSize)
164 validationBuffer.resize(std::strlen(
LOCALE_STR(
"ERROR_GLSL_COMPILE")) * 2 + g_validationBufferMaxSize);
166 validationBuffer.append(
" ... ");
171 gl46core::glDeleteShader(shader);
176 gl46core::glAttachShader(_handle, shader);
178 data._compiled =
true;
184 timingData._stageCompileLogRetrievalTime[
to_base(data._type)] += getTimerAndReset(timers[1]);
196 gl46core::glLinkProgram(_handle);
202 timingData._linkTime = getTimerAndReset(timers[1]);
207 gl46core::GLboolean linkStatus = gl46core::GL_FALSE;
208 gl46core::glGetProgramiv(_handle, gl46core::GL_LINK_STATUS, &linkStatus);
211 if (linkStatus == gl46core::GL_FALSE)
213 gl46core::GLint logSize = 0;
214 gl46core::glGetProgramiv(_handle, gl46core::GL_INFO_LOG_LENGTH, &logSize);
215 string validationBuffer;
216 validationBuffer.resize(
to_size(logSize));
218 gl46core::glGetProgramInfoLog(_handle, logSize,
nullptr, &validationBuffer[0]);
219 if (validationBuffer.size() > g_validationBufferMaxSize)
222 validationBuffer.resize(std::strlen(
LOCALE_STR(
"GLSL_LINK_PROGRAM_LOG")) + g_validationBufferMaxSize);
224 validationBuffer.append(
" ... ");
235 gl46core::glObjectLabel( gl46core::GL_PROGRAM,
245 timingData._linkLogRetrievalTime = getTimerAndReset(timers[1]);
246 timingData._totalTime = getTimerAndReset(timers[0]);
249 U8 hotspotIndex = 0u;
250 U64 maxHotspotTimer = 0u;
251 string perStageTiming =
"";
254 perStageTiming.append(
Util::StringFormat(
"---- [ {} ] - [{:5.5f} ms] - [{:5.5f} ms]\n",
256 Time::MicrosecondsToMilliseconds<F32>(timingData._stageCompileTime[i]),
257 Time::MicrosecondsToMilliseconds<F32>(timingData._stageCompileLogRetrievalTime[i])));
258 if (timingData._stageCompileTime[i] > maxHotspotTimer)
260 maxHotspotTimer = timingData._stageCompileTime[i];
264 if (timingData._stageCompileLogRetrievalTime[i] > maxHotspotTimer)
266 maxHotspotTimer = timingData._stageCompileLogRetrievalTime[i];
274 Time::MicrosecondsToMilliseconds<F32>(timingData._totalTime),
275 Time::MicrosecondsToMilliseconds<F32>(timingData._linkTime),
276 Time::MicrosecondsToMilliseconds<F32>(timingData._linkLogRetrievalTime),
278 perStageTiming.c_str());
288 _valid =
false;
_linked =
false;
298 _stageMask = gl46core::UseProgramStageMask::GL_NONE_BIT;
306 assert(!it._sourceCodeGLSL.empty() || !it._sourceCodeSpirV.empty());
307 _stageMask |= GetStageMask(it._type);
310 if (_stageMask == gl46core::UseProgramStageMask::GL_NONE_BIT)
322 const std::string_view name,
323 const U32 targetGeneration,
329 ._generation = targetGeneration
335 if (shader_ptr ==
nullptr || shader_ptr->generation() < ret._generation )
340 if (!
static_cast<glShader*
>(shader_ptr.get())->
load(data))
350 ret._shader =
static_cast<glShader*
>(shader_ptr.get());
363 gl46core::glDetachShader(_handle, shader);
364 gl46core::glDeleteShader(shader);
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
static bool DeleteShaderPrograms(gl46core::GLuint count, gl46core::GLuint *programs)
FORCE_INLINE I64 getGUID() const noexcept
GFXDevice & context() const noexcept
PlatformContext & context() noexcept
void registerParent(ShaderProgram *parent)
static SharedMutex s_shaderNameLock
static ShaderMap s_shaderNameMap
std::array< LoadData, to_base(ShaderType::COUNT)> ShaderLoadData
void uploadPushConstants(const PushConstantsStruct &pushConstants)
gl46core::GLint _pushConstantsLocation
vector< gl46core::GLuint > _shaderIDs
static glShaderEntry LoadShader(GFXDevice &context, glShaderProgram *parent, const std::string_view name, U32 targetGeneration, ShaderProgram::ShaderLoadData &data)
Add or refresh a shader from the cache.
bool load(const ShaderProgram::ShaderLoadData &data)
ShaderProgram::ShaderLoadData _loadData
glShader(GFXDevice &context, const std::string_view name, const U32 generation)
void onParentValidation()
ShaderResult uploadToGPU()
OpenGL implementation of the ShaderProgram entity.
static void Idle(PlatformContext &platformContext)
constexpr bool ENABLE_GPU_VALIDATION
Error callbacks, validations, buffer checks, etc. are controlled by this flag. Heavy performance impa...
std::array< gl46core::GLenum, to_base(ShaderType::COUNT)> glShaderStageTable
static constexpr const char * shaderTypes[]
Str StringFormat(const char *fmt, Args &&...args)
size_t g_validationBufferMaxSize
FORCE_INLINE gl46core::UseProgramStageMask GetStageMask(const ShaderType type) noexcept
constexpr bool g_useSPIRVBinaryCode
Handle console commands that start with a forward slash.
std::lock_guard< mutex > LockGuard
constexpr gl46core::GLuint GL_NULL_HANDLE
Invalid object value. Used to compare handles and determine if they were properly created.
constexpr U64 _ID(const char *const str, const U64 value=val_64_const) noexcept
void efficient_clear(eastl::fixed_vector< T, nodeCount, bEnableOverflow, OverflowAllocator > &fixed_vector)
constexpr size_t to_size(const T value)
ShaderType
Available shader stages.
constexpr auto to_base(const Type value) -> Type
static NO_INLINE void d_printfn(const char *format, T &&... args)
static NO_INLINE void errorfn(const char *format, T &&... args)
static NO_INLINE void printfn(const char *format, T &&... args)
const F32 * dataPtr() const