[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
+503 -173
View File
@@ -4,56 +4,416 @@
#include "EGL_impl.h"
#undef MOBILEGL_GLSLTOOL_H
#undef MOBILEGL_PROGRAM_DEBUGTOOL_H
#include "../../../../Includes.h"
typedef Diligent::IEngineFactoryVk* (*Diligent_GetEngineFactoryVk_t)();
typedef Diligent::IEngineFactoryOpenGL* (*Diligent_GetEngineFactoryOpenGL_t)();
namespace MG_Diligent {
Diligent::IRenderDevice* g_pDevice;
Diligent::IDeviceContext* g_pContext;
Diligent::ISwapChain* g_pSwapChain;
MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_BufferMap;
MG_Global::unordered_map<GLuint, Diligent::ITexture*> g_TextureMap;
MG_Global::unordered_map<GLuint, Diligent::ITextureView*> g_TextureViewMap;
MG_Global::unordered_map<GLuint, GLFramebufferInfo> g_FramebufferMap;
MG_Global::unordered_map<GLuint, Diligent::IShader*> g_ShaderMap;
MG_Global::unordered_map<GLuint, GLProgramInfo> g_ProgramMap;
MG_Global::unordered_map<GLuint, Diligent::ISampler*> g_SamplerMap;
MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_UniformBufferMap;
bool IsInRenderPass = false;
bool initialized = false;
void PipelineStateManager::ConfigurePSO(
Diligent::GraphicsPipelineStateCreateInfo &PSOCreateInfo,
GLProgramInfo &programInfo,
CommonState &commonState,
VertexArrayState &vaState,
GLFramebufferInfo& fbInfo) {
PSOCreateInfo.PSODesc.Name = "Program_PSO";
PSOCreateInfo.PSODesc.PipelineType = Diligent::PIPELINE_TYPE_GRAPHICS;
__android_log_print(ANDROID_LOG_DEBUG, "Diligent Engine", "Num AttachedShaders: %zu", programInfo.AttachedShaders.size());
for (auto shader: programInfo.AttachedShaders) {
__android_log_print(ANDROID_LOG_DEBUG, "Diligent Engine", "AttachedShader: %p, Type: %d", shader, shader->GetDesc().ShaderType);
switch (shader->GetDesc().ShaderType) {
case Diligent::SHADER_TYPE_VERTEX:
PSOCreateInfo.pVS = shader;
break;
case Diligent::SHADER_TYPE_PIXEL:
PSOCreateInfo.pPS = shader;
break;
case Diligent::SHADER_TYPE_GEOMETRY:
PSOCreateInfo.pGS = shader;
break;
default:
break;
}
}
PSOCreateInfo.GraphicsPipeline.InputLayout.LayoutElements = programInfo.inputLayout.data();
PSOCreateInfo.GraphicsPipeline.InputLayout.NumElements = programInfo.inputLayout.size();
PSOCreateInfo.GraphicsPipeline.PrimitiveTopology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
PSOCreateInfo.GraphicsPipeline.NumRenderTargets = fbInfo.ColorRTVs.size();
for (size_t i = 0; i < fbInfo.ColorRTVs.size(); ++i) {
if (fbInfo.ColorRTVs[i]) {
PSOCreateInfo.GraphicsPipeline.RTVFormats[i] =
fbInfo.ColorRTVs[i]->GetDesc().Format;
} else {
PSOCreateInfo.GraphicsPipeline.RTVFormats[i] = Diligent::TEX_FORMAT_RGBA8_UNORM;
}
}
if (fbInfo.DepthStencilFormat != Diligent::TEX_FORMAT_UNKNOWN) {
PSOCreateInfo.GraphicsPipeline.DSVFormat = fbInfo.DepthStencilFormat;
} else {
PSOCreateInfo.GraphicsPipeline.DSVFormat = Diligent::TEX_FORMAT_D32_FLOAT;
}
Diligent::BlendStateDesc &blendDesc = PSOCreateInfo.GraphicsPipeline.BlendDesc;
blendDesc.IndependentBlendEnable = false;
blendDesc.RenderTargets[0].BlendEnable = commonState.capabilities[GL_BLEND];
blendDesc.RenderTargets[0].SrcBlend = ConvertGLBlendFactor(commonState.blendSrcRGB);
blendDesc.RenderTargets[0].DestBlend = ConvertGLBlendFactor(commonState.blendDstRGB);
blendDesc.RenderTargets[0].BlendOp = Diligent::BLEND_OPERATION_ADD;
blendDesc.RenderTargets[0].SrcBlendAlpha = ConvertGLBlendFactor(
commonState.blendSrcAlpha);
blendDesc.RenderTargets[0].DestBlendAlpha = ConvertGLBlendFactor(
commonState.blendDstAlpha);
blendDesc.RenderTargets[0].BlendOpAlpha = Diligent::BLEND_OPERATION_ADD;
blendDesc.RenderTargets[0].RenderTargetWriteMask = Diligent::COLOR_MASK_ALL;
Diligent::DepthStencilStateDesc &depthStencilDesc = PSOCreateInfo.GraphicsPipeline.DepthStencilDesc;
depthStencilDesc.DepthEnable = commonState.capabilities[GL_DEPTH_TEST];
depthStencilDesc.DepthWriteEnable = commonState.depthMask;
depthStencilDesc.DepthFunc = ConvertGLDepthFunc(commonState.depthFunc);
Diligent::RasterizerStateDesc &rasterizerDesc = PSOCreateInfo.GraphicsPipeline.RasterizerDesc;
rasterizerDesc.CullMode = commonState.capabilities[GL_CULL_FACE] ?
Diligent::CULL_MODE_BACK : Diligent::CULL_MODE_NONE;
rasterizerDesc.FrontCounterClockwise = true;
ConfigureResourceLayout(PSOCreateInfo, programInfo);
}
void PipelineStateManager::ReleasePSO(GLuint program) {
auto &programInfo = g_ProgramMap[program];
if (programInfo.pPipelineState) {
MG_Util::Debug::LogD("Releasing PSO for program %u", program);
programInfo.pPipelineState->Release();
programInfo.pPipelineState = nullptr;
MG_Util::Debug::LogD("PSO released for program %u", program);
}
programInfo.psoDirty = true;
}
void PipelineStateManager::MarkPSODirty(GLuint program) {
auto &programInfo = g_ProgramMap[program];
programInfo.psoDirty = true;
MG_Util::Debug::LogD("Marked PSO dirty for program %u", program);
}
Diligent::IPipelineState *PipelineStateManager::GetOrCreatePSO(
GLuint program,
GLProgramInfo &programInfo,
CommonState &commonState,
VertexArrayState &vaState,
GLFramebufferInfo& fbInfo) {
uint64_t currentStateHash = CalculateStateHash(commonState, vaState, fbInfo);
if (programInfo.pPipelineState &&
programInfo.psoStateHash == currentStateHash &&
!programInfo.psoDirty) {
return programInfo.pPipelineState;
}
PSOKey key{program, currentStateHash};
auto it = psoCache.find(key);
if (it != psoCache.end()) {
return it->second;
}
Diligent::GraphicsPipelineStateCreateInfo PSOCreateInfo;
ConfigurePSO(PSOCreateInfo, programInfo, commonState, vaState, fbInfo);
Diligent::IPipelineState *pNewPSO = nullptr;
MG_Util::Debug::LogD("Creating new PSO for program %u", program);
g_pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pNewPSO);
if (pNewPSO) {
MG_Util::Debug::LogD("PSO created successfully for program %u: %p", program, pNewPSO);
} else {
MG_Util::Debug::LogE("Failed to create PSO for program %u", program);
}
psoCache[key] = pNewPSO;
return pNewPSO;
}
void PipelineStateManager::ConfigureResourceLayout(
Diligent::GraphicsPipelineStateCreateInfo& PSOCreateInfo,
const GLProgramInfo& programInfo)
{
MG_Util::Debug::LogD("Begin configuring resource layout for pipeline");
auto& ResourceLayout = PSOCreateInfo.PSODesc.ResourceLayout;
ResourceLayout.DefaultVariableType = Diligent::SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
std::vector<Diligent::ShaderResourceVariableDesc> Variables;
std::vector<Diligent::ImmutableSamplerDesc> ImmutableSamplers;
MG_Global::unordered_map<GLuint, std::string> shaderSourcesMap;
ProgramObject programObj = MG_State_T::programState->programs_[programInfo.id];
for (GLuint shaderId : programObj.attachedShaders) {
auto it = MG_State_T::programState->shaders_.find(shaderId);
if (it != MG_State_T::programState->shaders_.end() &&
!it->second.markedForDeletion) {
shaderSourcesMap[it->first] = it->second.source;
}
}
MG_Util::Program::GenerateDefaultUBOForGLSL_Multi(shaderSourcesMap);
for (auto shader : programInfo.AttachedShaders) {
GLuint shaderId = 0;
for (auto const& [key, val] : MG_Diligent::g_ShaderMap) {
if (val == shader) {
shaderId = key;
break;
}
}
MG_Util::Debug::LogD("Processing shader ID: %u", shaderId);
auto& shaderObj = MG_State_T::programState->shaders_[shaderId];
std::string compilationLog;
auto spirv =
MG_Util::Program::CompileGLSLToSPIRV(shaderObj.type,
shaderSourcesMap[shaderId],
compilationLog);
if (spirv.empty()) {
MG_Util::Debug::LogE("Failed to compile shader %u: %s", shaderId, compilationLog.c_str());
continue;
} else {
MG_Util::Debug::LogD("Shader %u (modified) compiled to SPIR-V successfully", shaderId);
}
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) {
MG_Util::Debug::LogE("spvc_context_create failed for shader %u", shaderId);
continue;
}
result = spvc_context_parse_spirv(context,
spirv.data(),
spirv.size(),
&parsed_ir);
if (result != SPVC_SUCCESS) {
MG_Util::Debug::LogE("spvc_context_parse_spirv failed for shader %u", shaderId);
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) {
MG_Util::Debug::LogE("spvc_context_create_compiler failed for shader %u", shaderId);
spvc_context_destroy(context);
continue;
}
result = spvc_compiler_create_shader_resources(compiler, &resources);
if (result != SPVC_SUCCESS) {
MG_Util::Debug::LogE("spvc_compiler_create_shader_resources failed for shader %u", shaderId);
spvc_context_destroy(context);
continue;
}
Diligent::SHADER_TYPE shaderType;
switch (shaderObj.type) {
case GL_VERTEX_SHADER:
shaderType = Diligent::SHADER_TYPE_VERTEX;
break;
case GL_FRAGMENT_SHADER:
shaderType = Diligent::SHADER_TYPE_PIXEL;
break;
case GL_GEOMETRY_SHADER:
shaderType = Diligent::SHADER_TYPE_GEOMETRY;
break;
case GL_COMPUTE_SHADER:
shaderType = Diligent::SHADER_TYPE_COMPUTE;
break;
default:
shaderType = Diligent::SHADER_TYPE_UNKNOWN;
}
MG_Util::Debug::LogD("Shader %u mapped to Diligent shader type %d", shaderId, shaderType);
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);
MG_Util::Debug::LogD("Shader %u has %zu uniform buffers", shaderId, resourceCount);
for (size_t i = 0; i < resourceCount; i++) {
bool already_added = false;
for(const auto& existing_var : Variables) {
if (strcmp(existing_var.Name, resourceList[i].name) == 0) {
already_added = true;
MG_Util::Debug::LogD("Uniform buffer %s already added, skipping.", resourceList[i].name);
break;
}
}
if (already_added) continue;
Diligent::ShaderResourceVariableDesc varDesc;
varDesc.Name = strdup(resourceList[i].name);
varDesc.ShaderStages = Diligent::SHADER_TYPE_ALL; // TODO
varDesc.Type = Diligent::SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
MG_Util::Debug::LogD("Uniform buffer: %s, Stage: %u, Type: %u", varDesc.Name, varDesc.ShaderStages, varDesc.Type);
Variables.push_back(varDesc);
}
spvc_resources_get_resource_list_for_type(
resources, SPVC_RESOURCE_TYPE_SAMPLED_IMAGE,
&resourceList, &resourceCount);
MG_Util::Debug::LogD("Shader %u has %zu sampled images", shaderId, resourceCount);
for (size_t i = 0; i < resourceCount; i++) {
Diligent::ShaderResourceVariableDesc varDesc;
varDesc.Name = strdup(resourceList[i].name);
varDesc.ShaderStages = shaderType;
varDesc.Type = Diligent::SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
MG_Util::Debug::LogD("Sampled image: %s", varDesc.Name);
Variables.push_back(varDesc);
const char* samplerName = varDesc.Name;
if (samplerName) {
auto& texState = *MG_State_T::textureState;
GLuint activeTextureUnit = texState.activeTextureUnit_;
if (activeTextureUnit < texState.textureUnits_.size()) {
auto& unitState = texState.textureUnits_[activeTextureUnit];
GLuint boundTexture = unitState.GetBoundTexture(GL_TEXTURE_2D);
if (boundTexture != 0) {
auto texIt = texState.textures.find(boundTexture);
if (texIt != texState.textures.end()) {
auto& texObj = texIt->second;
Diligent::ImmutableSamplerDesc samplerDesc;
samplerDesc.ShaderStages = shaderType;
samplerDesc.SamplerOrTextureName = samplerName;
auto minFilterIt = texObj.params.texPropertiesInt.find(GL_TEXTURE_MIN_FILTER);
samplerDesc.Desc.MinFilter = (minFilterIt != texObj.params.texPropertiesInt.end()) ?
ConvertGLFilter(minFilterIt->second) : Diligent::FILTER_TYPE_LINEAR;
auto magFilterIt = texObj.params.texPropertiesInt.find(GL_TEXTURE_MAG_FILTER);
samplerDesc.Desc.MagFilter = (magFilterIt != texObj.params.texPropertiesInt.end()) ?
ConvertGLFilter(magFilterIt->second) : Diligent::FILTER_TYPE_LINEAR;
samplerDesc.Desc.MipFilter = ConvertGLMipFilter(
minFilterIt != texObj.params.texPropertiesInt.end() ?
minFilterIt->second : GL_LINEAR_MIPMAP_LINEAR);
auto wrapSIt = texObj.params.texPropertiesInt.find(GL_TEXTURE_WRAP_S);
samplerDesc.Desc.AddressU = (wrapSIt != texObj.params.texPropertiesInt.end()) ?
ConvertGLWrapMode(wrapSIt->second) : Diligent::TEXTURE_ADDRESS_WRAP;
auto wrapTIt = texObj.params.texPropertiesInt.find(GL_TEXTURE_WRAP_T);
samplerDesc.Desc.AddressV = (wrapTIt != texObj.params.texPropertiesInt.end()) ?
ConvertGLWrapMode(wrapTIt->second) : Diligent::TEXTURE_ADDRESS_WRAP;
samplerDesc.Desc.AddressW = Diligent::TEXTURE_ADDRESS_CLAMP;
MG_Util::Debug::LogD("Created immutable sampler for: %s", samplerName);
ImmutableSamplers.push_back(samplerDesc);
}
}
}
}
}
spvc_resources_get_resource_list_for_type(
resources, SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS,
&resourceList, &resourceCount);
MG_Util::Debug::LogD("Shader %u has %zu separate samplers", shaderId, resourceCount);
for (size_t i = 0; i < resourceCount; i++) {
Diligent::ShaderResourceVariableDesc varDesc;
varDesc.Name = strdup(resourceList[i].name);
varDesc.ShaderStages = shaderType;
varDesc.Type = Diligent::SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
Variables.push_back(varDesc);
Diligent::ImmutableSamplerDesc samplerDesc;
samplerDesc.ShaderStages = shaderType;
samplerDesc.Desc.MinFilter = Diligent::FILTER_TYPE_LINEAR;
samplerDesc.Desc.MagFilter = Diligent::FILTER_TYPE_LINEAR;
samplerDesc.Desc.MipFilter = Diligent::FILTER_TYPE_LINEAR;
samplerDesc.Desc.AddressU = Diligent::TEXTURE_ADDRESS_WRAP;
samplerDesc.Desc.AddressV = Diligent::TEXTURE_ADDRESS_WRAP;
samplerDesc.Desc.AddressW = Diligent::TEXTURE_ADDRESS_CLAMP;
samplerDesc.SamplerOrTextureName = resourceList[i].name;
MG_Util::Debug::LogD("Added fallback immutable sampler: %s", samplerDesc.SamplerOrTextureName);
ImmutableSamplers.push_back(samplerDesc);
}
spvc_resources_get_resource_list_for_type(
resources, SPVC_RESOURCE_TYPE_STORAGE_IMAGE,
&resourceList, &resourceCount);
MG_Util::Debug::LogD("Shader %u has %zu storage images", shaderId, resourceCount);
for (size_t i = 0; i < resourceCount; i++) {
Diligent::ShaderResourceVariableDesc varDesc;
varDesc.Name = strdup(resourceList[i].name);
varDesc.ShaderStages = shaderType;
varDesc.Type = Diligent::SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
MG_Util::Debug::LogD("Storage image: %s", varDesc.Name);
Variables.push_back(varDesc);
}
spvc_context_destroy(context);
}
if (!Variables.empty()) {
ResourceLayout.Variables = Variables.data();
ResourceLayout.NumVariables = static_cast<Diligent::Uint32>(Variables.size());
MG_Util::Debug::LogD("Added %u shader resource variables", ResourceLayout.NumVariables);
}
if (!ImmutableSamplers.empty()) {
ResourceLayout.ImmutableSamplers = ImmutableSamplers.data();
ResourceLayout.NumImmutableSamplers = static_cast<Diligent::Uint32>(ImmutableSamplers.size());
MG_Util::Debug::LogD("Added %u immutable samplers", ResourceLayout.NumImmutableSamplers);
}
MG_Util::Debug::LogD("Finished configuring resource layout");
}
PipelineStateManager g_PSOManager;
}
using namespace Diligent;
namespace MG_EGL::Diligent {
static const char *VSSource = R"(
struct PSInput
{
float4 Pos : SV_POSITION;
float3 Color : COLOR;
};
void main(in uint VertId : SV_VertexID,
out PSInput PSIn)
{
float4 Pos[3];
Pos[0] = float4(-0.5, -0.5, 0.0, 1.0);
Pos[1] = float4( 0.0, +0.5, 0.0, 1.0);
Pos[2] = float4(+0.5, -0.5, 0.0, 1.0);
float3 Col[3];
Col[0] = float3(1.0, 0.0, 0.0); // red
Col[1] = float3(0.0, 1.0, 0.0); // green
Col[2] = float3(0.0, 0.0, 1.0); // blue
PSIn.Pos = Pos[VertId];
PSIn.Color = Col[VertId];
}
)";
static const char *PSSource = R"(
struct PSInput
{
float4 Pos : SV_POSITION;
float3 Color : COLOR;
};
struct PSOutput
{
float4 Color : SV_TARGET;
};
void main(in PSInput PSIn,
out PSOutput PSOut)
{
PSOut.Color = float4(PSIn.Color.rgb, 1.0);
}
)";
void LoadDiligentCoreOpenGL(NativeWindowType window) {
void *handle = dlopen("libGraphicsEngineOpenGL.so", RTLD_LAZY);
auto Diligent_GetEngineFactoryOpenGL =
@@ -67,8 +427,15 @@ void main(in PSInput PSIn,
::Diligent::SwapChainDesc SCDesc;
MG_Util::Debug::LogD("Creating OpenGL device and swap chain");
pFactoryOpenGL->CreateDeviceAndSwapChainGL(
EngineCI, &ctx.pDevice, &ctx.pContext, SCDesc, &ctx.pSwapChain);
EngineCI, &MG_Diligent::g_pDevice, &MG_Diligent::g_pContext, SCDesc, &MG_Diligent::g_pSwapChain);
if (MG_Diligent::g_pDevice && MG_Diligent::g_pContext && MG_Diligent::g_pSwapChain) {
MG_Util::Debug::LogD("OpenGL device created: device=%p, context=%p, swapchain=%p",
MG_Diligent::g_pDevice, MG_Diligent::g_pContext, MG_Diligent::g_pSwapChain);
} else {
MG_Util::Debug::LogE("Failed to create OpenGL device");
}
}
void LoadDiligentCoreVulkan(NativeWindowType window) {
@@ -82,11 +449,25 @@ void main(in PSInput PSIn,
::Diligent::SwapChainDesc SCDesc;
MG_Util::Debug::LogD("Creating Vulkan device and contexts");
pFactoryVk->CreateDeviceAndContextsVk(
EngineCI, &ctx.pDevice, &ctx.pContext);
EngineCI, &MG_Diligent::g_pDevice, &MG_Diligent::g_pContext);
if (MG_Diligent::g_pDevice && MG_Diligent::g_pContext) {
MG_Util::Debug::LogD("Vulkan device created: device=%p, context=%p",
MG_Diligent::g_pDevice, MG_Diligent::g_pContext);
} else {
MG_Util::Debug::LogE("Failed to create Vulkan device");
}
AndroidNativeWindow nativeWindow{window};
MG_Util::Debug::LogD("Creating Vulkan swap chain");
pFactoryVk->CreateSwapChainVk(
ctx.pDevice, ctx.pContext, SCDesc, nativeWindow, &ctx.pSwapChain);
MG_Diligent::g_pDevice, MG_Diligent::g_pContext, SCDesc, nativeWindow, &MG_Diligent::g_pSwapChain);
if (MG_Diligent::g_pSwapChain) {
MG_Util::Debug::LogD("Vulkan swap chain created: %p", MG_Diligent::g_pSwapChain);
} else {
MG_Util::Debug::LogE("Failed to create Vulkan swap chain");
}
}
void LoadDiligentCore(NativeWindowType window) {
@@ -102,81 +483,48 @@ void main(in PSInput PSIn,
}
void CreateDefaultRenderPass() {
::Diligent::RenderPassDesc RPDesc;
RPDesc.AttachmentCount = 2;
::Diligent::RenderPassAttachmentDesc Attachments[2];
RPDesc.pAttachments = Attachments;
Attachments[0].Format = ::Diligent::TEX_FORMAT_RGBA8_UNORM;
Attachments[0].InitialState = ::Diligent::RESOURCE_STATE_RENDER_TARGET;
Attachments[0].FinalState = ::Diligent::RESOURCE_STATE_RENDER_TARGET;
Attachments[0].LoadOp = ::Diligent::ATTACHMENT_LOAD_OP_CLEAR;
Attachments[0].StoreOp = ::Diligent::ATTACHMENT_STORE_OP_STORE;
Attachments[1].Format = ::Diligent::TEX_FORMAT_D24_UNORM_S8_UINT;
Attachments[1].InitialState = ::Diligent::RESOURCE_STATE_DEPTH_WRITE;
Attachments[1].FinalState = ::Diligent::RESOURCE_STATE_DEPTH_WRITE;
Attachments[1].LoadOp = ::Diligent::ATTACHMENT_LOAD_OP_CLEAR;
Attachments[1].StoreOp = ::Diligent::ATTACHMENT_STORE_OP_STORE;
::Diligent::AttachmentReference RTAttachmentRef{0, ::Diligent::RESOURCE_STATE_RENDER_TARGET};
::Diligent::AttachmentReference DSAttachmentRef{1, ::Diligent::RESOURCE_STATE_DEPTH_WRITE};
::Diligent::SubpassDesc Subpasses[1];
Subpasses[0].RenderTargetAttachmentCount = 1;
Subpasses[0].pRenderTargetAttachments = &RTAttachmentRef;
Subpasses[0].pDepthStencilAttachment = &DSAttachmentRef;
RPDesc.SubpassCount = 1;
RPDesc.pSubpasses = Subpasses;
MG_Util::Debug::LogD("Creating default render pass");
MG_Diligent::g_pDevice->CreateRenderPass(RPDesc, &MG_Diligent::g_FramebufferMap[0].pRenderPass);
if (MG_Diligent::g_FramebufferMap[0].pRenderPass) {
MG_Util::Debug::LogD("Default render pass created: %p", MG_Diligent::g_FramebufferMap[0].pRenderPass);
} else {
MG_Util::Debug::LogE("Failed to create default render pass");
}
}
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window,
const EGLint *attrib_list) {
LoadDiligentCore(window);
RenderPassAttachmentDesc RPAttachmentDescs[2];
RPAttachmentDescs[0].Format = ctx.pSwapChain->GetDesc().ColorBufferFormat;
RPAttachmentDescs[0].InitialState = RESOURCE_STATE_RENDER_TARGET;
RPAttachmentDescs[0].FinalState = RESOURCE_STATE_RENDER_TARGET;
RPAttachmentDescs[0].LoadOp = ATTACHMENT_LOAD_OP_CLEAR;
RPAttachmentDescs[0].StoreOp = ATTACHMENT_STORE_OP_STORE;
RPAttachmentDescs[1].Format = ctx.pSwapChain->GetDesc().DepthBufferFormat;
RPAttachmentDescs[1].InitialState = RESOURCE_STATE_DEPTH_WRITE;
RPAttachmentDescs[1].FinalState = RESOURCE_STATE_DEPTH_WRITE;
RPAttachmentDescs[1].LoadOp = ATTACHMENT_LOAD_OP_CLEAR;
RPAttachmentDescs[1].StoreOp = ATTACHMENT_STORE_OP_DISCARD;
SubpassDesc Subpass;
Subpass.InputAttachmentCount = 0;
Subpass.RenderTargetAttachmentCount = 1;
AttachmentReference RTAttachmentRef = {0, RESOURCE_STATE_RENDER_TARGET};
Subpass.pRenderTargetAttachments = &RTAttachmentRef;
AttachmentReference DSAttachmentRef = {1, RESOURCE_STATE_DEPTH_WRITE};
Subpass.pDepthStencilAttachment = &DSAttachmentRef;
RenderPassDesc RPDesc;
RPDesc.Name = "Main render pass";
RPDesc.AttachmentCount = 2;
RPDesc.pAttachments = RPAttachmentDescs;
RPDesc.SubpassCount = 1;
RPDesc.pSubpasses = &Subpass;
ctx.pDevice->CreateRenderPass(RPDesc, &ctx.pRenderPass);
GraphicsPipelineStateCreateInfo PSOCreateInfo;
PSOCreateInfo.PSODesc.Name = "Simple triangle PSO";
PSOCreateInfo.PSODesc.PipelineType = PIPELINE_TYPE_GRAPHICS;
PSOCreateInfo.GraphicsPipeline.NumRenderTargets = 0;
PSOCreateInfo.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_UNKNOWN;
PSOCreateInfo.GraphicsPipeline.DSVFormat = TEX_FORMAT_UNKNOWN;
PSOCreateInfo.GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
PSOCreateInfo.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
PSOCreateInfo.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
PSOCreateInfo.GraphicsPipeline.pRenderPass = ctx.pRenderPass;
ShaderCreateInfo ShaderCI;
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
ShaderCI.Desc.UseCombinedTextureSamplers = true;
RefCntAutoPtr <IShader> pVS;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_VERTEX;
ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Triangle vertex shader";
ShaderCI.Source = VSSource;
ctx.pDevice->CreateShader(ShaderCI, &pVS);
}
RefCntAutoPtr <IShader> pPS;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL;
ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Triangle pixel shader";
ShaderCI.Source = PSSource;
ctx.pDevice->CreateShader(ShaderCI, &pPS);
}
PSOCreateInfo.pVS = pVS;
PSOCreateInfo.pPS = pPS;
ctx.pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &ctx.pPSO);
const auto& SCDesc = ctx.pSwapChain->GetDesc();
ctx.pFramebuffers.resize(SCDesc.BufferCount);
ctx.pContext->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_NONE);
MG_GL::GL::UpdateDefaultFramebuffer();
return (EGLSurface) 1;
}
@@ -251,63 +599,39 @@ void main(in PSInput PSIn,
return EGL_TRUE;
}
static int swapBuffersCount = 0;
static int bufferCount = 0;
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) {
const float ClearColor[] = {0.350f, 0.350f, 0.350f, 1.0f};
MG_Util::Debug::LogD("Flushing context");
MG_Diligent::g_pContext->Flush();
// Framebuffer Creation
if (!bufferCount) bufferCount = ctx.pSwapChain->GetDesc().BufferCount;
ITextureView* pDSV = ctx.pSwapChain->GetDepthBufferDSV();
if (swapBuffersCount < bufferCount) {
ITextureView *pRTV = ctx.pSwapChain->GetCurrentBackBufferRTV();
ITextureView *attachments[2];
attachments[0] = pRTV;
attachments[1] = pDSV;
MG_Util::Debug::LogD("Presenting swap chain");
MG_Diligent::g_pSwapChain->Present();
MG_GL::GL::UpdateDefaultFramebuffer();
MG_Util::Debug::LogD("Finishing frame");
MG_Diligent::g_pContext->FinishFrame();
FramebufferDesc FBDesc;
FBDesc.Name = ("Main framebuffer " + std::to_string(swapBuffersCount)).c_str();
FBDesc.pRenderPass = ctx.pRenderPass;
FBDesc.AttachmentCount = 2;
FBDesc.ppAttachments = attachments;
ctx.pDevice->CreateFramebuffer(FBDesc, &ctx.pFramebuffers[swapBuffersCount]);
auto& fbInfo = MG_Diligent::g_FramebufferMap[0];
if (fbInfo.pRenderPass && fbInfo.pFramebuffer) {
MG_Util::Debug::LogD("Setting render targets: %zu color attachments", fbInfo.ColorRTVs.size());
MG_Diligent::g_pContext->SetRenderTargets(
static_cast<Uint32>(fbInfo.ColorRTVs.size()),
fbInfo.ColorRTVs.data(),
fbInfo.pDepthStencilRTV,
::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
);
MG_Util::Debug::LogD("Beginning render pass: pass=%p, fb=%p", fbInfo.pRenderPass, fbInfo.pFramebuffer);
MG_Diligent::g_pContext->BeginRenderPass(
::Diligent::BeginRenderPassAttribs{
fbInfo.pRenderPass,
fbInfo.pFramebuffer,
::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
}
);
}
BeginRenderPassAttribs beginRenderPassAttribs;
beginRenderPassAttribs.pFramebuffer = ctx.pFramebuffers[swapBuffersCount % bufferCount];
beginRenderPassAttribs.pRenderPass = ctx.pRenderPass;
beginRenderPassAttribs.ClearValueCount = 2;
OptimizedClearValue optimizedClearValues[2];
optimizedClearValues[0].Color[0] = ClearColor[0];
optimizedClearValues[0].Color[1] = ClearColor[1];
optimizedClearValues[0].Color[2] = ClearColor[2];
optimizedClearValues[0].Color[3] = ClearColor[3];
optimizedClearValues[1].DepthStencil.Depth = 1.f;
optimizedClearValues[1].DepthStencil.Stencil = 0;
beginRenderPassAttribs.pClearValues = optimizedClearValues;
beginRenderPassAttribs.StateTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
ctx.pContext->BeginRenderPass(beginRenderPassAttribs);
Viewport vp = {0, 0, (float)ctx.pSwapChain->GetDesc().Width, (float)ctx.pSwapChain->GetDesc().Height, 0, 1};
ctx.pContext->SetViewports(1, &vp, ctx.pSwapChain->GetDesc().Width, ctx.pSwapChain->GetDesc().Height);
ctx.pContext->SetPipelineState(ctx.pPSO);
DrawAttribs drawAttrs;
drawAttrs.NumVertices = 3;
drawAttrs.Flags = DRAW_FLAG_VERIFY_ALL;
ctx.pContext->Draw(drawAttrs);
ctx.pContext->EndRenderPass();
ctx.pContext->Flush();
ctx.pSwapChain->Present();
swapBuffersCount++;
const auto& SCDesc = MG_Diligent::g_pSwapChain->GetDesc();
MG_Util::Debug::LogD("Setting viewport: width=%d, height=%d", SCDesc.Width, SCDesc.Height);
MG_Diligent::g_pContext->SetViewports(1, nullptr, 0, 0);
return EGL_TRUE;
}
@@ -382,6 +706,11 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
return (__eglMustCastToProperFunctionPointerType)(&eglGetProcAddress);
}
#define MG_EGL_PROC_EXPORT(name) \
if (strncmp(procname, #name, strlen(#name)) == 0) { \
return (__eglMustCastToProperFunctionPointerType)(&MG_EGL::Diligent::name); \
}
MG_EGL_PROC_EXPORT(eglCreateWindowSurface);
MG_EGL_PROC_EXPORT(eglChooseConfig);
MG_EGL_PROC_EXPORT(eglCreateContext);
@@ -401,6 +730,7 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
MG_EGL_PROC_EXPORT(eglSwapInterval);
MG_EGL_PROC_EXPORT(eglSwapBuffers);
MG_EGL_PROC_EXPORT(eglCreatePbufferSurface);
#undef MG_EGL_PROC_EXPORT
/* TODO: Call real eglGetProcAddress() to get the rest (should be real native GLES functions) */
if (!libEGL) {
@@ -411,4 +741,4 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
return real_eglGetProcAddress(procname);
return nullptr;
}
}
+240 -21
View File
@@ -2,30 +2,254 @@
// Created by Swung 0x48 on 2025-05-18.
//
#ifndef MOBILEGL_EGL_IMPL_H
#define MOBILEGL_EGL_IMPL_H
#ifndef MOBILEGL_DILIGENT_EGL_IMPL_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#include "../../../../Includes.h"
#include "DiligentConfig.h"
#if BACKEND_TYPE == BACKEND_DILIGENT
namespace MG_EGL::Diligent {
struct DeviceContext {
public:
::Diligent::RefCntAutoPtr<::Diligent::IRenderDevice> pDevice;
::Diligent::RefCntAutoPtr<::Diligent::IDeviceContext> pContext;
::Diligent::RefCntAutoPtr<::Diligent::ISwapChain> pSwapChain;
::Diligent::RefCntAutoPtr<::Diligent::IPipelineState> pPSO;
::Diligent::RefCntAutoPtr<::Diligent::IRenderPass> pRenderPass;
std::vector<::Diligent::RefCntAutoPtr<::Diligent::IFramebuffer>> pFramebuffers;
bool initialized = false;
int majorVer = 1;
int minorVer = 5;
namespace MG_Diligent {
extern Diligent::IRenderDevice* g_pDevice;
extern Diligent::IDeviceContext* g_pContext;
extern Diligent::ISwapChain* g_pSwapChain;
extern MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_BufferMap;
extern MG_Global::unordered_map<GLuint, Diligent::ITexture*> g_TextureMap;
extern MG_Global::unordered_map<GLuint, Diligent::ITextureView*> g_TextureViewMap;
extern MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_BufferMap;
struct GLFramebufferInfo
{
Diligent::IFramebuffer* pFramebuffer = nullptr;
Diligent::IRenderPass* pRenderPass = nullptr;
std::vector<Diligent::ITextureView*> ColorRTVs;
Diligent::ITextureView* pDepthStencilRTV = nullptr;
Diligent::TEXTURE_FORMAT DepthStencilFormat = Diligent::TEX_FORMAT_UNKNOWN;
bool HasDepthStencil = false;
std::vector<Diligent::OptimizedClearValue> ClearValues;
// ...
};
extern MG_Global::unordered_map<GLuint, GLFramebufferInfo> g_FramebufferMap;
extern MG_Global::unordered_map<GLuint, Diligent::IShader*> g_ShaderMap;
struct GLProgramInfo
{
GLuint id;
std::vector<Diligent::IShader*> AttachedShaders;
std::vector<GLuint> AttachedShadersID;
Diligent::IPipelineState* pPipelineState = nullptr;
Diligent::IShaderResourceBinding* pResourceBinding = nullptr;
uint64_t psoStateHash = 0;
bool psoDirty = true;
std::vector<Diligent::LayoutElement> inputLayout;
GLuint DefaultFBO = 0;
ProgramObject programObj;
Diligent::IBuffer* pDefaultUBO = nullptr;
std::unordered_map<std::string, Diligent::SHADER_TYPE> uniformStages;
std::unordered_map<std::string, size_t> uniformOffsets;
// ...
};
extern MG_Global::unordered_map<GLuint, GLProgramInfo> g_ProgramMap;
extern MG_Global::unordered_map<GLuint, Diligent::ISampler*> g_SamplerMap;
extern MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_UniformBufferMap;
class PipelineStateManager {
private:
struct PSOKey {
uint64_t programHash;
uint64_t stateHash;
bool operator==(const PSOKey &other) const {
return programHash == other.programHash && stateHash == other.stateHash;
}
};
struct PSOKeyHash {
size_t operator()(const PSOKey &key) const {
return std::hash<uint64_t>()(key.programHash) ^
std::hash<uint64_t>()(key.stateHash);
}
};
std::unordered_map<PSOKey, Diligent::IPipelineState *, PSOKeyHash> psoCache;
public:
Diligent::IPipelineState *GetOrCreatePSO(
GLuint program,
GLProgramInfo &programInfo,
CommonState &commonState,
VertexArrayState &vaState,
GLFramebufferInfo& fbInfo);
void MarkPSODirty(GLuint program);
void ReleasePSO(GLuint program);
private:
Diligent::FILTER_TYPE ConvertGLFilter(GLenum filter) {
switch (filter) {
case GL_NEAREST:
case GL_NEAREST_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
return Diligent::FILTER_TYPE_POINT;
case GL_LINEAR:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_LINEAR:
return Diligent::FILTER_TYPE_LINEAR;
default:
return Diligent::FILTER_TYPE_LINEAR;
}
}
Diligent::FILTER_TYPE ConvertGLMipFilter(GLenum filter) {
switch (filter) {
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
return Diligent::FILTER_TYPE_POINT;
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
return Diligent::FILTER_TYPE_LINEAR;
case GL_NEAREST:
case GL_LINEAR:
return Diligent::FILTER_TYPE_LINEAR;
default:
return Diligent::FILTER_TYPE_LINEAR;
}
}
Diligent::TEXTURE_ADDRESS_MODE ConvertGLWrapMode(GLenum wrap) {
switch (wrap) {
case GL_REPEAT:
return Diligent::TEXTURE_ADDRESS_WRAP;
case GL_MIRRORED_REPEAT:
return Diligent::TEXTURE_ADDRESS_MIRROR;
case GL_CLAMP_TO_EDGE:
return Diligent::TEXTURE_ADDRESS_CLAMP;
case GL_CLAMP_TO_BORDER:
return Diligent::TEXTURE_ADDRESS_BORDER;
case GL_MIRROR_CLAMP_TO_EDGE:
return Diligent::TEXTURE_ADDRESS_MIRROR_ONCE;
default:
return Diligent::TEXTURE_ADDRESS_WRAP;
}
}
Diligent::BLEND_FACTOR ConvertGLBlendFactor(GLenum factor) {
switch (factor) {
case GL_ZERO:
return Diligent::BLEND_FACTOR_ZERO;
case GL_ONE:
return Diligent::BLEND_FACTOR_ONE;
case GL_SRC_COLOR:
return Diligent::BLEND_FACTOR_SRC_COLOR;
case GL_ONE_MINUS_SRC_COLOR:
return Diligent::BLEND_FACTOR_INV_SRC_COLOR;
case GL_DST_COLOR:
return Diligent::BLEND_FACTOR_DEST_COLOR;
case GL_ONE_MINUS_DST_COLOR:
return Diligent::BLEND_FACTOR_INV_DEST_COLOR;
case GL_SRC_ALPHA:
return Diligent::BLEND_FACTOR_SRC_ALPHA;
case GL_ONE_MINUS_SRC_ALPHA:
return Diligent::BLEND_FACTOR_INV_SRC_ALPHA;
case GL_DST_ALPHA:
return Diligent::BLEND_FACTOR_DEST_ALPHA;
case GL_ONE_MINUS_DST_ALPHA:
return Diligent::BLEND_FACTOR_INV_DEST_ALPHA;
default:
return Diligent::BLEND_FACTOR_ONE;
}
}
Diligent::COMPARISON_FUNCTION ConvertGLDepthFunc(GLenum func) {
switch (func) {
case GL_LESS:
return Diligent::COMPARISON_FUNC_LESS;
case GL_LEQUAL:
return Diligent::COMPARISON_FUNC_LESS_EQUAL;
case GL_GREATER:
return Diligent::COMPARISON_FUNC_GREATER;
case GL_GEQUAL:
return Diligent::COMPARISON_FUNC_GREATER_EQUAL;
case GL_EQUAL:
return Diligent::COMPARISON_FUNC_EQUAL;
case GL_NOTEQUAL:
return Diligent::COMPARISON_FUNC_NOT_EQUAL;
case GL_ALWAYS:
return Diligent::COMPARISON_FUNC_ALWAYS;
case GL_NEVER:
return Diligent::COMPARISON_FUNC_NEVER;
default:
return Diligent::COMPARISON_FUNC_LESS;
}
}
uint64_t CalculateStateHash(
CommonState &commonState,
VertexArrayState &vaState,
GLFramebufferInfo& fbInfo) {
uint64_t hash = 0;
MG_Global::unordered_map<GLenum, bool> capabilities = commonState.capabilities;
hash ^= std::hash<int>()(commonState.blendSrcRGB);
hash ^= std::hash<int>()(commonState.blendDstRGB);
hash ^= std::hash<int>()(commonState.blendSrcAlpha);
hash ^= std::hash<int>()(commonState.blendDstAlpha);
hash ^= std::hash<bool>()(capabilities[GL_BLEND]);
hash ^= std::hash<int>()(commonState.depthFunc);
hash ^= std::hash<bool>()(commonState.depthMask);
hash ^= std::hash<bool>()(capabilities[GL_DEPTH_TEST]);
hash ^= std::hash<int>()(0); // TODO: Cull Face Mode
hash ^= std::hash<bool>()(capabilities[GL_CULL_FACE]);
hash ^= std::hash<bool>()(capabilities[GL_STENCIL_TEST]);
auto *pVAO = vaState.GetCurrentVAO();
for (const auto &[index, attrib]: pVAO->attribs) {
if (attrib.enabled) {
hash ^= std::hash<int>()(index);
hash ^= std::hash<int>()(attrib.size);
hash ^= std::hash<int>()(attrib.type);
hash ^= std::hash<bool>()(attrib.normalized);
}
}
hash ^= std::hash<size_t>()(fbInfo.ColorRTVs.size());
for (const auto& rtv : fbInfo.ColorRTVs) {
if (rtv) {
hash ^= std::hash<uint32_t>()(rtv->GetDesc().Format);
}
}
hash ^= std::hash<uint32_t>()(fbInfo.DepthStencilFormat);
return hash;
}
void ConfigurePSO(
Diligent::GraphicsPipelineStateCreateInfo &PSOCreateInfo,
GLProgramInfo &programInfo,
CommonState &commonState,
VertexArrayState &vaState,
GLFramebufferInfo& fbInfo);
void ConfigureResourceLayout(
Diligent::GraphicsPipelineStateCreateInfo& PSOCreateInfo,
const GLProgramInfo& programInfo);
};
static struct DeviceContext ctx;
extern PipelineStateManager g_PSOManager;
extern bool initialized;
extern bool IsInRenderPass;
}
namespace MG_EGL::Diligent {
EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint* attrib_list);
EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config);
@@ -48,14 +272,9 @@ namespace MG_EGL::Diligent {
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
}
#define MG_EGL_PROC_EXPORT(name) \
if (strncmp(procname, #name, strlen(#name)) == 0) { \
return (__eglMustCastToProperFunctionPointerType)(&MG_EGL::Diligent::name); \
}
MG_EXPORT __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname);
#endif
#endif //MOBILEGL_EGL_IMPL_H
#endif //MOBILEGL_DILIGENT_EGL_IMPL_H
+3 -3
View File
@@ -11,9 +11,9 @@ std::atomic<uintptr_t> g_nextSurfaceId{1};
EGLenum g_currentAPI = EGL_OPENGL_ES_API;
std::mutex g_globalMutex;
ankerl::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
ankerl::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
ankerl::unordered_map<EGLContext, VulkanContext> g_contexts;
MG_Global::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
MG_Global::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
MG_Global::unordered_map<EGLContext, VulkanContext> g_contexts;
EGLint g_lastError = EGL_SUCCESS;
thread_local EGLContext tls_currentContext = EGL_NO_CONTEXT;
+3 -3
View File
@@ -69,9 +69,9 @@ extern std::atomic<uintptr_t> g_nextSurfaceId;
extern EGLenum g_currentAPI;
extern std::mutex g_globalMutex;
extern ankerl::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
extern ankerl::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
extern ankerl::unordered_map<EGLContext, VulkanContext> g_contexts;
extern MG_Global::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
extern MG_Global::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
extern MG_Global::unordered_map<EGLContext, VulkanContext> g_contexts;
extern EGLint g_lastError;
extern thread_local EGLContext tls_currentContext;
@@ -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));
}