[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
+21 -21
View File
@@ -21,11 +21,11 @@
#define MG_EXPORT extern "C" __attribute__((visibility("default")))
#endif
namespace ankerl {
template <typename K, typename V>
namespace MG_Global {
template<typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
template <typename T>
template<typename T>
using unordered_set = ankerl::unordered_dense::set<T>;
}
@@ -39,7 +39,7 @@ namespace MG_Constants {
}
namespace Blend {
static const ankerl::unordered_set<GLenum> VALID_FACTORS = {
static const MG_Global::unordered_set<GLenum> VALID_FACTORS = {
GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
@@ -48,51 +48,51 @@ namespace MG_Constants {
}
namespace Depth {
static const ankerl::unordered_set<GLenum> VALID_FUNCS = {
static const MG_Global::unordered_set<GLenum> VALID_FUNCS = {
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
}; // OpenGL 3
}
namespace CommonState {
static const ankerl::unordered_set<GLenum> VALID_CAPS = {
static const MG_Global::unordered_set<GLenum> VALID_CAPS = {
GL_BLEND, GL_DEPTH_TEST, GL_STENCIL_TEST, GL_SCISSOR_TEST, GL_CULL_FACE,
GL_POLYGON_OFFSET_FILL, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE
}; // OpenGL 3
}
namespace Framebuffer {
static const ankerl::unordered_set<GLenum> VALID_ATTACHMENTS = {
static const MG_Global::unordered_set<GLenum> VALID_ATTACHMENTS = {
GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT
}; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_TARGETS = {
static const MG_Global::unordered_set<GLenum> VALID_TARGETS = {
GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER
}; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_ACCESS = {
static const MG_Global::unordered_set<GLenum> VALID_ACCESS = {
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
}; // OpenGL 3
}
namespace Buffer {
static const ankerl::unordered_set<GLenum> VALID_PARAM_NAMES = {
static const MG_Global::unordered_set<GLenum> VALID_PARAM_NAMES = {
GL_BUFFER_ACCESS, GL_BUFFER_MAPPED, GL_BUFFER_SIZE, GL_BUFFER_USAGE
}; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_TARGETS = {
static const MG_Global::unordered_set<GLenum> VALID_TARGETS = {
GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER,
GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER
}; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_ACCESS = {
static const MG_Global::unordered_set<GLenum> VALID_ACCESS = {
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
}; // OpenGL 3
}
namespace PixelStore {
static const ankerl::unordered_map<GLenum, GLint> DEFAULT_VALUES_MAP = {
static const MG_Global::unordered_map<GLenum, GLint> DEFAULT_VALUES_MAP = {
{GL_PACK_SWAP_BYTES, GL_FALSE},
{GL_PACK_LSB_FIRST, GL_FALSE},
{GL_PACK_ROW_LENGTH, 0},
@@ -111,7 +111,7 @@ namespace MG_Constants {
{GL_UNPACK_ALIGNMENT, 4}
}; // OpenGL 3
static const ankerl::unordered_set<GLenum> VALID_PARAM_NAMES = {
static const MG_Global::unordered_set<GLenum> VALID_PARAM_NAMES = {
GL_PACK_SWAP_BYTES, GL_PACK_LSB_FIRST, GL_PACK_ROW_LENGTH, GL_PACK_IMAGE_HEIGHT,
GL_PACK_SKIP_ROWS, GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_IMAGES, GL_PACK_ALIGNMENT,
GL_UNPACK_SWAP_BYTES, GL_UNPACK_LSB_FIRST, GL_UNPACK_ROW_LENGTH,
@@ -125,18 +125,18 @@ namespace MG_Constants {
inline const GLuint MAX_TEXTURE_UNITS = 80;
const GLsizei MAX_TEXTURE_SIZE = 32768;
const GLsizei MAX_ARRAY_LAYERS = 256;
inline const ankerl::unordered_set<GLenum> VALID_TARGETS = {
inline const MG_Global::unordered_set<GLenum> VALID_TARGETS = {
GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D, GL_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_1D_ARRAY,
GL_TEXTURE_RECTANGLE, GL_PROXY_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_PROXY_TEXTURE_CUBE_MAP
}; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_FORMATS = {
inline const MG_Global::unordered_set<GLenum> VALID_FORMATS = {
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL
}; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_INTERNAL_FORMATS = {
inline const MG_Global::unordered_set<GLenum> VALID_INTERNAL_FORMATS = {
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL,
GL_RGBA32F, GL_RGBA32I, GL_RGBA32UI, GL_RGBA16, GL_RGBA16F, GL_RGBA16I,
GL_RGBA16UI, GL_RGBA8, GL_RGBA8UI, GL_SRGB8_ALPHA8, GL_RGB10_A2, GL_RGB10_A2UI,
@@ -151,7 +151,7 @@ namespace MG_Constants {
GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8
}; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_TYPES = {
inline const MG_Global::unordered_set<GLenum> VALID_TYPES = {
GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT,
GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5,
GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
@@ -159,14 +159,14 @@ namespace MG_Constants {
GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
}; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_TEXTURE_PARAM_NAMES = {
inline const MG_Global::unordered_set<GLenum> VALID_TEXTURE_PARAM_NAMES = {
GL_TEXTURE_BASE_LEVEL, GL_TEXTURE_COMPARE_FUNC, GL_TEXTURE_COMPARE_MODE, GL_TEXTURE_MIN_FILTER,
GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MAX_LEVEL, GL_TEXTURE_SWIZZLE_R, GL_TEXTURE_SWIZZLE_G,
GL_TEXTURE_SWIZZLE_B, GL_TEXTURE_SWIZZLE_A, GL_TEXTURE_SWIZZLE_RGBA, GL_TEXTURE_WRAP_S,
GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_R, GL_TEXTURE_LOD_BIAS, GL_TEXTURE_MIN_LOD, GL_TEXTURE_MAX_LOD, GL_TEXTURE_BORDER_COLOR
}; // OpenGL 3
inline const ankerl::unordered_set<GLenum> VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES = {
inline const MG_Global::unordered_set<GLenum> VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES = {
GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH, GL_TEXTURE_INTERNAL_FORMAT,
GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE,
GL_TEXTURE_DEPTH_SIZE, GL_TEXTURE_COMPRESSED, GL_TEXTURE_COMPRESSED_IMAGE_SIZE
+1 -1
View File
@@ -27,7 +27,7 @@ namespace MG_Global {
}
namespace Common {
inline constexpr int LogLevel = MG_Constants::Common::LOG_LEVEL_INFO;
inline constexpr int LogLevel = MG_Constants::Common::LOG_LEVEL_DEBUG;
#ifdef __ANDROID__
inline const char* LOG_FILE_PATH = "/sdcard/MG/latest.log";
+4
View File
@@ -32,6 +32,9 @@
#ifndef MOBILEGL_GL_VERTEXARRAY_H
#include "MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h"
#endif
#ifndef MOBILEGL_DILIGENT_EGL_IMPL_H
#include "MG_GL/Implementations/EGL/Diligent/EGL_impl.h"
#endif
#ifndef MOBILEGL_GLSTATE_H
#include "MG_GL/State/Core/GLState.h"
#endif
@@ -90,6 +93,7 @@
#include <string>
#include <map>
#include <vector>
#include <cctype>
#include <stdexcept>
#include <atomic>
#include <regex>
+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));
}
+3 -5
View File
@@ -5,13 +5,11 @@
#ifndef MOBILEGL_BUFFERSTATE_H
#define MOBILEGL_BUFFERSTATE_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#include "../../../Includes.h"
class BufferState {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
public:
struct BufferObject {
GLenum usage = GL_STATIC_DRAW;
@@ -46,8 +44,8 @@ public:
void Delete(GLuint buffer);
GLuint GetCurrentBinding(GLenum target) const;
unordered_map<GLenum, GLuint> currentBindings_;
unordered_map<GLuint, BufferObject> buffers_;
MG_Global::unordered_map<GLenum, GLuint> currentBindings_;
MG_Global::unordered_map<GLuint, BufferObject> buffers_;
private:
std::vector<GLuint> freeId_;
GLuint lastId_ = 1;
+3 -4
View File
@@ -5,12 +5,11 @@
#ifndef MOBILEGL_COMMONSTATE_H
#define MOBILEGL_COMMONSTATE_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#include "../../../Includes.h"
class CommonState {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
public:
// Viewport
GLint viewport[4] = {0, 0, 0, 0};
@@ -19,7 +18,7 @@ public:
GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
// Pixel storage parameters
unordered_map<GLenum, GLint> pixelStoreParams;
MG_Global::unordered_map<GLenum, GLint> pixelStoreParams;
// Blend state
GLenum blendSrcRGB = GL_ONE;
@@ -37,7 +36,7 @@ public:
GLboolean depthMask = GL_TRUE;
// Capability enables
unordered_map<GLenum, bool> capabilities;
MG_Global::unordered_map<GLenum, bool> capabilities;
CommonState();
+1
View File
@@ -4,6 +4,7 @@
#ifndef MOBILEGL_GLSTATE_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#include "../../../Includes.h"
@@ -47,6 +47,7 @@ GLenum FramebufferState::Bind(GLenum target, GLuint framebuffer) {
if (framebuffer != 0 && !ValidateHandle(framebuffer))
return GL_INVALID_OPERATION;
if (target == GL_FRAMEBUFFER) {
currentBindings_[GL_FRAMEBUFFER] = framebuffer;
currentBindings_[GL_READ_FRAMEBUFFER] = framebuffer;
currentBindings_[GL_DRAW_FRAMEBUFFER] = framebuffer;
} else {
@@ -60,7 +61,7 @@ GLenum FramebufferState::AttachTexture2D(GLenum target, GLenum attachment,
if (MG_Constants::Framebuffer::VALID_ATTACHMENTS.find(attachment) == MG_Constants::Framebuffer::VALID_ATTACHMENTS.end() ||
MG_Constants::Texture::VALID_TARGETS.find(textarget) == MG_Constants::Texture::VALID_TARGETS.end())
return GL_INVALID_ENUM;
if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER;
// if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER;
FramebufferObject* fbo = GetCurrentFBO(target);
if (!fbo) return GL_INVALID_OPERATION;
if (texture != 0 && !MG_State_T::textureState->IsTexture(texture))
@@ -85,7 +86,7 @@ GLenum FramebufferState::AttachTexture2D(GLenum target, GLenum attachment,
}
GLenum FramebufferState::ValidateCompleteness(GLenum target) {
if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER;
// if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER;
FramebufferObject* fbo = GetCurrentFBO(target);
if (!fbo) return GL_INVALID_OPERATION;
return fbo->status;
@@ -5,6 +5,7 @@
#ifndef MOBILEGL_FRAMEBUFFERSTATE_H
#define MOBILEGL_FRAMEBUFFERSTATE_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#include "../../../Includes.h"
@@ -17,7 +18,7 @@ struct FramebufferAttachment {
struct FramebufferObject {
bool generated = false;
ankerl::unordered_map<GLenum, FramebufferAttachment> attachments;
MG_Global::unordered_map<GLenum, FramebufferAttachment> attachments;
GLenum status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
GLsizei width = 0;
GLsizei height = 0;
@@ -35,10 +36,10 @@ public:
GLenum ValidateCompleteness(GLenum target);
FramebufferObject* GetCurrentFBO(GLenum target);
ankerl::unordered_map<GLenum, GLuint> currentBindings_; // READ/DRAW
MG_Global::unordered_map<GLenum, GLuint> currentBindings_; // READ/DRAW
private:
ankerl::unordered_map<GLuint, FramebufferObject> framebuffers_;
MG_Global::unordered_map<GLuint, FramebufferObject> framebuffers_;
std::set<GLuint> freeIds_;
GLuint lastId_ = 0;
bool ValidateHandle(GLuint framebuffer);
+7 -6
View File
@@ -5,6 +5,7 @@
#ifndef MOBILEGL_PROGRAMSTATE_H
#define MOBILEGL_PROGRAMSTATE_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#define MOBILEGL_PROGRAM_DEBUGTOOL_H
#define MOBILEGL_GLSLTOOL_H
@@ -41,17 +42,17 @@ struct ProgramObject {
bool dirty;
GLint linkStatus;
std::string infoLog;
ankerl::unordered_map<std::string, GLint> attribBindings;
ankerl::unordered_map<std::string, GLint> attribLocations;
ankerl::unordered_map<std::string, GLint> uniformLocations;
ankerl::unordered_map<std::string, UniformValue> uniformValues;
MG_Global::unordered_map<std::string, GLint> attribBindings;
MG_Global::unordered_map<std::string, GLint> attribLocations;
MG_Global::unordered_map<std::string, GLint> uniformLocations;
MG_Global::unordered_map<std::string, UniformValue> uniformValues;
bool markedForDeletion;
};
class ProgramState {
public:
ankerl::unordered_map<GLuint, ShaderObject> shaders_;
ankerl::unordered_map<GLuint, ProgramObject> programs_;
MG_Global::unordered_map<GLuint, ShaderObject> shaders_;
MG_Global::unordered_map<GLuint, ProgramObject> programs_;
std::set<GLuint> freeShaderIds_;
std::set<GLuint> freeProgramIds_;
GLuint lastShaderId_ = 0;
+1
View File
@@ -6,6 +6,7 @@
#define MOBILEGL_SHADEROBJECT_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#include "../../../Includes.h"
+1 -2
View File
@@ -146,7 +146,6 @@ GLenum TextureState::Bind(GLenum target, GLuint texture) {
}
}
TextureUnitState& unit = textureUnits_[activeTextureUnit_];
TextureObject* texObj = nullptr;
auto it = this->textures.find(texture);
@@ -700,7 +699,7 @@ GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLe
return GL_NO_ERROR;
}
unordered_map<GLuint, TextureObject>::iterator texIt;
MG_Global::unordered_map<GLuint, TextureObject>::iterator texIt;
if (!isProxyTexture) {
texIt = textures.find(boundTexture);
+8 -13
View File
@@ -5,6 +5,7 @@
#ifndef MOBILEGL_TEXTURESTATE_H
#define MOBILEGL_TEXTURESTATE_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#include "../../../Includes.h"
@@ -19,10 +20,8 @@ struct ComponentSizes {
};
struct TextureParams {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
unordered_map<GLenum, GLfloat> texPropertiesFloat;
unordered_map<GLenum, GLint> texPropertiesInt;
MG_Global::unordered_map<GLenum, GLfloat> texPropertiesFloat;
MG_Global::unordered_map<GLenum, GLint> texPropertiesInt;
struct MipmapLevel {
GLsizei width = 0;
GLsizei height = 0;
@@ -33,7 +32,7 @@ struct TextureParams {
bool hasData = false;
bool dirty = false; // TODO: encapsulate this with an public API to RHI
};
unordered_map<GLint, MipmapLevel> mipmapData;
MG_Global::unordered_map<GLint, MipmapLevel> mipmapData;
};
class TextureObject {
@@ -47,27 +46,23 @@ public:
};
class TextureUnitState {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
private:
GLenum activeTarget = GL_TEXTURE_2D;
public:
unordered_map<GLenum, GLuint> boundTextures;
MG_Global::unordered_map<GLenum, GLuint> boundTextures;
void Bind(GLenum target, GLuint texture);
GLuint GetBoundTexture(GLenum target);
};
class TextureState {
template <typename K, typename V>
using unordered_map = ankerl::unordered_dense::map<K, V>;
private:
GLuint lastUsedID_ = 1;
// ankerl::unordered_set<GLuint> freeIDs_;
// MG_Global::unordered_set<GLuint> freeIDs_;
std::vector<GLuint> freeID_;
unordered_map<GLenum, TextureObject> proxyTextures_;
MG_Global::unordered_map<GLenum, TextureObject> proxyTextures_;
static GLint GetUnpackParam_(GLenum pname);
public:
@@ -75,7 +70,7 @@ public:
bool IsTextureGenerated(GLuint texture);
bool IsTexture(GLuint texture);
unordered_map<GLuint, TextureObject> textures;
MG_Global::unordered_map<GLuint, TextureObject> textures;
// Return: the validity of the operation, according to OpenGL 3 standard
GLenum BindUnit(GLenum textureUnit);
@@ -5,6 +5,7 @@
#ifndef MOBILEGL_VERTEXARRAYSTATE_H
#define MOBILEGL_VERTEXARRAYSTATE_H
#define MOBILEGL_GLSTATE_H
#define MOBILEGL_DILIGENT_EGL_IMPL_H
#include "../../../Includes.h"
@@ -24,7 +25,7 @@ struct VertexArrayObject {
bool attribDirty = false;
bool eboDirty = false;
GLuint elementBuffer = 0;
ankerl::unordered_map<GLuint, VertexAttribState> attribs;
MG_Global::unordered_map<GLuint, VertexAttribState> attribs;
};
class VertexArrayState {
@@ -50,7 +51,7 @@ public:
bool ValidateAllocatedHandle(GLuint array);
GLuint currentVao_ = 0;
ankerl::unordered_map<GLuint, VertexArrayObject> vaos_;
MG_Global::unordered_map<GLuint, VertexArrayObject> vaos_;
private:
std::set<GLuint> freeIds_;
GLuint lastId_ = 0;
+2 -2
View File
@@ -53,8 +53,8 @@ namespace MG_RHI::GLES::Test {
GLuint quadVBO = 0;
GLint uTexLoc = -1;
GLint uMVPLoc = -1;
ankerl::unordered_map<GLuint, GLuint> textureCache;
ankerl::unordered_map<GLuint, bool> textureDirty;
MG_Global::unordered_map<GLuint, GLuint> textureCache;
MG_Global::unordered_map<GLuint, bool> textureDirty;
};
static ScreenResources sRes;
+480 -1
View File
@@ -5,6 +5,485 @@
#include "GLSLTool.h"
namespace MG_Util::Program {
static std::vector<bool> buildCommentMask(const std::string &src) {
enum State {
NORMAL,
LINE_COMMENT,
BLOCK_COMMENT,
STRING_LITERAL,
CHAR_LITERAL
};
std::vector<bool> isComment(src.size(), false);
State state = NORMAL;
for (size_t i = 0; i < src.size(); ++i) {
switch (state) {
case NORMAL:
if (i + 1 < src.size() && src[i] == '/' && src[i + 1] == '/') {
state = LINE_COMMENT;
isComment[i] = true;
isComment[i + 1] = true;
++i;
}
else if (i + 1 < src.size() && src[i] == '/' && src[i + 1] == '*') {
state = BLOCK_COMMENT;
isComment[i] = true;
isComment[i + 1] = true;
++i;
}
else if (src[i] == '"') {
state = STRING_LITERAL;
}
else if (src[i] == '\'') {
state = CHAR_LITERAL;
}
break;
case LINE_COMMENT:
isComment[i] = true;
if (src[i] == '\n') {
state = NORMAL;
}
break;
case BLOCK_COMMENT:
isComment[i] = true;
if (i + 1 < src.size() && src[i] == '*' && src[i + 1] == '/') {
isComment[i + 1] = true;
state = NORMAL;
++i;
}
break;
case STRING_LITERAL:
if (src[i] == '\\' && (i + 1 < src.size())) {
i++;
}
else if (src[i] == '"') {
state = NORMAL;
}
break;
case CHAR_LITERAL:
if (src[i] == '\\' && (i + 1 < src.size())) {
i++;
}
else if (src[i] == '\'') {
state = NORMAL;
}
break;
}
}
return isComment;
}
static bool isPreprocessorLine(const std::string &src, size_t pos) {
size_t lineStart = src.rfind('\n', pos);
if (lineStart == std::string::npos) {
lineStart = 0;
} else {
lineStart += 1;
}
size_t firstNonSpace = src.find_first_not_of(" \t\r\n", lineStart);
if (firstNonSpace != std::string::npos && src[firstNonSpace] == '#') {
return true;
}
return false;
}
static inline bool isInComment(const std::vector<bool> &mask, size_t pos) {
if (pos >= mask.size()) return false;
return mask[pos];
}
static inline void leftTrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
static inline void rightTrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
static inline void trim(std::string &s) {
leftTrim(s);
rightTrim(s);
}
static size_t findNextNonSpace(const std::string& str, size_t pos) {
return str.find_first_not_of(" \t\r\n", pos);
}
static std::string extractVarNameFromUniformDecl(const std::string& decl) {
const std::regex layoutRegex(R"(\s*layout\s*\([^)]*\))");
std::string declNoLayout = std::regex_replace(decl, layoutRegex, "");
size_t uniformPos = declNoLayout.find("uniform");
if (uniformPos != std::string::npos) {
declNoLayout = declNoLayout.substr(uniformPos + 7);
}
trim(declNoLayout);
size_t semiPos = declNoLayout.rfind(';');
if (semiPos != std::string::npos) {
declNoLayout = declNoLayout.substr(0, semiPos);
}
trim(declNoLayout);
size_t lastSpace = declNoLayout.find_last_of(" \t\r\n");
if (lastSpace == std::string::npos) {
return declNoLayout;
}
std::string candidate = declNoLayout.substr(lastSpace + 1);
size_t bracketPos = candidate.find('[');
if (bracketPos != std::string::npos) {
candidate = candidate.substr(0, bracketPos);
}
return candidate;
}
std::pair<std::string, std::string> GenerateDefaultUBOForGLSL(const std::pair<std::string,
std::string>& glslSources) {
std::string source1 = glslSources.first;
std::string source2 = glslSources.second;
std::vector<bool> commentMask1 = buildCommentMask(source1);
std::vector<bool> commentMask2 = buildCommentMask(source2);
const std::regex layoutRegex(R"(\s*layout\s*\([^)]*\))");
std::set<std::string> allUniformNames;
std::vector<std::string> mergedUniforms;
std::vector<std::pair<size_t, size_t>> removalSpans1;
std::vector<std::pair<size_t, size_t>> removalSpans2;
auto processSource = [&](std::string& source, const std::vector<bool>& commentMask,
std::vector<std::pair<size_t, size_t>>& removalSpans,
bool isFirstSource)
{
size_t searchPos = 0;
while ((searchPos = source.find("uniform", searchPos)) != std::string::npos) {
if (isInComment(commentMask, searchPos)) {
searchPos++;
continue;
}
if (isPreprocessorLine(source, searchPos)) {
searchPos++;
continue;
}
if (searchPos > 0 && (std::isalnum(source[searchPos - 1]) || source[searchPos - 1] == '_')) {
searchPos++;
continue;
}
size_t nextCharPos = findNextNonSpace(source, searchPos + 7);
if (nextCharPos == std::string::npos) break;
if (source[nextCharPos] == '{') {
searchPos = nextCharPos + 1;
continue;
}
size_t bracePos = source.find('{', nextCharPos);
size_t semicolonPos = source.find(';', nextCharPos);
if (bracePos != std::string::npos && (semicolonPos == std::string::npos || bracePos < semicolonPos)) {
searchPos = bracePos + 1;
continue;
}
if (semicolonPos == std::string::npos) {
searchPos++;
continue;
}
size_t declStart = searchPos;
size_t declLength = semicolonPos - searchPos + 1;
std::string declaration = source.substr(declStart, declLength);
std::string declNoLayout = std::regex_replace(declaration, layoutRegex, "");
std::string afterUniform = declNoLayout.substr(declNoLayout.find("uniform") + 7);
trim(afterUniform);
size_t sep = afterUniform.find_first_of(" \t\r\n[");
std::string typeToken = (sep == std::string::npos ? afterUniform : afterUniform.substr(0, sep));
bool isSamplerOrImage = false;
if (typeToken.rfind("sampler", 0) == 0 ||
typeToken.rfind("isampler", 0) == 0 ||
typeToken.rfind("usampler", 0) == 0 ||
typeToken.rfind("image", 0) == 0)
{
isSamplerOrImage = true;
}
if (isSamplerOrImage) {
searchPos = declStart + declLength;
continue;
}
std::string varName = extractVarNameFromUniformDecl(declaration);
if (isFirstSource) {
mergedUniforms.push_back(declaration);
allUniformNames.insert(varName);
} else {
if (allUniformNames.find(varName) == allUniformNames.end()) {
mergedUniforms.push_back(declaration);
allUniformNames.insert(varName);
}
}
size_t removeStart = declStart;
{
size_t scanBack = declStart;
while (scanBack > 0 && std::isspace((unsigned char)source[scanBack - 1])) {
scanBack--;
}
if (scanBack >= 6) {
size_t maybeLayout = source.rfind("layout", scanBack - 6);
if (maybeLayout != std::string::npos) {
size_t parenOpen = source.find('(', maybeLayout + 6);
if (parenOpen != std::string::npos && parenOpen < scanBack) {
size_t parenClose = source.find(')', parenOpen);
if (parenClose != std::string::npos && parenClose < declStart) {
std::string between = source.substr(maybeLayout, declStart - maybeLayout);
const std::regex onlyLayout(R"(layout\s*\([^)]*\)\s*)");
if (std::regex_match(between, onlyLayout)) {
removeStart = maybeLayout;
}
}
}
}
}
}
removalSpans.emplace_back(removeStart, (declStart + declLength) - removeStart);
searchPos = declStart + declLength;
}
};
processSource(source1, commentMask1, removalSpans1, true);
processSource(source2, commentMask2, removalSpans2, false);
if (mergedUniforms.empty()) {
return glslSources;
}
std::sort(removalSpans1.rbegin(), removalSpans1.rend());
for (auto &span : removalSpans1) {
source1.erase(span.first, span.second);
}
source1 = std::regex_replace(source1, std::regex(R"((\r\n|\n|\r){2,})"), "$1");
std::sort(removalSpans2.rbegin(), removalSpans2.rend());
for (auto &span : removalSpans2) {
source2.erase(span.first, span.second);
}
source2 = std::regex_replace(source2, std::regex(R"((\r\n|\n|\r){2,})"), "$1");
std::string uboBlock = "\nlayout(std140) uniform MG_DEFAULT_UBO\n{\n";
for (auto &decl : mergedUniforms) {
std::string cleaned = std::regex_replace(decl, layoutRegex, "");
std::string memberDecl = cleaned.substr(cleaned.find("uniform") + 7);
size_t semiPos = memberDecl.rfind(';');
if (semiPos != std::string::npos) {
memberDecl.erase(semiPos);
}
trim(memberDecl);
uboBlock += " " + memberDecl + ";\n";
}
uboBlock += "};\n";
auto insertUBO = [&](std::string& source) {
size_t insertPos = 0, lastDirectivePos = 0;
size_t searchPos = 0;
while ((searchPos = source.find('#', searchPos)) != std::string::npos) {
if (isInComment(commentMask1, searchPos)) {
searchPos++;
continue;
}
size_t eol = source.find('\n', searchPos);
if (eol == std::string::npos) break;
std::string line = source.substr(searchPos, eol - searchPos);
if (line.find("#version") != std::string::npos || line.find("#extension") != std::string::npos) {
lastDirectivePos = eol + 1;
}
searchPos = eol + 1;
}
insertPos = lastDirectivePos;
source.insert(insertPos, uboBlock);
};
insertUBO(source1);
insertUBO(source2);
return {source1, source2};
}
void GenerateDefaultUBOForGLSL_Multi(
MG_Global::unordered_map<GLuint, std::string> &shaderSources) {
if (shaderSources.empty()) return;
std::unordered_map<GLuint, std::vector<bool>> commentMasks;
for (auto const& [id, source] : shaderSources) {
commentMasks[id] = buildCommentMask(source);
}
const std::regex layoutRegex(R"(\s*layout\s*\([^)]*\))");
std::set<std::string> allUniformNames;
std::vector<std::string> mergedUniforms;
std::unordered_map<GLuint, std::vector<std::pair<size_t, size_t>>> removalSpansPerShader;
for (auto& [id, source] : shaderSources) {
std::vector<bool>& commentMask = commentMasks[id];
// Ensure an entry exists for this shader ID, even if no uniforms are found
auto& removalSpans = removalSpansPerShader[id];
size_t searchPos = 0;
while ((searchPos = source.find("uniform", searchPos)) != std::string::npos) {
if (isInComment(commentMask, searchPos)) {
searchPos++;
continue;
}
if (isPreprocessorLine(source, searchPos)) {
searchPos++;
continue;
}
if (searchPos > 0 && (std::isalnum(source[searchPos - 1]) ||
source[searchPos - 1] == '_')) {
searchPos++;
continue;
}
size_t nextCharPos = findNextNonSpace(source, searchPos + 7);
if (nextCharPos == std::string::npos) break;
if (source[nextCharPos] == '{') {
searchPos = nextCharPos + 1;
continue;
}
size_t bracePos = source.find('{', nextCharPos);
size_t semicolonPos = source.find(';', nextCharPos);
if (bracePos != std::string::npos &&
(semicolonPos == std::string::npos || bracePos < semicolonPos)) {
searchPos = bracePos + 1;
continue;
}
if (semicolonPos == std::string::npos) {
searchPos++;
continue;
}
size_t declStart = searchPos;
size_t declLength = semicolonPos - searchPos + 1;
std::string declaration = source.substr(declStart, declLength);
std::string declNoLayout = std::regex_replace(declaration, layoutRegex, "");
std::string afterUniform = declNoLayout.substr(declNoLayout.find("uniform") + 7);
trim(afterUniform);
size_t sep = afterUniform.find_first_of(" \t\r\n[");
std::string typeToken = (sep == std::string::npos ? afterUniform : afterUniform.substr(0, sep));
bool isSamplerOrImage =
typeToken.rfind("sampler", 0) == 0 ||
typeToken.rfind("isampler", 0) == 0 ||
typeToken.rfind("usampler", 0) == 0 ||
typeToken.rfind("image", 0) == 0;
if (isSamplerOrImage) {
searchPos = declStart + declLength;
continue;
}
std::string varName = extractVarNameFromUniformDecl(declaration);
if (allUniformNames.find(varName) == allUniformNames.end()) {
mergedUniforms.push_back(declaration);
allUniformNames.insert(varName);
}
size_t removeStart = declStart;
size_t scanBack = declStart;
while (scanBack > 0 && std::isspace(static_cast<unsigned char>(source[scanBack - 1]))) {
scanBack--;
}
if (scanBack >= 6) {
size_t maybeLayout = source.rfind("layout", scanBack - 6);
if (maybeLayout != std::string::npos) {
size_t parenOpen = source.find('(', maybeLayout + 6);
if (parenOpen != std::string::npos && parenOpen < scanBack) {
size_t parenClose = source.find(')', parenOpen);
if (parenClose != std::string::npos && parenClose < declStart) {
std::string between = source.substr(maybeLayout, declStart - maybeLayout);
const std::regex onlyLayout(R"(layout\s*\([^)]*\)\s*)");
if (std::regex_match(between, onlyLayout)) {
removeStart = maybeLayout;
}
}
}
}
}
removalSpans.emplace_back(removeStart, (declStart + declLength) - removeStart);
searchPos = declStart + declLength;
}
}
if (mergedUniforms.empty()) return;
for (auto& [id, source] : shaderSources) {
auto& removalSpans = removalSpansPerShader[id];
std::sort(removalSpans.rbegin(), removalSpans.rend());
for (auto& span : removalSpans) {
source.erase(span.first, span.second);
}
source = std::regex_replace(
source,
std::regex(R"((\r\n|\n|\r){2,})"),
"$1"
);
}
std::string uboBlock = "\nlayout(std140) uniform MG_DEFAULT_UBO\n{\n";
for (auto& decl : mergedUniforms) {
std::string cleaned = std::regex_replace(decl, layoutRegex, "");
std::string memberDecl = cleaned.substr(cleaned.find("uniform") + 7);
size_t semiPos = memberDecl.rfind(';');
if (semiPos != std::string::npos) {
memberDecl.erase(semiPos);
}
trim(memberDecl);
uboBlock += " " + memberDecl + ";\n";
}
uboBlock += "};\n";
for (auto& [id, source] : shaderSources) {
size_t insertPos = 0, lastDirectivePos = 0;
size_t searchPos = 0;
while ((searchPos = source.find('#', searchPos)) != std::string::npos) {
if (isInComment(commentMasks[id], searchPos)) {
searchPos++;
continue;
}
size_t eol = source.find('\n', searchPos);
if (eol == std::string::npos) break;
std::string line = source.substr(searchPos, eol - searchPos);
if (line.find("#version") != std::string::npos ||
line.find("#extension") != std::string::npos) {
lastDirectivePos = eol + 1;
}
searchPos = eol + 1;
}
insertPos = lastDirectivePos;
source.insert(insertPos, uboBlock);
}
}
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader) {
std::string infoLog;
using namespace glslang;
@@ -108,7 +587,7 @@ namespace MG_Util::Program {
return;
}
ankerl::unordered_set<GLint> used_locations;
MG_Global::unordered_set<GLint> used_locations;
GLint auto_location = 0;
for (auto spirv: allSpirv) {
spvc_parsed_ir ir = nullptr;
+4
View File
@@ -178,6 +178,10 @@ namespace MG_Util::Program {
std::vector<std::vector<unsigned>> CompileMultipleShadersToSPIRV(const ProgramState& state, ProgramObject& prog, std::string& infoLog);
void ReflectSPIRVUniforms(const std::vector<std::vector<unsigned>>& allSpirv, ProgramObject& prog, std::string& infoLog);
std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES);
std::pair<std::string, std::string> GenerateDefaultUBOForGLSL(const std::pair<std::string,
std::string>& glslSources);
void GenerateDefaultUBOForGLSL_Multi(
MG_Global::unordered_map<GLuint, std::string> &shaderSources);
}
#endif //MOBILEGL_GLSLTOOL_H