[Feat] (DiligentEngine): Implement most rendering by DiligentEngine.

This commit is contained in:
BZLZHH
2025-06-07 19:41:32 +08:00
parent c95077f263
commit f5a14c20a9
29 changed files with 3146 additions and 313 deletions
@@ -5,6 +5,15 @@
#include "GL_Buffer.h"
namespace MG_GL::GL {
Diligent::VALUE_TYPE ConvertGLIndexTypeToDiligent(GLenum type) {
switch (type) {
case GL_UNSIGNED_BYTE: return Diligent::VT_UINT8;
case GL_UNSIGNED_SHORT: return Diligent::VT_UINT16;
case GL_UNSIGNED_INT: return Diligent::VT_UINT32;
default: return Diligent::VT_UNDEFINED;
}
}
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
GLbitfield access) {
MG_Util::Debug::LogD("glMapBufferRange, target: %s, offset: %lld, length: %lld, access: 0x%X",
@@ -31,6 +40,30 @@ namespace MG_GL::GL {
static_cast<long long>(length));
GLenum result = MG_State::SyncBufferMemory(target, offset, length);
if (result == GL_NO_ERROR) {
GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target);
if (buffer == 0) return;
auto& bufferObj = MG_State_T::bufferState->buffers_[buffer];
if (!bufferObj.isMapped) return;
size_t start = static_cast<size_t>(offset);
size_t end = start + static_cast<size_t>(length);
Diligent::IBuffer* pBuffer = MG_Diligent::g_BufferMap[buffer];
if (pBuffer && bufferObj.data.size() >= end) {
void * data;
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE,
Diligent::MAP_FLAG_NONE, data);
if (data) {
void* dst = static_cast<char*>(data) + offset;
const void* src = bufferObj.data.data() + offset;
memcpy(dst, src, length);
MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE);
}
}
return;
}
MG_State::SetError(result);
@@ -50,6 +83,22 @@ namespace MG_GL::GL {
static_cast<long long>(size));
GLenum result = MG_State::CopyBufferRange(readTarget, writeTarget, readOffset, writeOffset, size);
if (result == GL_NO_ERROR) {
GLuint srcBuffer = MG_State_T::bufferState->GetCurrentBinding(readTarget);
GLuint dstBuffer = MG_State_T::bufferState->GetCurrentBinding(writeTarget);
if (srcBuffer == 0 || dstBuffer == 0) return;
Diligent::IBuffer* pSrcBuffer = MG_Diligent::g_BufferMap[srcBuffer];
Diligent::IBuffer* pDstBuffer = MG_Diligent::g_BufferMap[dstBuffer];
if (pSrcBuffer && pDstBuffer) {
MG_Diligent::g_pContext->CopyBuffer(pSrcBuffer, static_cast<Diligent::Uint64>(readOffset),
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
pDstBuffer, static_cast<Diligent::Uint64>(writeOffset),
static_cast<Diligent::Uint64>(size),
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
}
return;
}
MG_State::SetError(result);
@@ -78,6 +127,22 @@ namespace MG_GL::GL {
MG_Util::Debug::LogE("glUnmapBuffer failed: %s", MG_Util::Debug::GLEnumToString(err));
return GL_FALSE;
}
GLuint buffer = MG_State_T::bufferState->currentBindings_[target];
auto& bufferObj = MG_State_T::bufferState->buffers_[buffer];
Diligent::IBuffer* pBuffer = MG_Diligent::g_BufferMap[buffer];
if (pBuffer) {
void * data;
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE,
Diligent::MAP_FLAG_NONE, data);
if (data) {
memcpy(data, bufferObj.data.data(), bufferObj.data.size());
MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE);
}
}
MG_Util::Debug::LogD("glUnmapBuffer succeeded");
return GL_TRUE;
}
@@ -112,8 +177,82 @@ namespace MG_GL::GL {
MG_Util::Debug::LogD("glBufferData, target: %s, size: %zd, data: %p, usage: %s",
MG_Util::Debug::GLEnumToString(target), size, data, MG_Util::Debug::GLEnumToString(usage));
GLenum result = MG_State::CommitBufferStorage(target, size, data, usage);
if (result == GL_NO_ERROR)
if (result == GL_NO_ERROR) {
GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target);
if (buffer == 0) return;
Diligent::IBuffer*& pBuffer = MG_Diligent::g_BufferMap[buffer];
Diligent::BufferDesc BuffDesc;
BuffDesc.Name = "Buffer";
BuffDesc.Size = static_cast<Diligent::Uint64>(size);
switch (target) {
case GL_ARRAY_BUFFER:
BuffDesc.BindFlags = Diligent::BIND_VERTEX_BUFFER;
break;
case GL_ELEMENT_ARRAY_BUFFER:
BuffDesc.BindFlags = Diligent::BIND_INDEX_BUFFER;
break;
case GL_UNIFORM_BUFFER:
BuffDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
break;
default:
BuffDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE;
break;
}
switch (usage) {
case GL_STATIC_DRAW:
BuffDesc.Usage = Diligent::USAGE_UNIFIED;
BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE;
break;
case GL_DYNAMIC_DRAW:
BuffDesc.Usage = Diligent::USAGE_UNIFIED;
BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE;
break;
case GL_STREAM_DRAW:
BuffDesc.Usage = Diligent::USAGE_UNIFIED;
BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE;
break;
default:
BuffDesc.Usage = Diligent::USAGE_DEFAULT;
break;
}
if (pBuffer == nullptr) {
Diligent::BufferData BuffData;
// Initial data must not be null for immutable buffers
if (BuffDesc.Usage == Diligent::USAGE_IMMUTABLE) {
BuffData.pData = data;
}
else {
BuffData.pData = nullptr;
}
BuffData.DataSize = static_cast<Diligent::Uint64>(size);
MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, &BuffData, &pBuffer);
}
if (data != nullptr) {
if (BuffDesc.Usage == Diligent::USAGE_DEFAULT ||
BuffDesc.Usage == Diligent::USAGE_SPARSE) {
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, 0,
static_cast<Diligent::Uint64>(size), data,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
} else if (BuffDesc.Usage == Diligent::USAGE_UNIFIED ||
BuffDesc.Usage == Diligent::USAGE_STAGING ||
BuffDesc.Usage == Diligent::USAGE_DYNAMIC) {
void *pMappedData = nullptr;
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE,
Diligent::MAP_FLAG_NONE, pMappedData);
if (pMappedData) {
memcpy(pMappedData, data, size);
MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE);
}
}
}
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -140,8 +279,9 @@ namespace MG_GL::GL {
GLenum result = MG_State::GenBufferNames(n, buffers);
if (result == GL_NO_ERROR) {
MG_Util::Debug::LogD("Generated buffer names:");
for (GLsizei i = 0; i < n; ++i) {
for (GLsizei i = 0; i < n; ++i) {
MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]);
MG_Diligent::g_BufferMap[buffers[i]] = nullptr;
}
return;
}
@@ -174,13 +314,32 @@ namespace MG_GL::GL {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target);
if (buffer == 0) return;
Diligent::IBuffer* pBuffer = MG_Diligent::g_BufferMap[buffer];
if (pBuffer) {
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, static_cast<Diligent::Uint64>(offset),
static_cast<Diligent::Uint64>(size), data,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
}
}
void DeleteBuffers(GLsizei n, const GLuint *buffers) {
MG_Util::Debug::LogD("glDeleteBuffers, n: %d, buffers: %p", n, buffers);
GLenum result = MG_State::DeleteBuffers(n, buffers);
if (result == GL_NO_ERROR)
if (result == GL_NO_ERROR) {
for (GLsizei i = 0; i < n; ++i) {
GLuint buffer = buffers[i];
if (buffer != 0) {
Diligent::IBuffer* pBuffer = MG_Diligent::g_BufferMap[buffer];
if (pBuffer) pBuffer->Release();
MG_Diligent::g_BufferMap.erase(buffer);
}
}
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
@@ -6,19 +6,73 @@
namespace MG_GL::GL {
void Clear(GLbitfield mask) {
MG_Util::Debug::LogD("glClear, mask: 0x%X", mask);
GLenum result = MG_State::glClear(mask);
if (result == GL_NO_ERROR) {
GLuint drawFramebuffer = MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER];
if (drawFramebuffer == 0) {
drawFramebuffer = 0;
}
auto it = MG_Diligent::g_FramebufferMap.find(drawFramebuffer);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Util::Debug::LogE("Framebuffer not found: %u", drawFramebuffer);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error clearing buffers: %s", MG_Util::Debug::GLEnumToString(result));
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
auto& commonState = *MG_State_T::commonState;
/*if (!MG_Diligent::IsInRenderPass) {
if (fbInfo.pRenderPass && fbInfo.pFramebuffer) {
Diligent::BeginRenderPassAttribs beginRenderPassAttribs;
beginRenderPassAttribs.pFramebuffer = fbInfo.pFramebuffer;
beginRenderPassAttribs.pRenderPass = fbInfo.pRenderPass;
beginRenderPassAttribs.StateTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
beginRenderPassAttribs.ClearValueCount = fbInfo.ClearValues.size();
beginRenderPassAttribs.pClearValues = fbInfo.ClearValues.data();
MG_Diligent::g_pContext->BeginRenderPass(beginRenderPassAttribs);
MG_Diligent::IsInRenderPass = true;
} else {
MG_Util::Debug::LogE("Cannot begin render pass for framebuffer: %u", drawFramebuffer);
return;
}
}*/
if (mask & GL_COLOR_BUFFER_BIT) {
for (size_t i = 0; i < fbInfo.ColorRTVs.size(); ++i) {
if (fbInfo.ColorRTVs[i]) {
MG_Diligent::g_pContext->ClearRenderTarget(
fbInfo.ColorRTVs[i],
commonState.clearColor,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
}
}
}
if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
if (fbInfo.pDepthStencilRTV) {
Diligent::Uint32 clearFlags = 0;
if (mask & GL_DEPTH_BUFFER_BIT) clearFlags |= Diligent::CLEAR_DEPTH_FLAG;
if (mask & GL_STENCIL_BUFFER_BIT) clearFlags |= Diligent::CLEAR_STENCIL_FLAG;
MG_Diligent::g_pContext->ClearDepthStencil(
fbInfo.pDepthStencilRTV,
static_cast<Diligent::CLEAR_DEPTH_STENCIL_FLAGS>(clearFlags),
commonState.clearDepth,
0,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
}
}
}
void Enable(GLenum cap) {
MG_Util::Debug::LogD("glEnable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
GLenum result = MG_State::glEnable(cap);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error enabling capability: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -26,7 +80,10 @@ namespace MG_GL::GL {
void Disable(GLenum cap) {
MG_Util::Debug::LogD("glDisable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
GLenum result = MG_State::glDisable(cap);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error disabling capability: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -36,7 +93,10 @@ namespace MG_GL::GL {
MG_Util::Debug::GLEnumToString(sfactor),
MG_Util::Debug::GLEnumToString(dfactor));
GLenum result = MG_State::glBlendFunc(sfactor, dfactor);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting blend func: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -48,7 +108,10 @@ namespace MG_GL::GL {
MG_Util::Debug::GLEnumToString(srcAlpha),
MG_Util::Debug::GLEnumToString(dstAlpha));
GLenum result = MG_State::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting separate blend func: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -56,7 +119,10 @@ namespace MG_GL::GL {
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
MG_Util::Debug::LogD("glClearColor, rgba: [%.2f, %.2f, %.2f, %.2f]", red, green, blue, alpha);
GLenum result = MG_State::glClearColor(red, green, blue, alpha);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting clear color: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -64,7 +130,10 @@ namespace MG_GL::GL {
void ClearDepth(GLdouble depth) {
MG_Util::Debug::LogD("glClearDepth, depth: %.3f", depth);
GLenum result = MG_State::glClearDepth(depth);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting clear depth: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -72,7 +141,10 @@ namespace MG_GL::GL {
void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
MG_Util::Debug::LogD("glColorMask, rgba: [%d, %d, %d, %d]", red, green, blue, alpha);
GLenum result = MG_State::glColorMask(red, green, blue, alpha);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting color mask: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -80,7 +152,10 @@ namespace MG_GL::GL {
void DepthFunc(GLenum func) {
MG_Util::Debug::LogD("glDepthFunc, func: %s", MG_Util::Debug::GLEnumToString(func));
GLenum result = MG_State::glDepthFunc(func);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting depth func: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -88,7 +163,10 @@ namespace MG_GL::GL {
void DepthMask(GLboolean flag) {
MG_Util::Debug::LogD("glDepthMask, flag: %d", flag);
GLenum result = MG_State::glDepthMask(flag);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting depth mask: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -97,7 +175,9 @@ namespace MG_GL::GL {
MG_Util::Debug::LogD("glViewport, x: %d, y: %d, width: %d, height: %d",
x, y, width, height);
GLenum result = MG_State::glViewport(x, y, width, height);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error setting viewport: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -105,8 +185,10 @@ namespace MG_GL::GL {
void PixelStorei(GLenum pname, GLint param) {
MG_Util::Debug::LogD("glPixelStorei, pname: %d, param: %d", pname, param);
GLenum result = MG_State::SetPixelStoreInt(pname,param);
if (result == GL_NO_ERROR)
if (result == GL_NO_ERROR) {
MG_Diligent::g_PSOManager.MarkPSODirty(MG_State_T::programState->currentProgram_);
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -5,10 +5,500 @@
#include "GL_Drawing.h"
namespace MG_GL::GL {
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) {
// TODO
void CreateRenderPassAndFramebuffer(GLuint framebuffer,
const FramebufferObject& fbo,
MG_Diligent::GLFramebufferInfo& fbInfo);
inline bool IsSamplerType(GLenum type) {
switch (type) {
case GL_SAMPLER_2D:
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_2D_ARRAY:
case GL_SAMPLER_2D_ARRAY_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
return true;
default:
return false;
}
}
inline size_t GetUniformSize(GLenum type) {
switch (type) {
case GL_FLOAT: return sizeof(float);
case GL_FLOAT_VEC2: return 2 * sizeof(float);
case GL_FLOAT_VEC3: return 3 * sizeof(float);
case GL_FLOAT_VEC4: return 4 * sizeof(float);
case GL_FLOAT_MAT2: return 4 * sizeof(float);
case GL_FLOAT_MAT3: return 9 * sizeof(float);
case GL_FLOAT_MAT4: return 16 * sizeof(float);
case GL_INT:
case GL_BOOL:
return sizeof(int);
case GL_INT_VEC2: return 2 * sizeof(int);
case GL_INT_VEC3: return 3 * sizeof(int);
case GL_INT_VEC4: return 4 * sizeof(int);
case GL_UNSIGNED_INT: return sizeof(uint32_t);
case GL_UNSIGNED_INT_VEC2: return 2 * sizeof(uint32_t);
case GL_UNSIGNED_INT_VEC3: return 3 * sizeof(uint32_t);
case GL_UNSIGNED_INT_VEC4: return 4 * sizeof(uint32_t);
// case GL_DOUBLE: return sizeof(double); // Not supported
// case GL_DOUBLE_VEC2: return 2 * sizeof(double); // Not supported
// case GL_DOUBLE_VEC3: return 3 * sizeof(double); // Not supported
// case GL_DOUBLE_VEC4: return 4 * sizeof(double); // Not supported
default: return 0;
}
}
inline size_t AlignSize(size_t size, size_t alignment) {
return (size + alignment - 1) & ~(alignment - 1);
}
inline Diligent::SHADER_TYPE GetDiligentShaderType(GLenum shaderType) {
switch (shaderType) {
case GL_VERTEX_SHADER:
return Diligent::SHADER_TYPE_VERTEX;
case GL_FRAGMENT_SHADER:
return Diligent::SHADER_TYPE_PIXEL;
case GL_GEOMETRY_SHADER:
return Diligent::SHADER_TYPE_GEOMETRY;
case GL_COMPUTE_SHADER:
return Diligent::SHADER_TYPE_COMPUTE;
case GL_TESS_CONTROL_SHADER:
return Diligent::SHADER_TYPE_DOMAIN;
case GL_TESS_EVALUATION_SHADER:
return Diligent::SHADER_TYPE_HULL;
default:
return Diligent::SHADER_TYPE_UNKNOWN;
}
}
Diligent::SHADER_TYPE GetShaderStageForUniform(GLuint program, const std::string& name) {
auto& programInfo = MG_Diligent::g_ProgramMap[program];
auto& programObj = MG_State_T::programState->programs_[program];
auto it = programInfo.uniformStages.find(name);
if (it != programInfo.uniformStages.end()) {
return it->second;
}
Diligent::SHADER_TYPE stage = Diligent::SHADER_TYPE_ALL;
for (auto shader : programInfo.AttachedShadersID) {
auto& shaderObj = MG_State_T::programState->shaders_[shader];
if (shaderObj.compiledSpirv.empty()) continue;
spvc_context context = nullptr;
spvc_parsed_ir parsed_ir = nullptr;
spvc_compiler compiler = nullptr;
spvc_resources resources = nullptr;
spvc_result result = spvc_context_create(&context);
if (result != SPVC_SUCCESS) continue;
result = spvc_context_parse_spirv(context,
reinterpret_cast<const SpvId*>(shaderObj.compiledSpirv.data()),
shaderObj.compiledSpirv.size() / sizeof(SpvId),
&parsed_ir);
if (result != SPVC_SUCCESS) {
spvc_context_destroy(context);
continue;
}
result = spvc_context_create_compiler(context, SPVC_BACKEND_GLSL,
parsed_ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler);
if (result != SPVC_SUCCESS) {
spvc_context_destroy(context);
continue;
}
result = spvc_compiler_create_shader_resources(compiler, &resources);
if (result != SPVC_SUCCESS) {
spvc_context_destroy(context);
continue;
}
const spvc_reflected_resource* resourceList = nullptr;
size_t resourceCount = 0;
spvc_resources_get_resource_list_for_type(
resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER,
&resourceList, &resourceCount);
for (size_t i = 0; i < resourceCount; i++) {
if (strcmp(resourceList[i].name, name.c_str()) == 0) {
stage = GetDiligentShaderType(shaderObj.type);
break;
}
}
spvc_resources_get_resource_list_for_type(
resources, SPVC_RESOURCE_TYPE_SAMPLED_IMAGE,
&resourceList, &resourceCount);
for (size_t i = 0; i < resourceCount; i++) {
if (strcmp(resourceList[i].name, name.c_str()) == 0) {
stage = GetDiligentShaderType(shaderObj.type);
break;
}
}
spvc_resources_get_resource_list_for_type(
resources, SPVC_RESOURCE_TYPE_STORAGE_IMAGE,
&resourceList, &resourceCount);
for (size_t i = 0; i < resourceCount; i++) {
if (strcmp(resourceList[i].name, name.c_str()) == 0) {
stage = GetDiligentShaderType(shaderObj.type);
break;
}
}
spvc_resources_get_resource_list_for_type(
resources, SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS,
&resourceList, &resourceCount);
for (size_t i = 0; i < resourceCount; i++) {
if (strcmp(resourceList[i].name, name.c_str()) == 0) {
stage = GetDiligentShaderType(shaderObj.type);
break;
}
}
spvc_context_destroy(context);
}
if (stage == Diligent::SHADER_TYPE_ALL)
stage = Diligent::SHADER_TYPE_VERTEX;
programInfo.uniformStages[name] = stage;
return stage;
}
void UpdateSamplerAndTextureUniforms(GLuint program) {
auto& programInfo = MG_Diligent::g_ProgramMap[program];
auto& programObj = MG_State_T::programState->programs_[program];
if (!programInfo.pResourceBinding) return;
for (auto& [name, uniform] : programObj.uniformValues) {
if (!IsSamplerType(uniform.type)) continue;
Diligent::IShaderResourceVariable* pVar =
programInfo.pResourceBinding->GetVariableByName(
GetShaderStageForUniform(program, name.c_str()), name.c_str());
if (!pVar) continue;
GLuint textureID = 0;
if (!uniform.intData.empty()) {
textureID = static_cast<GLuint>(uniform.intData[0]);
}
Diligent::ITextureView* pTextureView = nullptr;
if (textureID != 0) {
auto it = MG_Diligent::g_TextureViewMap.find(textureID);
if (it != MG_Diligent::g_TextureViewMap.end()) {
pTextureView = it->second;
}
}
if (pTextureView) {
pVar->Set(pTextureView);
}
}
}
void UpdateUniformsToDefaultUBO(GLuint program) {
MG_Util::Debug::LogD("Updating uniforms to default UBO for program %u", program);
auto& programInfo = MG_Diligent::g_ProgramMap[program];
auto& programObj = MG_State_T::programState->programs_[program];
if (programObj.uniformValues.empty() || !programInfo.pDefaultUBO) {
return;
}
void * mapped;
MG_Util::Debug::LogD("Mapping UBO for program %u", program);
MG_Diligent::g_pContext->MapBuffer(programInfo.pDefaultUBO, Diligent::MAP_WRITE,
Diligent::MAP_FLAG_DISCARD, mapped);
if (mapped) {
MG_Util::Debug::LogD("UBO mapped successfully for program %u. Updating uniform values.", program);
uint8_t* uboData = static_cast<uint8_t*>(mapped);
for (auto& [name, uniform] : programObj.uniformValues) {
if (IsSamplerType(uniform.type)) continue;
auto it = programInfo.uniformOffsets.find(name);
if (it != programInfo.uniformOffsets.end()) {
size_t offset = it->second;
// MG_Util::Debug::LogD("Updating uniform '%s' at offset %zu for program %u", name.c_str(), offset, program);
switch (uniform.type) {
case GL_FLOAT:
*reinterpret_cast<float*>(uboData + offset) = uniform.floatData[0];
break;
case GL_FLOAT_VEC2:
memcpy(uboData + offset, uniform.floatData.data(), 2 * sizeof(float));
break;
case GL_FLOAT_VEC3:
memcpy(uboData + offset, uniform.floatData.data(), 3 * sizeof(float));
break;
case GL_FLOAT_VEC4:
memcpy(uboData + offset, uniform.floatData.data(), 4 * sizeof(float));
break;
case GL_FLOAT_MAT2:
memcpy(uboData + offset, uniform.floatData.data(), 4 * sizeof(float));
break;
case GL_FLOAT_MAT3:
memcpy(uboData + offset, uniform.floatData.data(), 9 * sizeof(float));
break;
case GL_FLOAT_MAT4:
memcpy(uboData + offset, uniform.floatData.data(), 16 * sizeof(float));
break;
case GL_INT:
case GL_BOOL:
*reinterpret_cast<int*>(uboData + offset) = uniform.intData[0];
break;
case GL_INT_VEC2:
memcpy(uboData + offset, uniform.intData.data(), 2 * sizeof(int));
break;
case GL_INT_VEC3:
memcpy(uboData + offset, uniform.intData.data(), 3 * sizeof(int));
break;
case GL_INT_VEC4:
memcpy(uboData + offset, uniform.intData.data(), 4 * sizeof(int));
break;
case GL_UNSIGNED_INT:
*reinterpret_cast<uint32_t*>(uboData + offset) = uniform.uintData[0];
break;
case GL_UNSIGNED_INT_VEC2:
memcpy(uboData + offset, uniform.uintData.data(), 2 * sizeof(uint32_t));
break;
case GL_UNSIGNED_INT_VEC3:
memcpy(uboData + offset, uniform.uintData.data(), 3 * sizeof(uint32_t));
break;
case GL_UNSIGNED_INT_VEC4:
memcpy(uboData + offset, uniform.uintData.data(), 4 * sizeof(uint32_t));
break;
// Not supported types
// case GL_DOUBLE:
// *reinterpret_cast<double*>(uboData + offset) = uniform.doubleData[0];
// break;
// case GL_DOUBLE_VEC2:
// memcpy(uboData + offset, uniform.doubleData.data(), 2 * sizeof(double));
// break;
// case GL_DOUBLE_VEC3:
// memcpy(uboData + offset, uniform.doubleData.data(), 3 * sizeof(double));
// break;
// case GL_DOUBLE_VEC4:
// memcpy(uboData + offset, uniform.doubleData.data(), 4 * sizeof(double));
// break;
// case GL_DOUBLE_MAT2:
// memcpy(uboData + offset, uniform.doubleData.data(), 4 * sizeof(double));
// break;
// case GL_DOUBLE_MAT3:
// memcpy(uboData + offset, uniform.doubleData.data(), 9 * sizeof(double));
// break;
// case GL_DOUBLE_MAT4:
// memcpy(uboData + offset, uniform.doubleData.data(), 16 * sizeof(double));
// break;
// ...
}
}
}
MG_Util::Debug::LogD("Finished updating uniform values in UBO for program %u.", program);
} else {
MG_Util::Debug::LogE("Failed to map UBO for program %u.", program);
}
MG_Util::Debug::LogD("Unmapping UBO for program %u", program);
MG_Diligent::g_pContext->UnmapBuffer(programInfo.pDefaultUBO, Diligent::MAP_WRITE);
}
void EnsureRenderPassActive() {
MG_Util::Debug::LogD("EnsureRenderPassActive called.");
if (MG_Diligent::IsInRenderPass) {
MG_Util::Debug::LogD("Render pass is already active.");
return;
}
MG_Util::Debug::LogD("Render pass is not active, attempting to begin one.");
GLuint drawFB = MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER];
if (drawFB == 0) {
MG_Util::Debug::LogD("drawFB is 0, using default framebuffer (0).");
drawFB = 0;
}
auto it = MG_Diligent::g_FramebufferMap.find(drawFB);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Util::Debug::LogE("Framebuffer %u not found in g_FramebufferMap.", drawFB);
return;
}
MG_Util::Debug::LogD("Found framebuffer %u in g_FramebufferMap.", drawFB);
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
if (!fbInfo.pRenderPass || !fbInfo.pFramebuffer) {
MG_Util::Debug::LogD("RenderPass or Framebuffer not yet created for FBO %u. Creating now.", drawFB);
FramebufferObject* pFBO = MG_State_T::framebufferState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER);
if (!pFBO) {
MG_Util::Debug::LogE("No current FBO found for GL_DRAW_FRAMEBUFFER when trying to create RenderPass/Framebuffer.");
return;
}
CreateRenderPassAndFramebuffer(drawFB, *pFBO, fbInfo);
if (!fbInfo.pRenderPass || !fbInfo.pFramebuffer) {
MG_Util::Debug::LogE("Failed to create RenderPass or Framebuffer for FBO %u.", drawFB);
return;
}
MG_Util::Debug::LogD("Successfully created RenderPass and Framebuffer for FBO %u.", drawFB);
}
MG_Util::Debug::LogD("Proceeding to begin render pass for FBO %u.", drawFB);
if (fbInfo.pRenderPass && fbInfo.pFramebuffer) {
Diligent::BeginRenderPassAttribs beginRenderPassAttribs;
beginRenderPassAttribs.pFramebuffer = fbInfo.pFramebuffer;
beginRenderPassAttribs.pRenderPass = fbInfo.pRenderPass;
beginRenderPassAttribs.StateTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
beginRenderPassAttribs.ClearValueCount = fbInfo.ClearValues.size();
beginRenderPassAttribs.pClearValues = fbInfo.ClearValues.data();
MG_Diligent::g_pContext->BeginRenderPass(beginRenderPassAttribs);
MG_Diligent::IsInRenderPass = true;
} else {
MG_Util::Debug::LogE("RenderPass or Framebuffer not yet created for FBO %u.", drawFB);
}
}
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
GLuint program = MG_State::GetCurrentProgram();
MG_Util::Debug::LogD("DrawElements called with mode: %d, count: %d, type: %d, program: %u", mode, count, type, program);
if (program == 0) {
MG_Util::Debug::LogE("No active program for DrawElements");
return;
}
auto& programInfo = MG_Diligent::g_ProgramMap[program];
GLuint drawFB = MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER];
if (drawFB == 0) drawFB = 0;
auto itFB = MG_Diligent::g_FramebufferMap.find(drawFB);
if (itFB == MG_Diligent::g_FramebufferMap.end()) {
MG_Util::Debug::LogE("Framebuffer not found: %u", drawFB);
return;
}
MG_Diligent::GLFramebufferInfo& fbInfo = itFB->second;
MG_Util::Debug::LogD("Fetching PSO for program %u", program);
programInfo.pPipelineState = MG_Diligent::g_PSOManager.GetOrCreatePSO(
program,
programInfo,
*MG_State_T::commonState,
*MG_State_T::vertexArrayState,
fbInfo
);
if (!programInfo.pPipelineState) {
MG_Util::Debug::LogE("Failed to get or create PSO for program %u", program);
return;
}
MG_Util::Debug::LogD("Successfully obtained PSO for program %u", program);
if (!programInfo.pResourceBinding) {
MG_Util::Debug::LogD("Creating ShaderResourceBinding for program %u", program);
programInfo.pPipelineState->CreateShaderResourceBinding(
&programInfo.pResourceBinding, true);
if (!programInfo.pResourceBinding) {
MG_Util::Debug::LogE("Failed to create ShaderResourceBinding for program %u", program);
return;
}
MG_Util::Debug::LogD("Successfully created ShaderResourceBinding for program %u", program);
}
MG_Diligent::g_pContext->SetPipelineState(programInfo.pPipelineState);
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
if (pVAO) {
std::vector<Diligent::IBuffer*> vertexBuffers;
std::vector<Diligent::Uint32> offsets;
for (auto& attrib : pVAO->attribs) {
if (!attrib.second.enabled) {
MG_Util::Debug::LogD("Vertex attribute %u is not enabled, skipping.", attrib.first);
continue;
}
GLuint buffer = attrib.second.buffer;
if (buffer != 0) {
MG_Util::Debug::LogD("Processing vertex attribute %u with buffer %u", attrib.first, buffer);
auto it = MG_Diligent::g_BufferMap.find(buffer);
if (it != MG_Diligent::g_BufferMap.end()) {
MG_Util::Debug::LogD("Found buffer %u in g_BufferMap", buffer);
vertexBuffers.push_back(it->second);
offsets.push_back(static_cast<Diligent::Uint32>(
reinterpret_cast<size_t>(attrib.second.pointer)));
} else {
MG_Util::Debug::LogW("Buffer %u not found in g_BufferMap for vertex attribute %u", buffer, attrib.first);
}
}
}
if (!vertexBuffers.empty()) {
MG_Util::Debug::LogD("Setting %zu vertex buffers", vertexBuffers.size());
MG_Diligent::g_pContext->SetVertexBuffers(
0, vertexBuffers.size(), vertexBuffers.data(),
(const Diligent::Uint64*) offsets.data(),
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
Diligent::SET_VERTEX_BUFFERS_FLAG_RESET
);
}
if (pVAO->elementBuffer != 0) {
MG_Util::Debug::LogD("Processing element buffer %u", pVAO->elementBuffer);
auto it = MG_Diligent::g_BufferMap.find(pVAO->elementBuffer);
if (it != MG_Diligent::g_BufferMap.end()) {
MG_Util::Debug::LogD("Found element buffer %u in g_BufferMap, setting index buffer.", pVAO->elementBuffer);
MG_Diligent::g_pContext->SetIndexBuffer(
it->second, 0,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
} else {
MG_Util::Debug::LogW("Element buffer %u not found in g_BufferMap.", pVAO->elementBuffer);
}
}
} else {
MG_Util::Debug::LogD("No current VAO found.");
}
MG_Util::Debug::LogD("Updating uniforms for program %u", program);
UpdateUniformsToDefaultUBO(program);
UpdateSamplerAndTextureUniforms(program);
MG_Util::Debug::LogD("Committing shader resources for program %u", program);
MG_Diligent::g_pContext->CommitShaderResources(
programInfo.pResourceBinding,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
MG_Util::Debug::LogD("Preparing to draw indexed for program %u", program);
Diligent::DrawIndexedAttribs drawAttrs;
drawAttrs.IndexType = ConvertGLTypeToDiligent(type);
drawAttrs.NumIndices = count;
drawAttrs.Flags = Diligent::DRAW_FLAG_VERIFY_ALL;
drawAttrs.IndexType = Diligent::VT_UINT32;
EnsureRenderPassActive();
MG_Diligent::g_pContext->DrawIndexed(drawAttrs);
MG_Diligent::g_pContext->EndRenderPass();
MG_Diligent::IsInRenderPass = false;
MG_Util::Debug::LogD("DrawIndexed completed.");
}
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
// TODO
}
@@ -5,10 +5,225 @@
#include "GL_Framebuffer.h"
namespace MG_GL::GL {
void ReleaseFramebufferResources(MG_Diligent::GLFramebufferInfo& fbInfo) {
if (fbInfo.pFramebuffer) {
fbInfo.pFramebuffer->Release();
fbInfo.pFramebuffer = nullptr;
}
if (fbInfo.pRenderPass) {
fbInfo.pRenderPass->Release();
fbInfo.pRenderPass = nullptr;
}
for (auto& rtv : fbInfo.ColorRTVs) {
if (rtv) {
rtv->Release();
rtv = nullptr;
}
}
fbInfo.ColorRTVs.clear();
if (fbInfo.pDepthStencilRTV) {
fbInfo.pDepthStencilRTV->Release();
fbInfo.pDepthStencilRTV = nullptr;
}
}
void CreateRenderPassAndFramebuffer(GLuint framebuffer,
const FramebufferObject& fbo,
MG_Diligent::GLFramebufferInfo& fbInfo) {
Diligent::Uint32 width = 0;
Diligent::Uint32 height = 0;
if (framebuffer == 0) {
if (MG_Diligent::g_pSwapChain) {
width = MG_Diligent::g_pSwapChain->GetDesc().Width;
height = MG_Diligent::g_pSwapChain->GetDesc().Height;
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Using swap chain dimensions: %ux%u", width, height);
} else {
MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Swap chain not initialized for default framebuffer");
return;
}
}
else {
if (!fbInfo.ColorRTVs.empty() && fbInfo.ColorRTVs[0]) {
const auto& desc = fbInfo.ColorRTVs[0]->GetTexture()->GetDesc();
width = desc.Width;
height = desc.Height;
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Using color attachment 0 for dimensions: %ux%u", width, height);
} else if (fbInfo.pDepthStencilRTV) {
const auto& desc = fbInfo.pDepthStencilRTV->GetTexture()->GetDesc();
width = desc.Width;
height = desc.Height;
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Using depth/stencil attachment for dimensions: %ux%u", width, height);
} else {
MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Failed to determine framebuffer dimensions. No attachments.");
return;
}
}
if (width == 0 || height == 0) {
MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Failed to determine framebuffer dimensions. Width or Height is 0.");
return;
}
Diligent::RenderPassDesc RPDesc;
std::vector<Diligent::RenderPassAttachmentDesc> Attachments;
std::vector<Diligent::SubpassDesc> Subpasses;
std::vector<Diligent::AttachmentReference> ColorRefs;
for (size_t i = 0; i < fbInfo.ColorRTVs.size(); ++i) {
if (fbInfo.ColorRTVs[i]) {
Diligent::RenderPassAttachmentDesc ColorAttachment;
ColorAttachment.Format = fbInfo.ColorRTVs[i]->GetDesc().Format;
ColorAttachment.SampleCount = 1;
ColorAttachment.InitialState = Diligent::RESOURCE_STATE_RENDER_TARGET;
ColorAttachment.FinalState = Diligent::RESOURCE_STATE_RENDER_TARGET;
ColorAttachment.LoadOp = Diligent::ATTACHMENT_LOAD_OP_LOAD;
ColorAttachment.StoreOp = Diligent::ATTACHMENT_STORE_OP_STORE;
Attachments.push_back(ColorAttachment);
Diligent::AttachmentReference ColorRef;
ColorRef.AttachmentIndex = static_cast<Diligent::Uint32>(Attachments.size() - 1);
ColorRef.State = Diligent::RESOURCE_STATE_RENDER_TARGET;
ColorRefs.push_back(ColorRef);
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Added color attachment %zu", i);
}
}
Diligent::AttachmentReference DepthRef;
if (fbInfo.pDepthStencilRTV) {
Diligent::RenderPassAttachmentDesc DepthAttachment;
DepthAttachment.Format = fbInfo.DepthStencilFormat;
DepthAttachment.SampleCount = 1;
DepthAttachment.InitialState = Diligent::RESOURCE_STATE_DEPTH_WRITE;
DepthAttachment.FinalState = Diligent::RESOURCE_STATE_DEPTH_WRITE;
DepthAttachment.LoadOp = Diligent::ATTACHMENT_LOAD_OP_LOAD;
DepthAttachment.StoreOp = Diligent::ATTACHMENT_STORE_OP_STORE;
DepthAttachment.StencilLoadOp = Diligent::ATTACHMENT_LOAD_OP_LOAD;
DepthAttachment.StencilStoreOp = Diligent::ATTACHMENT_STORE_OP_STORE;
Attachments.push_back(DepthAttachment);
DepthRef.AttachmentIndex = static_cast<Diligent::Uint32>(Attachments.size() - 1);
DepthRef.State = Diligent::RESOURCE_STATE_DEPTH_WRITE;
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Added depth/stencil attachment");
}
Diligent::SubpassDesc Subpass;
Subpass.RenderTargetAttachmentCount = static_cast<Diligent::Uint32>(ColorRefs.size());
Subpass.pRenderTargetAttachments = ColorRefs.empty() ? nullptr : ColorRefs.data();
Subpass.pDepthStencilAttachment = fbInfo.pDepthStencilRTV ? &DepthRef : nullptr;
Subpasses.push_back(Subpass);
RPDesc.AttachmentCount = static_cast<Diligent::Uint32>(Attachments.size());
RPDesc.pAttachments = Attachments.empty() ? nullptr : Attachments.data();
RPDesc.SubpassCount = static_cast<Diligent::Uint32>(Subpasses.size());
RPDesc.pSubpasses = Subpasses.data();
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Creating RenderPass with %u attachments and %u subpasses.",
RPDesc.AttachmentCount, RPDesc.SubpassCount);
MG_Diligent::g_pDevice->CreateRenderPass(RPDesc, &fbInfo.pRenderPass);
if (!fbInfo.pRenderPass) {
MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Failed to create RenderPass.");
return;
}
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: RenderPass created successfully.");
Diligent::FramebufferDesc FBDesc;
FBDesc.Name = "Framebuffer";
FBDesc.pRenderPass = fbInfo.pRenderPass;
FBDesc.AttachmentCount = static_cast<Diligent::Uint32>(Attachments.size());
std::vector<Diligent::ITextureView *> FBAtachments(Attachments.size());
for (size_t i = 0; i < ColorRefs.size(); ++i) {
if (i < fbInfo.ColorRTVs.size() && fbInfo.ColorRTVs[i]) {
FBAtachments[i] = fbInfo.ColorRTVs[i];
}
}
if (fbInfo.pDepthStencilRTV) {
FBAtachments[ColorRefs.size()] = fbInfo.pDepthStencilRTV;
}
FBDesc.ppAttachments = FBAtachments.data();
FBDesc.Width = width;
FBDesc.Height = height;
FBDesc.NumArraySlices = 1;
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Creating Framebuffer '%s' with %u attachments, Dimensions: %ux%u.",
FBDesc.Name, FBDesc.AttachmentCount, FBDesc.Width, FBDesc.Height);
fbInfo.ClearValues.clear();
for (size_t i = 0; i < fbInfo.ColorRTVs.size(); ++i) {
Diligent::OptimizedClearValue clearValue;
clearValue.Color[0] = 0.0f;
clearValue.Color[1] = 0.0f;
clearValue.Color[2] = 0.0f;
clearValue.Color[3] = 1.0f;
fbInfo.ClearValues.push_back(clearValue);
}
if (fbInfo.pDepthStencilRTV) {
Diligent::OptimizedClearValue clearValue;
clearValue.DepthStencil.Depth = 1.0f;
clearValue.DepthStencil.Stencil = 0;
fbInfo.ClearValues.push_back(clearValue);
}
MG_Diligent::g_pDevice->CreateFramebuffer(FBDesc, &fbInfo.pFramebuffer);
if (!fbInfo.pFramebuffer) {
MG_Util::Debug::LogE("CreateRenderPassAndFramebuffer: Failed to create Framebuffer.");
return;
}
MG_Util::Debug::LogD("CreateRenderPassAndFramebuffer: Framebuffer created successfully.");
}
void UpdateDefaultFramebuffer() {
auto it = MG_Diligent::g_FramebufferMap.find(0);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Diligent::g_FramebufferMap[0] = MG_Diligent::GLFramebufferInfo();
}
MG_Diligent::GLFramebufferInfo& fbInfo = MG_Diligent::g_FramebufferMap[0];
ReleaseFramebufferResources(fbInfo);
if (MG_Diligent::g_pSwapChain) {
Diligent::ITextureView* pRTV = MG_Diligent::g_pSwapChain->GetCurrentBackBufferRTV();
Diligent::ITextureView* pDSV = MG_Diligent::g_pSwapChain->GetDepthBufferDSV();
if (pRTV) {
fbInfo.ColorRTVs = {pRTV};
} else {
MG_Util::Debug::LogE("Failed to get swap chain back buffer RTV");
}
if (pDSV) {
fbInfo.pDepthStencilRTV = pDSV;
fbInfo.DepthStencilFormat = MG_Diligent::g_pSwapChain->GetDesc().DepthBufferFormat;
fbInfo.HasDepthStencil = true;
} else {
MG_Util::Debug::LogE("Failed to get swap chain depth buffer DSV");
}
CreateRenderPassAndFramebuffer(0, FramebufferObject(), fbInfo);
} else {
MG_Util::Debug::LogE("Swap chain not initialized for default framebuffer");
}
}
void GenFramebuffers(GLsizei n, GLuint* framebuffers) {
MG_Util::Debug::LogD("glGenFramebuffers, n: %d, framebuffers: %p", n, framebuffers);
GLenum result = MG_State::CreateFramebuffers(n, framebuffers);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
for (GLsizei i = 0; i < n; ++i) {
MG_Diligent::GLFramebufferInfo fbInfo;
MG_Diligent::g_FramebufferMap[framebuffers[i]] = fbInfo;
}
return;
};
MG_State::SetError(result);
MG_Util::Debug::LogE("Framebuffer generation failed: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -21,6 +236,30 @@ namespace MG_GL::GL {
MG_State::SetError(result);
MG_Util::Debug::LogE("Failed to delete framebuffer %u: %s",
framebuffers[i], MG_Util::Debug::GLEnumToString(result));
} else {
GLuint fb = framebuffers[i];
auto it = MG_Diligent::g_FramebufferMap.find(fb);
if (it != MG_Diligent::g_FramebufferMap.end()) {
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
if (fbInfo.pFramebuffer) {
fbInfo.pFramebuffer->Release();
}
if (fbInfo.pRenderPass) {
fbInfo.pRenderPass->Release();
}
for (auto& rtv : fbInfo.ColorRTVs) {
if (rtv) rtv->Release();
}
if (fbInfo.pDepthStencilRTV) {
fbInfo.pDepthStencilRTV->Release();
}
MG_Diligent::g_FramebufferMap.erase(it);
}
}
}
}
@@ -29,7 +268,51 @@ namespace MG_GL::GL {
MG_Util::Debug::LogD("glBindFramebuffer, target: %s, fb: %u",
MG_Util::Debug::GLEnumToString(target), framebuffer);
GLenum result = MG_State::BindFramebuffer(target, framebuffer);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
if (MG_Diligent::IsInRenderPass) {
MG_Diligent::g_pContext->EndRenderPass();
MG_Diligent::IsInRenderPass = false;
}
if (framebuffer == 0) {
UpdateDefaultFramebuffer();
}
FramebufferObject* pFBO = MG_State_T::framebufferState->GetCurrentFBO(target);
auto it = MG_Diligent::g_FramebufferMap.find(framebuffer);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Util::Debug::LogE("Framebuffer %u not found in map", framebuffer);
return;
}
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
if (!fbInfo.pRenderPass || !fbInfo.pFramebuffer) {
CreateRenderPassAndFramebuffer(framebuffer, pFBO ? *pFBO : FramebufferObject(), fbInfo);
}
MG_Diligent::g_pContext->SetRenderTargets(
static_cast<Diligent::Uint32>(fbInfo.ColorRTVs.size()),
fbInfo.ColorRTVs.empty() ? nullptr : fbInfo.ColorRTVs.data(),
fbInfo.pDepthStencilRTV,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
if (fbInfo.pRenderPass && fbInfo.pFramebuffer) {
Diligent::BeginRenderPassAttribs beginRenderPassAttribs;
beginRenderPassAttribs.pFramebuffer = fbInfo.pFramebuffer;
beginRenderPassAttribs.pRenderPass = fbInfo.pRenderPass;
beginRenderPassAttribs.ClearValueCount = fbInfo.ClearValues.size();
beginRenderPassAttribs.pClearValues = fbInfo.ClearValues.data();
beginRenderPassAttribs.StateTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
MG_Diligent::g_pContext->BeginRenderPass(beginRenderPassAttribs);
MG_Diligent::IsInRenderPass = true;
}
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Framebuffer bind error: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -42,11 +325,114 @@ namespace MG_GL::GL {
MG_Util::Debug::GLEnumToString(textarget),
texture, level);
GLuint currentFB = MG_State_T::framebufferState->currentBindings_[target];
GLenum result = MG_State::AttachTexture2DToFramebuffer(
target, attachment, textarget, texture, level
);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
auto it = MG_Diligent::g_FramebufferMap.find(currentFB);
if (it == MG_Diligent::g_FramebufferMap.end()) {
MG_Util::Debug::LogE("Framebuffer %u not found in map", currentFB);
return;
}
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
if (fbInfo.pFramebuffer) {
fbInfo.pFramebuffer->Release();
fbInfo.pFramebuffer = nullptr;
MG_Util::Debug::LogD("Released existing framebuffer");
}
if (fbInfo.pRenderPass) {
fbInfo.pRenderPass->Release();
fbInfo.pRenderPass = nullptr;
MG_Util::Debug::LogD("Released existing render pass");
}
if (texture == 0) {
MG_Util::Debug::LogD("Unbinding attachment: %s", MG_Util::Debug::GLEnumToString(attachment));
if (attachment == GL_DEPTH_ATTACHMENT ||
attachment == GL_STENCIL_ATTACHMENT ||
attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
if (fbInfo.pDepthStencilRTV) {
fbInfo.pDepthStencilRTV->Release();
fbInfo.pDepthStencilRTV = nullptr;
MG_Util::Debug::LogD("Released depth/stencil attachment");
}
} else {
size_t index = attachment - GL_COLOR_ATTACHMENT0;
if (index < fbInfo.ColorRTVs.size() && fbInfo.ColorRTVs[index]) {
fbInfo.ColorRTVs[index]->Release();
fbInfo.ColorRTVs[index] = nullptr;
MG_Util::Debug::LogD("Released color attachment %zu", index);
}
}
} else {
Diligent::ITexture* pTexture = MG_Diligent::g_TextureMap[texture];
if (!pTexture) {
MG_Util::Debug::LogE("Texture %u exists in map but pointer is null", texture);
return;
}
const auto& texDesc = pTexture->GetDesc();
MG_Util::Debug::LogD("Attaching texture: %s (size: %ux%u)",
texDesc.Name,
texDesc.Width, texDesc.Height);
Diligent::TextureViewDesc ViewDesc;
ViewDesc.TextureDim = Diligent::RESOURCE_DIM_TEX_2D;
ViewDesc.MostDetailedMip = level;
ViewDesc.NumMipLevels = 1;
if (attachment == GL_DEPTH_ATTACHMENT ||
attachment == GL_STENCIL_ATTACHMENT ||
attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
MG_Util::Debug::LogD("Creating depth/stencil attachment");
if (fbInfo.pDepthStencilRTV) {
fbInfo.pDepthStencilRTV->Release();
MG_Util::Debug::LogD("Released existing depth/stencil attachment");
}
ViewDesc.ViewType = Diligent::TEXTURE_VIEW_DEPTH_STENCIL;
fbInfo.DepthStencilFormat = texDesc.Format;
pTexture->CreateView(ViewDesc, &fbInfo.pDepthStencilRTV);
if (fbInfo.pDepthStencilRTV) {
fbInfo.HasDepthStencil = true;
MG_Util::Debug::LogD("Created new depth/stencil RTV");
} else {
MG_Util::Debug::LogE("Failed to create depth/stencil RTV");
}
} else {
size_t index = attachment - GL_COLOR_ATTACHMENT0;
MG_Util::Debug::LogD("Creating color attachment at index %zu", index);
if (index >= fbInfo.ColorRTVs.size()) {
fbInfo.ColorRTVs.resize(index + 1, nullptr);
MG_Util::Debug::LogD("Resized color attachments to %zu", fbInfo.ColorRTVs.size());
}
if (fbInfo.ColorRTVs[index]) {
fbInfo.ColorRTVs[index]->Release();
MG_Util::Debug::LogD("Released existing color attachment %zu", index);
}
ViewDesc.ViewType = Diligent::TEXTURE_VIEW_RENDER_TARGET;
pTexture->CreateView(ViewDesc, &fbInfo.ColorRTVs[index]);
if (fbInfo.ColorRTVs[index]) {
MG_Util::Debug::LogD("Created new color RTV at index %zu", index);
} else {
MG_Util::Debug::LogE("Failed to create color RTV at index %zu", index);
}
}
}
MG_Util::Debug::LogD("FramebufferTexture2D completed successfully");
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Texture attachment failed: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -56,8 +442,7 @@ namespace MG_GL::GL {
MG_Util::Debug::GLEnumToString(target));
GLenum result = MG_State::ValidateFramebufferCompleteness(target);
if (result >= GL_FRAMEBUFFER_COMPLETE) {
MG_Util::Debug::LogD("Framebuffer status: %s",
MG_Util::Debug::GLEnumToString(result));
MG_Util::Debug::LogD("Framebuffer status: %s", MG_Util::Debug::GLEnumToString(result));
return result;
}
MG_State::SetError(result);
@@ -68,6 +453,64 @@ namespace MG_GL::GL {
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
// TODO
GLuint readFB = MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER];
GLuint drawFB = MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER];
MG_Diligent::GLFramebufferInfo* pSrcFB = nullptr;
MG_Diligent::GLFramebufferInfo* pDstFB = nullptr;
if (readFB != 0) pSrcFB = &MG_Diligent::g_FramebufferMap[readFB];
if (drawFB != 0) pDstFB = &MG_Diligent::g_FramebufferMap[drawFB];
if (!pSrcFB) pSrcFB = &MG_Diligent::g_FramebufferMap[0];
if (!pDstFB) pDstFB = &MG_Diligent::g_FramebufferMap[0];
bool copyColor = (mask & GL_COLOR_BUFFER_BIT) != 0;
bool copyDepth = (mask & GL_DEPTH_BUFFER_BIT) != 0;
bool copyStencil = (mask & GL_STENCIL_BUFFER_BIT) != 0;
if (copyColor && !pSrcFB->ColorRTVs.empty() && !pDstFB->ColorRTVs.empty()) {
for (size_t i = 0; i < pSrcFB->ColorRTVs.size() && i < pDstFB->ColorRTVs.size(); ++i) {
if (pSrcFB->ColorRTVs[i] && pDstFB->ColorRTVs[i]) {
Diligent::CopyTextureAttribs CopyAttribs;
CopyAttribs.pSrcTexture = pSrcFB->ColorRTVs[i]->GetTexture();
CopyAttribs.pDstTexture = pDstFB->ColorRTVs[i]->GetTexture();
CopyAttribs.SrcTextureTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
CopyAttribs.DstTextureTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
Diligent::Box SrcBox;
SrcBox.MinX = srcX0;
SrcBox.MinY = srcY0;
SrcBox.MaxX = srcX1;
SrcBox.MaxY = srcY1;
CopyAttribs.pSrcBox = &SrcBox;
CopyAttribs.DstX = dstX0;
CopyAttribs.DstY = dstY0;
MG_Diligent::g_pContext->CopyTexture(CopyAttribs);
}
}
}
if ((copyDepth || copyStencil) && pSrcFB->pDepthStencilRTV && pDstFB->pDepthStencilRTV) {
Diligent::CopyTextureAttribs CopyAttribs;
CopyAttribs.pSrcTexture = pSrcFB->pDepthStencilRTV->GetTexture();
CopyAttribs.pDstTexture = pDstFB->pDepthStencilRTV->GetTexture();
CopyAttribs.SrcTextureTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
CopyAttribs.DstTextureTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
Diligent::Box SrcBox;
SrcBox.MinX = srcX0;
SrcBox.MinY = srcY0;
SrcBox.MaxX = srcX1;
SrcBox.MaxY = srcY1;
CopyAttribs.pSrcBox = &SrcBox;
CopyAttribs.DstX = dstX0;
CopyAttribs.DstY = dstY0;
MG_Diligent::g_pContext->CopyTexture(CopyAttribs);
}
}
}
}
@@ -8,6 +8,8 @@
#include "../../../../Includes.h"
namespace MG_GL::GL {
void UpdateDefaultFramebuffer();
void GenFramebuffers(GLsizei n, GLuint* framebuffers);
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
void BindFramebuffer(GLenum target, GLuint framebuffer);
@@ -4,13 +4,162 @@
#include "GL_Program.h"
#undef MOBILEGL_GLSLTOOL_H
#include "../../../../Includes.h"
namespace MG_GL::GL {
inline bool IsSamplerType(GLenum type) {
switch (type) {
case GL_SAMPLER_2D:
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_2D_ARRAY:
case GL_SAMPLER_2D_ARRAY_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
return true;
default:
return false;
}
}
inline size_t GetUniformSize(GLenum type) {
switch (type) {
case GL_FLOAT: return sizeof(float);
case GL_FLOAT_VEC2: return 2 * sizeof(float);
case GL_FLOAT_VEC3: return 3 * sizeof(float);
case GL_FLOAT_VEC4: return 4 * sizeof(float);
case GL_FLOAT_MAT2: return 4 * sizeof(float);
case GL_FLOAT_MAT3: return 9 * sizeof(float);
case GL_FLOAT_MAT4: return 16 * sizeof(float);
case GL_INT:
case GL_BOOL:
return sizeof(int);
case GL_INT_VEC2: return 2 * sizeof(int);
case GL_INT_VEC3: return 3 * sizeof(int);
case GL_INT_VEC4: return 4 * sizeof(int);
case GL_UNSIGNED_INT: return sizeof(uint32_t);
case GL_UNSIGNED_INT_VEC2: return 2 * sizeof(uint32_t);
case GL_UNSIGNED_INT_VEC3: return 3 * sizeof(uint32_t);
case GL_UNSIGNED_INT_VEC4: return 4 * sizeof(uint32_t);
default: return 0;
}
}
inline size_t AlignSize(size_t size, size_t alignment) {
return (size + alignment - 1) & ~(alignment - 1);
}
void CreateDefaultUBO(MG_Diligent::GLProgramInfo& programInfo) {
MG_Util::Debug::LogD("CreateDefaultUBO for program");
size_t uboSize = 0;
std::vector<size_t> uniformSizes;
for (auto& [name, uniform] : programInfo.programObj.uniformValues) {
if (IsSamplerType(uniform.type)) continue;
size_t size = GetUniformSize(uniform.type);
size_t alignedSize = AlignSize(size, 16);
uniformSizes.push_back(alignedSize);
MG_Util::Debug::LogD(" Uniform '%s': size = %zu, alignedSize = %zu",
name.c_str(), size, alignedSize);
uboSize += alignedSize;
}
if (uboSize > 0) {
Diligent::BufferDesc BuffDesc;
BuffDesc.Name = "MG_DEFAULT_UBO";
BuffDesc.Size = uboSize;
BuffDesc.Usage = Diligent::USAGE_DYNAMIC;
BuffDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE;
MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, nullptr, &programInfo.pDefaultUBO);
MG_Util::Debug::LogD("Created default UBO: size = %zu", uboSize);
} else {
MG_Util::Debug::LogD("No non-sampler uniforms found, default UBO not created.");
}
}
void RecordUniformOffsets(MG_Diligent::GLProgramInfo& programInfo) {
MG_Util::Debug::LogD("RecordUniformOffsets for program");
size_t offset = 0;
programInfo.uniformOffsets.clear();
for (auto& [name, uniform] : programInfo.programObj.uniformValues) {
if (IsSamplerType(uniform.type)) continue;
size_t size = GetUniformSize(uniform.type);
size_t alignedSize = AlignSize(size, 16);
programInfo.uniformOffsets[name] = offset;
MG_Util::Debug::LogD(" Uniform '%s': offset = %zu, size = %zu, alignedSize = %zu",
name.c_str(), offset, size, alignedSize);
offset += alignedSize;
}
}
Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type) {
switch (type) {
case GL_FLOAT: return Diligent::VT_FLOAT32;
case GL_FLOAT_VEC2: return Diligent::VT_FLOAT32;
case GL_FLOAT_VEC3: return Diligent::VT_FLOAT32;
case GL_FLOAT_VEC4: return Diligent::VT_FLOAT32;
case GL_INT: return Diligent::VT_INT32;
case GL_INT_VEC2: return Diligent::VT_INT32;
case GL_INT_VEC3: return Diligent::VT_INT32;
case GL_INT_VEC4: return Diligent::VT_INT32;
case GL_UNSIGNED_INT: return Diligent::VT_UINT32;
case GL_UNSIGNED_INT_VEC2: return Diligent::VT_UINT32;
case GL_UNSIGNED_INT_VEC3: return Diligent::VT_UINT32;
case GL_UNSIGNED_INT_VEC4: return Diligent::VT_UINT32;
case GL_FLOAT_MAT2: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT3: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT4: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT2x3: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT2x4: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT3x2: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT3x4: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT4x2: return Diligent::VT_FLOAT32;
case GL_FLOAT_MAT4x3: return Diligent::VT_FLOAT32;
default: return Diligent::VT_UNDEFINED;
}
}
GLint GetGLTypeComponentCount(GLenum type) {
switch (type) {
case GL_FLOAT: return 1;
case GL_FLOAT_VEC2: return 2;
case GL_FLOAT_VEC3: return 3;
case GL_FLOAT_VEC4: return 4;
case GL_INT: return 1;
case GL_INT_VEC2: return 2;
case GL_INT_VEC3: return 3;
case GL_INT_VEC4: return 4;
case GL_UNSIGNED_INT: return 1;
case GL_UNSIGNED_INT_VEC2: return 2;
case GL_UNSIGNED_INT_VEC3: return 3;
case GL_UNSIGNED_INT_VEC4: return 4;
case GL_FLOAT_MAT2: return 4;
case GL_FLOAT_MAT3: return 9;
case GL_FLOAT_MAT4: return 16; // 4 * 4
case GL_FLOAT_MAT2x3: return 6; // 2 * 3
case GL_FLOAT_MAT2x4: return 8; // 2 * 4
case GL_FLOAT_MAT3x2: return 6; // 3 * 2
case GL_FLOAT_MAT3x4: return 12; // 3 * 4
case GL_FLOAT_MAT4x2: return 8; // 4 * 2
case GL_FLOAT_MAT4x3: return 12; // 4 * 3
default: return 0;
}
}
GLuint CreateShader(GLenum type) {
MG_Util::Debug::LogD("glCreateShader, type: %s", MG_Util::Debug::GLEnumToString(type));
GLuint shader;
GLenum result = MG_State::CreateShader(type, &shader);
if (result == GL_NO_ERROR) {
MG_Util::Debug::LogD("Created shader ID: %u", shader);
MG_Diligent::g_ShaderMap[shader] = nullptr;
return shader;
}
MG_State::SetError(result);
@@ -34,7 +183,16 @@ namespace MG_GL::GL {
void DeleteShader(GLuint shader) {
MG_Util::Debug::LogD("glDeleteShader, shader: %u", shader);
GLenum result = MG_State::DeleteShader(shader);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
auto it = MG_Diligent::g_ShaderMap.find(shader);
if (it != MG_Diligent::g_ShaderMap.end()) {
if (it->second) {
it->second->Release();
}
MG_Diligent::g_ShaderMap.erase(it);
}
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error deleting shader: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -42,7 +200,9 @@ namespace MG_GL::GL {
void DeleteProgram(GLuint program) {
MG_Util::Debug::LogD("glDeleteProgram, program: %u", program);
GLenum result = MG_State::DeleteProgram(program);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error deleting program: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -50,7 +210,9 @@ namespace MG_GL::GL {
void AttachShader(GLuint program, GLuint shader) {
MG_Util::Debug::LogD("glAttachShader, program: %u, shader: %u", program, shader);
GLenum result = MG_State::LinkShaderToProgram(program, shader);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error attaching shader: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -65,16 +227,114 @@ namespace MG_GL::GL {
void CompileShader(GLuint shader) {
MG_Util::Debug::LogD("glCompileShader, shader: %u", shader);
// Defer actual compilation to LinkProgram
GLenum result = MG_State::BuildShaderStage(shader);
if (result == GL_NO_ERROR) return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error compiling shader: %s", MG_Util::Debug::GLEnumToString(result));
MG_Util::Debug::LogE("Error marking shader for compilation: %s", MG_Util::Debug::GLEnumToString(result));
}
void LinkProgram(GLuint program) {
MG_Util::Debug::LogD("glLinkProgram, program: %u", program);
GLenum result = MG_State::FinalizeProgramPipeline(program);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
auto& programInfo = MG_Diligent::g_ProgramMap[program];
auto& programObj = MG_State_T::programState->programs_[program];
for (const auto& shaderId : programObj.attachedShaders) {
programInfo.AttachedShadersID.push_back(shaderId);
}
MG_Global::unordered_map<GLuint, std::string> shaderSources;
for (GLuint shaderId : programInfo.AttachedShadersID) {
auto& shaderObj = MG_State_T::programState->shaders_[shaderId];
shaderSources[shaderId] = shaderObj.source;
}
MG_Util::Program::GenerateDefaultUBOForGLSL_Multi(shaderSources);
// Compile attached shaders
for (GLuint shaderId : programInfo.AttachedShadersID) {
auto& shaderObj = MG_State_T::programState->shaders_[shaderId];
// Compile only if not already compiled in Diligent
if (MG_Diligent::g_ShaderMap.find(shaderId) == MG_Diligent::g_ShaderMap.end() || MG_Diligent::g_ShaderMap[shaderId] == nullptr) {
GLenum shaderType = shaderObj.type;
std::string sourceStr = shaderSources[shaderId];
Diligent::ShaderCreateInfo ShaderCI;
ShaderCI.Source = sourceStr.c_str();
ShaderCI.EntryPoint = "main";
switch (shaderType) {
case GL_VERTEX_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_VERTEX; break;
case GL_FRAGMENT_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_PIXEL; break;
case GL_GEOMETRY_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_GEOMETRY; break;
case GL_TESS_CONTROL_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_HULL; break;
case GL_TESS_EVALUATION_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_DOMAIN; break;
case GL_COMPUTE_SHADER: ShaderCI.Desc.ShaderType = Diligent::SHADER_TYPE_COMPUTE; break;
default: MG_Util::Debug::LogW("Unsupported shader type for compilation: %u", shaderType); continue;
}
ShaderCI.Desc.Name = ("Shader_" + std::to_string(shaderId)).c_str();
ShaderCI.SourceLanguage = Diligent::SHADER_SOURCE_LANGUAGE_GLSL_VERBATIM;
Diligent::IShader* pShader = nullptr;
MG_Diligent::g_pDevice->CreateShader(ShaderCI, &pShader);
if (pShader) {
MG_Diligent::g_ShaderMap[shaderId] = pShader;
programInfo.AttachedShaders.push_back(pShader);
shaderObj.compiled = UncertainBool::True;
shaderObj.compileStatus = GL_TRUE;
MG_Util::Debug::LogD("Successfully compiled shader ID: %u for program %u", shaderId, program);
} else {
shaderObj.compiled = UncertainBool::False;
shaderObj.compileStatus = GL_FALSE;
MG_Util::Debug::LogE("Failed to compile shader ID: %u for program %u", shaderId, program);
}
} else {
// Shader already compiled, just add to programInfo
programInfo.AttachedShaders.push_back(MG_Diligent::g_ShaderMap[shaderId]);
}
}
programInfo.id = program;
programInfo.inputLayout.clear();
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
if (!pVAO) return;
for (const auto& [index, attrib] : pVAO->attribs) {
if (attrib.enabled) {
Diligent::LayoutElement elem;
elem.InputIndex = index;
elem.BufferSlot = 0;
elem.NumComponents = attrib.size;
elem.ValueType = ConvertGLTypeToDiligent(attrib.type);
elem.IsNormalized = attrib.normalized;
elem.RelativeOffset = static_cast<GLuint>(reinterpret_cast<size_t>(attrib.pointer));
programInfo.inputLayout.push_back(elem);
}
}
programInfo.psoDirty = true;
programInfo.psoStateHash = 0;
programInfo.uniformStages.clear();
programInfo.programObj = MG_State_T::programState->programs_[program];
if (programInfo.pResourceBinding) {
programInfo.pResourceBinding->Release();
programInfo.pResourceBinding = nullptr;
}
CreateDefaultUBO(programInfo);
RecordUniformOffsets(programInfo);
programObj.linked = true;
programObj.linkStatus = GL_TRUE;
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error linking program: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -82,7 +342,9 @@ namespace MG_GL::GL {
void UseProgram(GLuint program) {
MG_Util::Debug::LogD("glUseProgram, program: %u", program);
GLenum result = MG_State::ActivateRenderProgram(program);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error using program: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -8,6 +8,8 @@
#include "../../../../Includes.h"
namespace MG_GL::GL {
Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type);
GLuint CreateShader(GLenum type);
GLuint CreateProgram();
void DeleteShader(GLuint shader);
@@ -5,6 +5,80 @@
#include "GL_Texture.h"
namespace MG_GL::GL {
Diligent::TEXTURE_FORMAT ConvertInternalFormat(GLint internalFormat) {
switch (internalFormat) {
case GL_RGBA: return Diligent::TEX_FORMAT_RGBA8_UNORM;
case GL_RGBA8: return Diligent::TEX_FORMAT_RGBA8_UNORM;
case GL_RGBA8_SNORM: return Diligent::TEX_FORMAT_RGBA8_SNORM;
case GL_RGBA16F: return Diligent::TEX_FORMAT_RGBA16_FLOAT;
case GL_RGBA32F: return Diligent::TEX_FORMAT_RGBA32_FLOAT;
case GL_RGB: return Diligent::TEX_FORMAT_RGBA8_UNORM;
case GL_RGB8: return Diligent::TEX_FORMAT_RGBA8_UNORM; // Diligent doesn't have RGB8, promote to RGBA8
case GL_RGB16F: return Diligent::TEX_FORMAT_RGBA16_FLOAT; // Promote
case GL_RGB32F: return Diligent::TEX_FORMAT_RGBA32_FLOAT; // Promote
case GL_DEPTH_COMPONENT: return Diligent::TEX_FORMAT_D32_FLOAT;
case GL_DEPTH_COMPONENT16: return Diligent::TEX_FORMAT_D16_UNORM;
case GL_DEPTH_COMPONENT24: return Diligent::TEX_FORMAT_D24_UNORM_S8_UINT; // No D24_UNORM, use with stencil
case GL_DEPTH_COMPONENT32: return Diligent::TEX_FORMAT_D32_FLOAT;
case GL_DEPTH_COMPONENT32F: return Diligent::TEX_FORMAT_D32_FLOAT;
case GL_DEPTH_STENCIL: return Diligent::TEX_FORMAT_D24_UNORM_S8_UINT;
case GL_DEPTH24_STENCIL8: return Diligent::TEX_FORMAT_D24_UNORM_S8_UINT;
case GL_DEPTH32F_STENCIL8: return Diligent::TEX_FORMAT_D32_FLOAT_S8X24_UINT;
case GL_RED: return Diligent::TEX_FORMAT_R8_UNORM;
case GL_R8: return Diligent::TEX_FORMAT_R8_UNORM;
case GL_R16F: return Diligent::TEX_FORMAT_R16_FLOAT;
case GL_R32F: return Diligent::TEX_FORMAT_R32_FLOAT;
case GL_RG: return Diligent::TEX_FORMAT_RG8_UNORM;
case GL_RG8: return Diligent::TEX_FORMAT_RG8_UNORM;
case GL_RG16F: return Diligent::TEX_FORMAT_RG16_FLOAT;
case GL_RG32F: return Diligent::TEX_FORMAT_RG32_FLOAT;
default: return Diligent::TEX_FORMAT_RGBA8_UNORM;
}
}
size_t GetBytesPerPixel(GLenum format, GLenum type) {
int components = 0;
switch (format) {
case GL_RED: components = 1; break;
case GL_RG: components = 2; break;
case GL_RGB: components = 3; break;
case GL_RGBA: components = 4; break;
case GL_DEPTH_COMPONENT: components = 1; break;
case GL_DEPTH_STENCIL: components = 2; break;
default: components = 4; break;
}
size_t typeSize = 0;
switch (type) {
case GL_UNSIGNED_BYTE:
case GL_BYTE: typeSize = 1; break;
case GL_UNSIGNED_SHORT:
case GL_SHORT: typeSize = 2; break;
case GL_UNSIGNED_INT:
case GL_INT:
case GL_FLOAT: typeSize = 4; break;
default: typeSize = 1; break;
}
return components * typeSize;
}
Diligent::TEXTURE_ADDRESS_MODE ConvertAddressMode(GLint param) {
switch (param) {
case GL_REPEAT: return Diligent::TEXTURE_ADDRESS_WRAP;
case GL_CLAMP_TO_EDGE: return Diligent::TEXTURE_ADDRESS_CLAMP;
case GL_MIRRORED_REPEAT: return Diligent::TEXTURE_ADDRESS_MIRROR;
default: return Diligent::TEXTURE_ADDRESS_WRAP;
}
}
void ActiveTexture(GLenum texture) {
MG_Util::Debug::LogD("glActiveTexture, texture: %d", texture);
GLenum result = MG_State::BindTextureUnit(texture);
@@ -17,8 +91,51 @@ namespace MG_GL::GL {
void BindTexture(GLenum target, GLuint texture) {
MG_Util::Debug::LogD("glBindTexture, target: %d, texture: %d", target, texture);
GLenum result = MG_State::BindTexture(target, texture);
if (result == GL_NO_ERROR)
if (result == GL_NO_ERROR) {
auto& texState = *MG_State_T::textureState;
auto activeUnit = texState.activeTextureUnit_;
auto unitState = &texState.textureUnits_[activeUnit];
GLuint boundTextureID = unitState->GetBoundTexture(target);
if (boundTextureID == 0) {
auto it = MG_Diligent::g_TextureMap.find(texture);
if (it != MG_Diligent::g_TextureMap.end()) {
if (it->second) {
it->second->Release();
it->second = nullptr;
}
}
return;
}
auto it = MG_Diligent::g_TextureMap.find(boundTextureID);
if (it == MG_Diligent::g_TextureMap.end() || it->second == nullptr) {
Diligent::TextureDesc TexDesc;
TexDesc.Type = (target == GL_TEXTURE_2D) ?
Diligent::RESOURCE_DIM_TEX_2D : Diligent::RESOURCE_DIM_UNDEFINED;
TexDesc.Format = Diligent::TEX_FORMAT_RGBA8_UNORM;
TexDesc.Width = 1;
TexDesc.Height = 1;
TexDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE;
Diligent::ITexture* pTexture = nullptr;
MG_Diligent::g_pDevice->CreateTexture(TexDesc, nullptr, &pTexture);
Diligent::ITextureView* pSRV = nullptr;
if (pTexture) {
Diligent::TextureViewDesc SRVDesc;
SRVDesc.ViewType = Diligent::TEXTURE_VIEW_SHADER_RESOURCE;
SRVDesc.TextureDim = Diligent::RESOURCE_DIM_TEX_2D;
pTexture->CreateView(SRVDesc, &pSRV);
}
MG_Diligent::g_TextureMap[boundTextureID] = pTexture;
MG_Diligent::g_TextureViewMap[boundTextureID] = pSRV;
MG_Util::Debug::LogD("Created placeholder Diligent texture for GL name %u", boundTextureID);
}
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -26,8 +143,27 @@ namespace MG_GL::GL {
void DeleteTextures(GLsizei n, const GLuint* textures) {
MG_Util::Debug::LogD("glDeleteTextures, n: %d, textures: %p", n, textures);
GLenum result = MG_State::DeleteTextures(n, textures);
if (result == GL_NO_ERROR)
if (result == GL_NO_ERROR) {
for (GLsizei i = 0; i < n; ++i) {
GLuint tex = textures[i];
auto texIt = MG_Diligent::g_TextureMap.find(tex);
if (texIt != MG_Diligent::g_TextureMap.end()) {
if (texIt->second) {
texIt->second->Release();
}
MG_Diligent::g_TextureMap.erase(texIt);
}
auto srvIt = MG_Diligent::g_TextureViewMap.find(tex);
if (srvIt != MG_Diligent::g_TextureViewMap.end()) {
if (srvIt->second) {
srvIt->second->Release();
}
MG_Diligent::g_TextureViewMap.erase(srvIt);
}
}
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
@@ -35,21 +171,144 @@ namespace MG_GL::GL {
void GenTextures(GLsizei n, GLuint* textures) {
MG_Util::Debug::LogD("glGenTextures, n: %d, textures: %p", n, textures);
GLenum result = MG_State::CreateTextures(n, textures);
if (result == GL_NO_ERROR)
if (result == GL_NO_ERROR) {
for (GLsizei i = 0; i < n; ++i) {
MG_Diligent::g_TextureMap[textures[i]] = nullptr;
MG_Diligent::g_TextureViewMap[textures[i]] = nullptr;
}
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
void TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border,
void TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const void* data) {
MG_Util::Debug::LogD("glTexImage2D, target: %d, level: %d, internalFormat: %d, width: %d, height: %d, format: %d, type: %d, data: %p",
target, level, internalFormat, width, height, format, type, data);
GLenum result = MG_State::UploadTexture2D(target, level, internalFormat, width, height, border, format, type, data);
if (result == GL_NO_ERROR)
GLenum result = MG_State::UploadTexture2D(target, level, internalFormat, width, height,
border, format, type, data);
if (result != GL_NO_ERROR) {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
MG_Util::Debug::LogD("TexImage2D: MG_State::UploadTexture2D successful.");
auto& texState = *MG_State_T::textureState;
auto activeUnit = texState.activeTextureUnit_;
auto unitState = &texState.textureUnits_[activeUnit];
GLuint boundTextureID = unitState->GetBoundTexture(target);
if (boundTextureID == 0) {
MG_Util::Debug::LogD("TexImage2D: No texture bound to active unit. Returning.");
return;
}
Diligent::ITexture* pTexture = nullptr;
Diligent::ITextureView* pSRV = nullptr;
auto texIt = MG_Diligent::g_TextureMap.find(boundTextureID);
auto srvIt = MG_Diligent::g_TextureViewMap.find(boundTextureID);
if (texIt != MG_Diligent::g_TextureMap.end()) {
pTexture = texIt->second;
}
if (srvIt != MG_Diligent::g_TextureViewMap.end()) {
pSRV = srvIt->second;
}
Diligent::TEXTURE_FORMAT newFormat = ConvertInternalFormat(internalFormat);
MG_Util::Debug::LogD("TexImage2D: New internalFormat: %d maps to Diligent format: %d",
internalFormat, newFormat);
bool needCreateTexture = false;
if (!pTexture) {
MG_Util::Debug::LogD("TexImage2D: No existing Diligent texture found for GL name %u. Creating new.", boundTextureID);
needCreateTexture = true;
} else {
Diligent::TextureDesc existingDesc = pTexture->GetDesc();
if (existingDesc.Width != static_cast<Diligent::Uint32>(width) ||
existingDesc.Height != static_cast<Diligent::Uint32>(height) ||
existingDesc.Format != newFormat) {
MG_Util::Debug::LogD("TexImage2D: Texture properties changed. Recreating texture.");
MG_Util::Debug::LogD("TexImage2D: Old (W:%u, H:%u, F:%d), New (W:%d, H:%d, F:%d)",
existingDesc.Width, existingDesc.Height, existingDesc.Format,
width, height, newFormat);
if (pSRV) {
pSRV->Release();
MG_Diligent::g_TextureViewMap[boundTextureID] = nullptr;
}
if (pTexture) {
pTexture->Release();
MG_Diligent::g_TextureMap[boundTextureID] = nullptr;
}
needCreateTexture = true;
}
}
if (needCreateTexture) {
Diligent::TextureDesc TexDesc;
TexDesc.Type = Diligent::RESOURCE_DIM_TEX_2D;
TexDesc.Width = width;
TexDesc.Height = height;
TexDesc.Format = newFormat;
TexDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE;
if (level > 0) {
TexDesc.MipLevels = level + 1;
}
MG_Util::Debug::LogD("TexImage2D: Creating new Diligent texture with Width: %d, Height: %d, Format: %d",
width, height, newFormat);
MG_Diligent::g_pDevice->CreateTexture(TexDesc, nullptr, &pTexture);
MG_Diligent::g_TextureMap[boundTextureID] = pTexture;
MG_Util::Debug::LogD("TexImage2D: Created new Diligent texture %p for GL name %u.",
(void*)pTexture, boundTextureID);
if (pTexture) {
Diligent::TextureViewDesc SRVDesc;
SRVDesc.ViewType = Diligent::TEXTURE_VIEW_SHADER_RESOURCE;
SRVDesc.TextureDim = Diligent::RESOURCE_DIM_TEX_2D;
SRVDesc.MostDetailedMip = 0;
SRVDesc.NumMipLevels = TexDesc.MipLevels;
pTexture->CreateView(SRVDesc, &pSRV);
MG_Diligent::g_TextureViewMap[boundTextureID] = pSRV;
MG_Util::Debug::LogD("TexImage2D: Created new SRV %p for texture.", (void*)pSRV);
}
}
if (pTexture && data) {
Diligent::TextureSubResData SubResData;
SubResData.pData = data;
SubResData.Stride = width * GetBytesPerPixel(format, type);
Diligent::Box UpdateBox;
UpdateBox.MinX = 0;
UpdateBox.MaxX = width;
UpdateBox.MinY = 0;
UpdateBox.MaxY = height;
MG_Util::Debug::LogD("TexImage2D: Updating texture. Level: %d, Box: [%u,%u]x[%u,%u], Stride: %llu",
level, UpdateBox.MinX, UpdateBox.MaxX, UpdateBox.MinY, UpdateBox.MaxY, SubResData.Stride);
MG_Diligent::g_pContext->UpdateTexture(
pTexture,
level,
0,
UpdateBox,
SubResData,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
MG_Util::Debug::LogD("TexImage2D: UpdateTexture completed.");
}
}
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
@@ -64,21 +323,120 @@ namespace MG_GL::GL {
void TexParameteri(GLenum target, GLenum pname, GLint param) {
MG_Util::Debug::LogD("glTexParameteri, target: %d, pname: %d, param: %d", target, pname, param);
GLenum result = MG_State::SetTexturePropertyInt(target, pname, param);
if (result == GL_NO_ERROR)
if (result != GL_NO_ERROR) {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
auto& texState = *MG_State_T::textureState;
auto activeUnit = texState.activeTextureUnit_;
auto unitState = &texState.textureUnits_[activeUnit];
GLuint boundTextureID = unitState->GetBoundTexture(target);
if (boundTextureID == 0) {
MG_Util::Debug::LogD("TexParameteri: No texture bound. Skipping sampler update.");
return;
}
Diligent::SamplerDesc SamDesc;
auto it = MG_Diligent::g_SamplerMap.find(boundTextureID);
if (it != MG_Diligent::g_SamplerMap.end() && it->second) {
SamDesc = it->second->GetDesc();
} else {
SamDesc.MinFilter = Diligent::FILTER_TYPE_LINEAR;
SamDesc.MagFilter = Diligent::FILTER_TYPE_LINEAR;
SamDesc.AddressU = Diligent::TEXTURE_ADDRESS_WRAP;
SamDesc.AddressV = Diligent::TEXTURE_ADDRESS_WRAP;
SamDesc.AddressW = Diligent::TEXTURE_ADDRESS_WRAP;
}
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
SamDesc.MinFilter = (param == GL_NEAREST) ?
Diligent::FILTER_TYPE_POINT : Diligent::FILTER_TYPE_LINEAR;
break;
case GL_TEXTURE_MAG_FILTER:
SamDesc.MagFilter = (param == GL_NEAREST) ?
Diligent::FILTER_TYPE_POINT : Diligent::FILTER_TYPE_LINEAR;
break;
case GL_TEXTURE_WRAP_S:
SamDesc.AddressU = ConvertAddressMode(param);
break;
case GL_TEXTURE_WRAP_T:
SamDesc.AddressV = ConvertAddressMode(param);
break;
case GL_TEXTURE_WRAP_R:
SamDesc.AddressW = ConvertAddressMode(param);
break;
}
Diligent::ISampler* pNewSampler = nullptr;
MG_Diligent::g_pDevice->CreateSampler(SamDesc, &pNewSampler);
if (it != MG_Diligent::g_SamplerMap.end()) {
if (it->second) {
it->second->Release();
}
it->second = pNewSampler;
} else {
MG_Diligent::g_SamplerMap[boundTextureID] = pNewSampler;
}
MG_Util::Debug::LogD("TexParameteri: Updated sampler for texture %u", boundTextureID);
}
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLenum format, GLenum type, const void* pixels) {
MG_Util::Debug::LogD("glTexSubImage2D, target: %d, level: %d, xoffset: %d, yoffset: %d, width: %d, height: %d, format: %d, type: %d, pixels: %p",
target, level, xoffset, yoffset, width, height, format, type, pixels);
GLenum result = MG_State::UpdateTextureRegion2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
if (result == GL_NO_ERROR)
if (result != GL_NO_ERROR) {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
return;
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
auto& texState = *MG_State_T::textureState;
auto activeUnit = texState.activeTextureUnit_;
auto unitState = &texState.textureUnits_[activeUnit];
GLuint boundTextureID = unitState->GetBoundTexture(target);
if (boundTextureID == 0) {
MG_Util::Debug::LogD("TexSubImage2D: No texture bound. Skipping update.");
return;
}
Diligent::ITexture* pTexture = MG_Diligent::g_TextureMap[boundTextureID];
if (!pTexture) {
MG_Util::Debug::LogW("TexSubImage2D: Diligent texture not found for GL name %u", boundTextureID);
return;
}
// 4. 更新纹理子区域
Diligent::TextureSubResData SubResData;
SubResData.pData = pixels;
SubResData.Stride = width * GetBytesPerPixel(format, type);
Diligent::Box UpdateBox;
UpdateBox.MinX = xoffset;
UpdateBox.MaxX = xoffset + width;
UpdateBox.MinY = yoffset;
UpdateBox.MaxY = yoffset + height;
MG_Util::Debug::LogD("TexSubImage2D: Updating region [%d,%d]-[%d,%d] at level %d",
xoffset, yoffset, xoffset+width, yoffset+height, level);
MG_Diligent::g_pContext->UpdateTexture(
pTexture,
level,
0,
UpdateBox,
SubResData,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
}
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) {
@@ -90,4 +448,4 @@ namespace MG_GL::GL {
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}
}
}
@@ -8,7 +8,9 @@ namespace MG_GL::GL {
void GenVertexArrays(GLsizei n, GLuint* arrays) {
MG_Util::Debug::LogD("glGenVertexArrays, n: %d, arrays: %p", n, arrays);
GLenum result = MG_State::GenVertexArraysNames(n, arrays);
if (result == GL_NO_ERROR) return;
if (result == GL_NO_ERROR) {
return;
}
MG_State::SetError(result);
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
}