mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 12:48:32 +09:00
[Feat] (DiligentEngine): Implement most rendering by DiligentEngine.
This commit is contained in:
+21
-21
@@ -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
@@ -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";
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define MOBILEGL_SHADEROBJECT_H
|
||||
|
||||
#define MOBILEGL_GLSTATE_H
|
||||
#define MOBILEGL_DILIGENT_EGL_IMPL_H
|
||||
|
||||
#include "../../../Includes.h"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user