mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
Compare commits
142
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f950fc345 | ||
|
|
83cfacf94b | ||
|
|
dae5827666 | ||
|
|
b119c45c16 | ||
|
|
a59fe679a7 | ||
|
|
82a4be37f2 | ||
|
|
f56453093f | ||
|
|
59e0291f9e | ||
|
|
833679e58a | ||
|
|
f04207905f | ||
|
|
8c98afb1ac | ||
|
|
8c52cd34ed | ||
|
|
fbb1fc1fdb | ||
|
|
c43ae7ed2c | ||
|
|
ad626025d5 | ||
|
|
9db24e6593 | ||
|
|
e3765f1f50 | ||
|
|
532ca5ced5 | ||
|
|
20d02b75e1 | ||
|
|
992ea967a7 | ||
|
|
9e3a5aefad | ||
|
|
bf0c29b384 | ||
|
|
164c2f25d4 | ||
|
|
4cf85c4f2a | ||
|
|
bcaf0e6e32 | ||
|
|
92cd0f3a82 | ||
|
|
067d517527 | ||
|
|
a6bcded3e4 | ||
|
|
79e5eb6a74 | ||
|
|
1078a33147 | ||
|
|
3fb314fc44 | ||
|
|
e1fd5678ec | ||
|
|
8a0d00f94b | ||
|
|
0207ee85b7 | ||
|
|
a5a661261d | ||
|
|
d056acf0af | ||
|
|
229b5f292e | ||
|
|
3e71f83d61 | ||
|
|
fa6ace0955 | ||
|
|
1e6f91809e | ||
|
|
afcc892b32 | ||
|
|
1c0a1fcbcb | ||
|
|
bf8aaaa9c1 | ||
|
|
0359a4e97f | ||
|
|
a18360c931 | ||
|
|
0c031d3e0b | ||
|
|
20a945c6f0 | ||
|
|
433a5ac39d | ||
|
|
b444b7de88 | ||
|
|
94dfdb6905 | ||
|
|
2f1b06d0f9 | ||
|
|
14b1d5a2d1 | ||
|
|
7c3912b9ae | ||
|
|
fa657fbf0b | ||
|
|
6e9f990eed | ||
|
|
a8ae34b3bd | ||
|
|
e959126ac0 | ||
|
|
7e1906da57 | ||
|
|
9075177533 | ||
|
|
e73db426eb | ||
|
|
150bfa15a6 | ||
|
|
cab375917b | ||
|
|
6ac9beaa61 | ||
|
|
a1bdaed2f6 | ||
|
|
ee29a397da | ||
|
|
cbf63dd2b6 | ||
|
|
6d73806d1a | ||
|
|
f6c416bdf1 | ||
|
|
99dd2f5dec | ||
|
|
d3b94dd1c6 | ||
|
|
edd1ad1a80 | ||
|
|
ae5c37b7e4 | ||
|
|
7c3b4e52c3 | ||
|
|
61ae5e2e34 | ||
|
|
6992c541af | ||
|
|
5d6bf42397 | ||
|
|
bc61669dad | ||
|
|
537ec9e2b0 | ||
|
|
4ae9c00c06 | ||
|
|
3583e24bd8 | ||
|
|
832fc56a1b | ||
|
|
e77b56c9ad | ||
|
|
ac4cb2217e | ||
|
|
cc2177e36c | ||
|
|
ac6827fdd8 | ||
|
|
3c30d3aba9 | ||
|
|
e4c77d1432 | ||
|
|
e8ca8161c8 | ||
|
|
a65ae7202e | ||
|
|
09d13579fc | ||
|
|
3d2596f701 | ||
|
|
6bc28c2ae9 | ||
|
|
2cd5edd08b | ||
|
|
58a46c6106 | ||
|
|
db93ddd280 | ||
|
|
6a1b1a5ed9 | ||
|
|
df95930481 | ||
|
|
0c2449dc5e | ||
|
|
8fcf58a732 | ||
|
|
937cab736b | ||
|
|
fa7bb59a82 | ||
|
|
a0016861e8 | ||
|
|
964f483fd5 | ||
|
|
c5ea0a7bf1 | ||
|
|
aad270bcd0 | ||
|
|
994e0a6675 | ||
|
|
836c169100 | ||
|
|
2fb0690804 | ||
|
|
30b7f4d69d | ||
|
|
44e787c56a | ||
|
|
0c4a5f54f2 | ||
|
|
b73c6e749e | ||
|
|
1022a4dfc3 | ||
|
|
ee72f7d07f | ||
|
|
8af2aa262b | ||
|
|
40a458b743 | ||
|
|
e645167c94 | ||
|
|
c183203264 | ||
|
|
4dfbc01479 | ||
|
|
f3497bd2fa | ||
|
|
3c98bc5eca | ||
|
|
9640e167df | ||
|
|
b580605c86 | ||
|
|
292c7eeecf | ||
|
|
848f110658 | ||
|
|
979d31407f | ||
|
|
f5c3514dde | ||
|
|
beecb3dac0 | ||
|
|
ea871e0188 | ||
|
|
ad6b9c1ca7 | ||
|
|
2caade5a36 | ||
|
|
8eb055ca81 | ||
|
|
852b843b4a | ||
|
|
211bf5de39 | ||
|
|
f5a14c20a9 | ||
|
|
c95077f263 | ||
|
|
ca5c1a123b | ||
|
|
6075ae1445 | ||
|
|
2466897531 | ||
|
|
604482d55c | ||
|
|
906323f219 | ||
|
|
13022c79bf |
@@ -3,3 +3,6 @@
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
/build
|
/build
|
||||||
|
.cxx
|
||||||
|
/.vs
|
||||||
|
/out/build
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "3rdparty/DiligentCore"]
|
||||||
|
path = 3rdparty/DiligentCore
|
||||||
|
url = https://github.com/DiligentGraphics/DiligentCore.git
|
||||||
+1
Submodule 3rdparty/DiligentCore added at f36e638805
+13
-3
@@ -56,6 +56,8 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
|||||||
|
|
||||||
MG/MG_GL/Implementations/EGL/GLES/EGL_WRAP.cpp
|
MG/MG_GL/Implementations/EGL/GLES/EGL_WRAP.cpp
|
||||||
|
|
||||||
|
MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp
|
||||||
|
|
||||||
# MG_GL/State
|
# MG_GL/State
|
||||||
MG/MG_GL/State/Core/GLState.cpp
|
MG/MG_GL/State/Core/GLState.cpp
|
||||||
|
|
||||||
@@ -88,7 +90,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
|||||||
|
|
||||||
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ./includes)
|
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ./includes)
|
||||||
|
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
|
||||||
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libglslang.a
|
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libglslang.a
|
||||||
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libspirv-cross-c-shared.so
|
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libspirv-cross-c-shared.so
|
||||||
#${CMAKE_SOURCE_DIR}/library/arm64-v8a/libshaderconv.so
|
#${CMAKE_SOURCE_DIR}/library/arm64-v8a/libshaderconv.so
|
||||||
@@ -110,15 +112,23 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
|
|||||||
vulkan
|
vulkan
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_subdirectory(3rdparty/DiligentCore)
|
||||||
|
|
||||||
target_include_directories(MobileGL PUBLIC
|
target_include_directories(MobileGL PUBLIC
|
||||||
${CMAKE_SOURCE_DIR}/include
|
${CMAKE_SOURCE_DIR}/include
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_link_libraries(MobileGL
|
||||||
|
PRIVATE
|
||||||
|
Diligent-Common
|
||||||
|
Diligent-GraphicsEngineOpenGL-shared
|
||||||
|
Diligent-GraphicsEngineVk-shared
|
||||||
|
)
|
||||||
|
|
||||||
if (PROFILING)
|
if (PROFILING)
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk)
|
include_directories(${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk)
|
||||||
add_library(perfetto STATIC ${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk/perfetto.cc)
|
add_library(perfetto STATIC ${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk/perfetto.cc)
|
||||||
target_link_libraries(MobileGL perfetto ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(MobileGL PRIVATE perfetto ${CMAKE_THREAD_LIBS_INIT})
|
||||||
target_compile_definitions(MobileGL PUBLIC PROFILING=1)
|
target_compile_definitions(MobileGL PUBLIC PROFILING=1)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
+41
-26
@@ -21,20 +21,20 @@
|
|||||||
#define MG_EXPORT extern "C" __attribute__((visibility("default")))
|
#define MG_EXPORT extern "C" __attribute__((visibility("default")))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ankerl {
|
namespace MG_Global {
|
||||||
template <typename K, typename V>
|
template<typename K, typename V>
|
||||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
using unordered_set = ankerl::unordered_dense::set<T>;
|
using unordered_set = ankerl::unordered_dense::set<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MG_Constants {
|
namespace MG_Constants {
|
||||||
namespace Common {
|
namespace Common {
|
||||||
inline constexpr int LOG_LEVEL_DEBUG = 0x0010;
|
inline constexpr int LOG_LEVEL_DEBUG = 0x0010;
|
||||||
inline constexpr int LOG_LEVEL_WARN = 0x0011;
|
inline constexpr int LOG_LEVEL_INFO = 0x0011;
|
||||||
inline constexpr int LOG_LEVEL_ERROR = 0x0012;
|
inline constexpr int LOG_LEVEL_WARN = 0x0012;
|
||||||
inline constexpr int LOG_LEVEL_INFO = 0x0013;
|
inline constexpr int LOG_LEVEL_ERROR = 0x0013;
|
||||||
inline constexpr int LOG_LEVEL_FATAL = 0x0014;
|
inline constexpr int LOG_LEVEL_FATAL = 0x0014;
|
||||||
|
|
||||||
|
|
||||||
@@ -43,10 +43,15 @@ namespace MG_Constants {
|
|||||||
inline constexpr int LOG_TARGET_FILE = 0x02;
|
inline constexpr int LOG_TARGET_FILE = 0x02;
|
||||||
inline constexpr int LOG_TARGET_ANDROID = 0x04; // Android logcat
|
inline constexpr int LOG_TARGET_ANDROID = 0x04; // Android logcat
|
||||||
inline constexpr int LOG_TARGET_ALL = LOG_TARGET_CONSOLE | LOG_TARGET_FILE | LOG_TARGET_ANDROID;
|
inline constexpr int LOG_TARGET_ALL = LOG_TARGET_CONSOLE | LOG_TARGET_FILE | LOG_TARGET_ANDROID;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool Contains(T item, const std::vector<T> vec) {
|
||||||
|
return std::find(vec.begin(), vec.end(), item) != vec.end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Blend {
|
namespace Blend {
|
||||||
static const ankerl::unordered_set<GLenum> VALID_FACTORS = {
|
static const std::vector<GLenum> VALID_FACTORS = {
|
||||||
GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
|
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_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,
|
GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
|
||||||
@@ -55,51 +60,55 @@ namespace MG_Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace Depth {
|
namespace Depth {
|
||||||
static const ankerl::unordered_set<GLenum> VALID_FUNCS = {
|
static const std::vector<GLenum> VALID_FUNCS = {
|
||||||
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
|
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CommonState {
|
namespace CommonState {
|
||||||
static const ankerl::unordered_set<GLenum> VALID_CAPS = {
|
static const std::vector<GLenum> VALID_CAPS = {
|
||||||
GL_BLEND, GL_DEPTH_TEST, GL_STENCIL_TEST, GL_SCISSOR_TEST, GL_CULL_FACE,
|
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
|
GL_POLYGON_OFFSET_FILL, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Framebuffer {
|
namespace Framebuffer {
|
||||||
static const ankerl::unordered_set<GLenum> VALID_ATTACHMENTS = {
|
static const std::vector<GLenum> VALID_ATTACHMENTS = {
|
||||||
GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
|
GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
|
||||||
GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT
|
GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
|
|
||||||
static const ankerl::unordered_set<GLenum> VALID_TARGETS = {
|
static const std::vector<GLenum> VALID_TARGETS = {
|
||||||
GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER
|
GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
|
|
||||||
static const ankerl::unordered_set<GLenum> VALID_ACCESS = {
|
static const std::vector<GLenum> VALID_ACCESS = {
|
||||||
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
|
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Buffer {
|
namespace Buffer {
|
||||||
static const ankerl::unordered_set<GLenum> VALID_PARAM_NAMES = {
|
static const std::vector<GLenum> VALID_PARAM_NAMES = {
|
||||||
GL_BUFFER_ACCESS, GL_BUFFER_MAPPED, GL_BUFFER_SIZE, GL_BUFFER_USAGE
|
GL_BUFFER_ACCESS, GL_BUFFER_MAPPED, GL_BUFFER_SIZE, GL_BUFFER_USAGE
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
|
|
||||||
static const ankerl::unordered_set<GLenum> VALID_TARGETS = {
|
static const std::vector<GLenum> VALID_TARGETS = {
|
||||||
GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
|
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_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER,
|
||||||
GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER
|
GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
|
|
||||||
static const ankerl::unordered_set<GLenum> VALID_ACCESS = {
|
static const std::vector<GLenum> VALID_ACCESS = {
|
||||||
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
|
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace VertexArray {
|
||||||
|
constexpr uint32_t MAX_VERTEX_ATTRIBS = 32;
|
||||||
|
}
|
||||||
|
|
||||||
namespace PixelStore {
|
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_SWAP_BYTES, GL_FALSE},
|
||||||
{GL_PACK_LSB_FIRST, GL_FALSE},
|
{GL_PACK_LSB_FIRST, GL_FALSE},
|
||||||
{GL_PACK_ROW_LENGTH, 0},
|
{GL_PACK_ROW_LENGTH, 0},
|
||||||
@@ -118,7 +127,7 @@ namespace MG_Constants {
|
|||||||
{GL_UNPACK_ALIGNMENT, 4}
|
{GL_UNPACK_ALIGNMENT, 4}
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
|
|
||||||
static const ankerl::unordered_set<GLenum> VALID_PARAM_NAMES = {
|
static const std::vector<GLenum> VALID_PARAM_NAMES = {
|
||||||
GL_PACK_SWAP_BYTES, GL_PACK_LSB_FIRST, GL_PACK_ROW_LENGTH, GL_PACK_IMAGE_HEIGHT,
|
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_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,
|
GL_UNPACK_SWAP_BYTES, GL_UNPACK_LSB_FIRST, GL_UNPACK_ROW_LENGTH,
|
||||||
@@ -132,18 +141,18 @@ namespace MG_Constants {
|
|||||||
inline const GLuint MAX_TEXTURE_UNITS = 80;
|
inline const GLuint MAX_TEXTURE_UNITS = 80;
|
||||||
const GLsizei MAX_TEXTURE_SIZE = 32768;
|
const GLsizei MAX_TEXTURE_SIZE = 32768;
|
||||||
const GLsizei MAX_ARRAY_LAYERS = 256;
|
const GLsizei MAX_ARRAY_LAYERS = 256;
|
||||||
inline const ankerl::unordered_set<GLenum> VALID_TARGETS = {
|
inline const std::vector<GLenum> VALID_TARGETS = {
|
||||||
GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D, GL_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_1D_ARRAY,
|
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_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_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
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_PROXY_TEXTURE_CUBE_MAP
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
|
|
||||||
inline const ankerl::unordered_set<GLenum> VALID_FORMATS = {
|
inline const std::vector<GLenum> VALID_FORMATS = {
|
||||||
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL
|
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
|
|
||||||
inline const ankerl::unordered_set<GLenum> VALID_INTERNAL_FORMATS = {
|
inline const std::vector<GLenum> VALID_INTERNAL_FORMATS = {
|
||||||
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL,
|
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_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,
|
GL_RGBA16UI, GL_RGBA8, GL_RGBA8UI, GL_SRGB8_ALPHA8, GL_RGB10_A2, GL_RGB10_A2UI,
|
||||||
@@ -158,7 +167,7 @@ namespace MG_Constants {
|
|||||||
GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8
|
GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8
|
||||||
}; // OpenGL 3
|
}; // OpenGL 3
|
||||||
|
|
||||||
inline const ankerl::unordered_set<GLenum> VALID_TYPES = {
|
inline const std::vector<GLenum> VALID_TYPES = {
|
||||||
GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT,
|
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_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,
|
GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
|
||||||
@@ -166,14 +175,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
|
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
|
}; // OpenGL 3
|
||||||
|
|
||||||
inline const ankerl::unordered_set<GLenum> VALID_TEXTURE_PARAM_NAMES = {
|
inline const std::vector<GLenum> VALID_TEXTURE_PARAM_NAMES = {
|
||||||
GL_TEXTURE_BASE_LEVEL, GL_TEXTURE_COMPARE_FUNC, GL_TEXTURE_COMPARE_MODE, GL_TEXTURE_MIN_FILTER,
|
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_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_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
|
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
|
}; // OpenGL 3
|
||||||
|
|
||||||
inline const ankerl::unordered_set<GLenum> VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES = {
|
inline const std::vector<GLenum> VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES = {
|
||||||
GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH, GL_TEXTURE_INTERNAL_FORMAT,
|
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_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
|
GL_TEXTURE_DEPTH_SIZE, GL_TEXTURE_COMPRESSED, GL_TEXTURE_COMPRESSED_IMAGE_SIZE
|
||||||
@@ -181,9 +190,15 @@ namespace MG_Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace Backend {
|
namespace Backend {
|
||||||
#define BACKEND_VULKAN 0x0015
|
#define BACKEND_VULKAN 0x0015
|
||||||
#define BACKEND_METAL 0x0016
|
#define BACKEND_METAL 0x0016
|
||||||
#define BACKEND_GLES 0x0017
|
#define BACKEND_GLES 0x0017
|
||||||
|
#define BACKEND_DILIGENT 0x0018
|
||||||
|
|
||||||
|
inline const int BACKEND_DILIGENT_VULKAN = 0x0020;
|
||||||
|
inline const int BACKEND_DILIGENT_METAL = 0x0021; // not ready currently
|
||||||
|
inline const int BACKEND_DILIGENT_OPENGL = 0x0022;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char* RenderName = "MobileGL";
|
inline const char* RenderName = "MobileGL";
|
||||||
|
|||||||
+47
-78
@@ -1,85 +1,9 @@
|
|||||||
//
|
//
|
||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "Constants.h"
|
#define BACKEND_TYPE BACKEND_DILIGENT
|
||||||
#define BACKEND_TYPE BACKEND_GLES
|
|
||||||
#include "Global.h"
|
|
||||||
#ifndef MOBILEGL_GLES_LOADER_H
|
|
||||||
#include "MG_GL/BackendLoader/GLES/Loader.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GL_FRAMEBUFFER_H
|
|
||||||
#include "MG_GL/Implementations/GL/Framebuffer/GL_Framebuffer.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GL_GETTER_H
|
|
||||||
#include "MG_GL/Implementations/GL/Getter/GL_Getter.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_BACKENDINFO_H
|
|
||||||
#include "MG_GL/Implementations/GL/Getter/BackendInfo.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GL_BUFFER_H
|
|
||||||
#include "MG_GL/Implementations/GL/Buffer/GL_Buffer.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GL_DRAWING_H
|
|
||||||
#include "MG_GL/Implementations/GL/Drawing/GL_Drawing.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GL_PROGRAM_H
|
|
||||||
#include "MG_GL/Implementations/GL/Program/GL_Program.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GL_TEXTURE_H
|
|
||||||
#include "MG_GL/Implementations/GL/Texture/GL_Texture.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GL_VERTEXARRAY_H
|
|
||||||
#include "MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GLSTATE_H
|
|
||||||
#include "MG_GL/State/Core/GLState.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_COMMONSTATE_H
|
|
||||||
#include "MG_GL/State/Common/CommonState.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_TEXTURESTATE_H
|
|
||||||
#include "MG_GL/State/Texture/TextureState.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_VERTEXARRAYSTATE_H
|
|
||||||
#include "MG_GL/State/VertexArray/VertexArrayState.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_BUFFERSTATE_H
|
|
||||||
#include "MG_GL/State/Buffer/BufferState.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_SHADEROBJECT_H
|
|
||||||
#include "MG_GL/State/Program/ShaderObject.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_PROGRAMSTATE_H
|
|
||||||
#include "MG_GL/State/Program/ProgramState.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_FRAMEBUFFERSTATE_H
|
|
||||||
#include "MG_GL/State/Framebuffer/FramebufferState.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_LOOKUP_H
|
|
||||||
#include "MG_GL/Implementations/GLX/LookUp/LookUp.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_DEBUG_H
|
|
||||||
#include "MG_UTIL/Debug/Debug.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GLSLTOOL_H
|
|
||||||
#include "MG_UTIL/Program/GLSLTool.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
|
||||||
#include "MG_UTIL/Program/DebugTool.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_GL_COMMON_H
|
|
||||||
#include "MG_GL/Implementations/GL/Common/GL_Common.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_EGL_VK_EMU_H
|
|
||||||
#include "MG_GL/Implementations/EGL/VK/EGL_EMU.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_EGL_GLES_EGL_WRAP_H
|
|
||||||
#include "MG_GL/Implementations/EGL/GLES/EGL_WRAP.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MOBILEGL_TESTDRAWING_H
|
|
||||||
#include "MG_RHI/GLES/Test/TestDrawing.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -90,6 +14,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cctype>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@@ -101,6 +26,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <format>
|
#include <format>
|
||||||
|
#include <memory>
|
||||||
#include <glslang/Public/ShaderLang.h>
|
#include <glslang/Public/ShaderLang.h>
|
||||||
#include <glslang/Include/Types.h>
|
#include <glslang/Include/Types.h>
|
||||||
#include <glslang/Public/ShaderLang.h>
|
#include <glslang/Public/ShaderLang.h>
|
||||||
@@ -112,6 +38,7 @@
|
|||||||
#include <GLES3/gl32.h>
|
#include <GLES3/gl32.h>
|
||||||
|
|
||||||
#include "MG_Include/UncertainBool.hpp"
|
#include "MG_Include/UncertainBool.hpp"
|
||||||
|
#include "MG_Include/IndexGenerator.hpp"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
@@ -138,3 +65,45 @@
|
|||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
|
|
||||||
|
#if BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
#include "EngineFactory.h"
|
||||||
|
#include "EngineFactoryOpenGL.h"
|
||||||
|
#include "EngineFactoryVk.h"
|
||||||
|
#include "RefCntAutoPtr.hpp"
|
||||||
|
|
||||||
|
#include "PipelineState.h"
|
||||||
|
#include "GraphicsTypes.h"
|
||||||
|
#include "DeviceContext.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "Constants.h"
|
||||||
|
#include "Global.h"
|
||||||
|
#include "MG_GL/Implementations/EGL/Diligent/DiligentConfig.h"
|
||||||
|
#include "MG_GL/BackendLoader/GLES/Loader.h"
|
||||||
|
#include "MG_GL/Implementations/GL/Framebuffer/GL_Framebuffer.h"
|
||||||
|
#include "MG_GL/Implementations/GL/Getter/GL_Getter.h"
|
||||||
|
#include "MG_GL/Implementations/GL/Getter/BackendInfo.h"
|
||||||
|
#include "MG_GL/Implementations/GL/Buffer/GL_Buffer.h"
|
||||||
|
#include "MG_GL/Implementations/GL/Drawing/GL_Drawing.h"
|
||||||
|
#include "MG_GL/Implementations/GL/Program/GL_Program.h"
|
||||||
|
#include "MG_GL/Implementations/GL/Texture/GL_Texture.h"
|
||||||
|
#include "MG_GL/Implementations/GL/VertexArray/GL_VertexArray.h"
|
||||||
|
#include "MG_GL/State/Common/CommonState.h"
|
||||||
|
#include "MG_GL/State/Texture/TextureState.h"
|
||||||
|
#include "MG_GL/State/VertexArray/VertexArrayState.h"
|
||||||
|
#include "MG_GL/State/Buffer/BufferState.h"
|
||||||
|
#include "MG_GL/State/Program/ShaderObject.h"
|
||||||
|
#include "MG_GL/State/Program/ProgramState.h"
|
||||||
|
#include "MG_GL/State/Framebuffer/FramebufferState.h"
|
||||||
|
#include "MG_GL/State/Core/GLState.h"
|
||||||
|
#include "MG_GL/Implementations/EGL/Diligent/EGL_impl.h"
|
||||||
|
#include "MG_GL/Implementations/GLX/LookUp/LookUp.h"
|
||||||
|
#include "MG_UTIL/Debug/Debug.h"
|
||||||
|
#include "MG_UTIL/Program/GLSLTool.h"
|
||||||
|
#include "MG_UTIL/Program/DebugTool.h"
|
||||||
|
#include "MG_GL/Implementations/GL/Common/GL_Common.h"
|
||||||
|
#include "MG_GL/Implementations/EGL/VK/EGL_EMU.h"
|
||||||
|
#include "MG_GL/Implementations/EGL/GLES/EGL_WRAP.h"
|
||||||
|
#include "MG_RHI/GLES/Test/TestDrawing.h"
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ void MG_Initialize() {
|
|||||||
MG_Util::Debug::LogInit();
|
MG_Util::Debug::LogInit();
|
||||||
MG_Util::Debug::LogI("MobileGL Initializing...");
|
MG_Util::Debug::LogI("MobileGL Initializing...");
|
||||||
MG_State::Init();
|
MG_State::Init();
|
||||||
|
#if BACKEND_TYPE == BACKEND_GLES
|
||||||
MG_GL::BackendLoader::Init();
|
MG_GL::BackendLoader::Init();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MG_Destroy() {
|
void MG_Destroy() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/4/26.
|
// Created by BZLZHH on 2025/4/26.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Loader.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
#if BACKEND_TYPE == BACKEND_GLES
|
#if BACKEND_TYPE == BACKEND_GLES
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_GLES_LOADER_H
|
#ifndef MOBILEGL_GLES_LOADER_H
|
||||||
#define MOBILEGL_GLES_LOADER_H
|
#define MOBILEGL_GLES_LOADER_H
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
#if BACKEND_TYPE == BACKEND_GLES
|
#if BACKEND_TYPE == BACKEND_GLES
|
||||||
|
|
||||||
#define APIENTRY_GLES
|
#define APIENTRY_GLES
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
//
|
||||||
|
// Created by BZLZHH on 2025/5/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace MG_Diligent {
|
||||||
|
inline const int DILIGENT_BACKEND_TYPE = MG_Constants::Backend::BACKEND_DILIGENT_VULKAN;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,264 @@
|
|||||||
|
//
|
||||||
|
// Created by Swung 0x48 on 2025-05-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MOBILEGL_DILIGENT_EGL_IMPL_H
|
||||||
|
#define MOBILEGL_DILIGENT_EGL_IMPL_H
|
||||||
|
|
||||||
|
#if BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Uniform names, in the order of their index in uniform buffer
|
||||||
|
std::vector<std::string> uniformBufferNames;
|
||||||
|
|
||||||
|
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;
|
||||||
|
extern Diligent::IBuffer* g_TriangleFanIndexBuffer;
|
||||||
|
|
||||||
|
inline Diligent::PRIMITIVE_TOPOLOGY GLPrimitiveTopologyToDiligent(GLenum Topology)
|
||||||
|
{
|
||||||
|
switch (Topology)
|
||||||
|
{
|
||||||
|
case GL_TRIANGLE_STRIP:
|
||||||
|
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||||
|
case GL_TRIANGLES:
|
||||||
|
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
case GL_TRIANGLE_FAN:
|
||||||
|
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
// TODO: Handle other topologies
|
||||||
|
default:
|
||||||
|
return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
GLenum primitiveTopology);
|
||||||
|
|
||||||
|
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,
|
||||||
|
GLenum primitiveTopology);
|
||||||
|
|
||||||
|
void ConfigurePSO(
|
||||||
|
Diligent::GraphicsPipelineStateCreateInfo &PSOCreateInfo,
|
||||||
|
GLProgramInfo &programInfo,
|
||||||
|
CommonState &commonState,
|
||||||
|
VertexArrayState &vaState,
|
||||||
|
GLFramebufferInfo& fbInfo,
|
||||||
|
GLenum primitiveTopology);
|
||||||
|
|
||||||
|
void ConfigureResourceLayout(
|
||||||
|
Diligent::GraphicsPipelineStateCreateInfo& PSOCreateInfo,
|
||||||
|
GLProgramInfo& programInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern PipelineStateManager g_PSOManager;
|
||||||
|
|
||||||
|
void BuildInputLayout(GLuint program, VertexArrayState& vaState,
|
||||||
|
std::vector<Diligent::LayoutElement>& inputLayout);
|
||||||
|
|
||||||
|
extern bool initialized;
|
||||||
|
// extern bool IsInRenderPass;
|
||||||
|
extern GLuint g_NextResourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext shareCtx, const EGLint* attrib_list);
|
||||||
|
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor);
|
||||||
|
EGLDisplay eglGetDisplay(NativeDisplayType display);
|
||||||
|
EGLint eglGetError();
|
||||||
|
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||||
|
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
|
||||||
|
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
|
||||||
|
EGLBoolean eglTerminate(EGLDisplay dpy);
|
||||||
|
EGLBoolean eglReleaseThread(void);
|
||||||
|
EGLContext eglGetCurrentContext(void);
|
||||||
|
EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||||
|
EGLBoolean eglBindAPI(EGLenum api);
|
||||||
|
EGLSurface eglGetCurrentSurface(EGLint readdraw);
|
||||||
|
EGLBoolean eglQuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint *value);
|
||||||
|
EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval);
|
||||||
|
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
|
||||||
|
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_EXPORT __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MOBILEGL_DILIGENT_EGL_IMPL_H
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/4/26.
|
// Created by BZLZHH on 2025/4/26.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "EGL_WRAP.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
#if BACKEND_TYPE == BACKEND_GLES
|
#if BACKEND_TYPE == BACKEND_GLES
|
||||||
|
|
||||||
@@ -48,7 +48,12 @@ MG_EXPORT EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint
|
|||||||
|
|
||||||
MG_EXPORT EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) {
|
MG_EXPORT EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) {
|
||||||
LOAD_EGL(eglCreateWindowSurface)
|
LOAD_EGL(eglCreateWindowSurface)
|
||||||
return egl_eglCreateWindowSurface(dpy, config, win, attrib_list);
|
EGLSurface surface = egl_eglCreateWindowSurface(dpy, config, win, attrib_list);
|
||||||
|
|
||||||
|
// auto* pFactoryOpenGL = GetEngineFactoryOpenGL();
|
||||||
|
|
||||||
|
|
||||||
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
MG_EXPORT EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) {
|
MG_EXPORT EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) {
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
#ifndef MOBILEGL_EGL_GLES_EGL_WRAP_H
|
#ifndef MOBILEGL_EGL_GLES_EGL_WRAP_H
|
||||||
#define MOBILEGL_EGL_GLES_EGL_WRAP_H
|
#define MOBILEGL_EGL_GLES_EGL_WRAP_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
#if BACKEND_TYPE == BACKEND_GLES
|
#if BACKEND_TYPE == BACKEND_GLES
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //MOBILEGL_EGL_GLES_EGL_WRAP_H
|
#endif //MOBILEGL_EGL_GLES_EGL_WRAP_H
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/3/30.
|
// Created by BZLZHH on 2025/3/30.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "EGL_EMU.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
#if BACKEND_TYPE == BACKEND_VULKAN
|
#if BACKEND_TYPE == BACKEND_VULKAN
|
||||||
|
|
||||||
@@ -11,9 +11,9 @@ std::atomic<uintptr_t> g_nextSurfaceId{1};
|
|||||||
EGLenum g_currentAPI = EGL_OPENGL_ES_API;
|
EGLenum g_currentAPI = EGL_OPENGL_ES_API;
|
||||||
|
|
||||||
std::mutex g_globalMutex;
|
std::mutex g_globalMutex;
|
||||||
ankerl::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
|
MG_Global::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
|
||||||
ankerl::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
|
MG_Global::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
|
||||||
ankerl::unordered_map<EGLContext, VulkanContext> g_contexts;
|
MG_Global::unordered_map<EGLContext, VulkanContext> g_contexts;
|
||||||
EGLint g_lastError = EGL_SUCCESS;
|
EGLint g_lastError = EGL_SUCCESS;
|
||||||
|
|
||||||
thread_local EGLContext tls_currentContext = EGL_NO_CONTEXT;
|
thread_local EGLContext tls_currentContext = EGL_NO_CONTEXT;
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_EGL_VK_EMU_H
|
#ifndef MOBILEGL_EGL_VK_EMU_H
|
||||||
#define MOBILEGL_EGL_VK_EMU_H
|
#define MOBILEGL_EGL_VK_EMU_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
#if BACKEND_TYPE == BACKEND_VULKAN
|
#if BACKEND_TYPE == BACKEND_VULKAN
|
||||||
|
|
||||||
struct EGLInternalConfig {
|
struct EGLInternalConfig {
|
||||||
@@ -69,9 +67,9 @@ extern std::atomic<uintptr_t> g_nextSurfaceId;
|
|||||||
extern EGLenum g_currentAPI;
|
extern EGLenum g_currentAPI;
|
||||||
|
|
||||||
extern std::mutex g_globalMutex;
|
extern std::mutex g_globalMutex;
|
||||||
extern ankerl::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
|
extern MG_Global::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
|
||||||
extern ankerl::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
|
extern MG_Global::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
|
||||||
extern ankerl::unordered_map<EGLContext, VulkanContext> g_contexts;
|
extern MG_Global::unordered_map<EGLContext, VulkanContext> g_contexts;
|
||||||
extern EGLint g_lastError;
|
extern EGLint g_lastError;
|
||||||
|
|
||||||
extern thread_local EGLContext tls_currentContext;
|
extern thread_local EGLContext tls_currentContext;
|
||||||
|
|||||||
@@ -2,9 +2,18 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GL_Buffer.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
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,
|
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
|
||||||
GLbitfield access) {
|
GLbitfield access) {
|
||||||
MG_Util::Debug::LogD("glMapBufferRange, target: %s, offset: %lld, length: %lld, access: 0x%X",
|
MG_Util::Debug::LogD("glMapBufferRange, target: %s, offset: %lld, length: %lld, access: 0x%X",
|
||||||
@@ -31,6 +40,38 @@ namespace MG_GL::GL {
|
|||||||
static_cast<long long>(length));
|
static_cast<long long>(length));
|
||||||
GLenum result = MG_State::SyncBufferMemory(target, offset, length);
|
GLenum result = MG_State::SyncBufferMemory(target, offset, length);
|
||||||
if (result == GL_NO_ERROR) {
|
if (result == GL_NO_ERROR) {
|
||||||
|
GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target);
|
||||||
|
if (buffer == 0) return;
|
||||||
|
|
||||||
|
auto& bufferObj = *MG_State_T::bufferState->GetBufferObject(buffer);
|
||||||
|
if (!bufferObj.isMapped) return;
|
||||||
|
|
||||||
|
size_t start = static_cast<size_t>(offset);
|
||||||
|
size_t end = start + static_cast<size_t>(length);
|
||||||
|
|
||||||
|
auto it = MG_Diligent::g_BufferMap.find(buffer);
|
||||||
|
if (it == MG_Diligent::g_BufferMap.end())
|
||||||
|
return;
|
||||||
|
Diligent::IBuffer* pBuffer = it->second;
|
||||||
|
if (pBuffer && bufferObj.data.size() >= end) {
|
||||||
|
const auto& Desc = pBuffer->GetDesc();
|
||||||
|
if (Desc.Usage == Diligent::USAGE_STAGING || Desc.Usage == Diligent::USAGE_DYNAMIC || Desc.Usage == Diligent::USAGE_UNIFIED) {
|
||||||
|
void * data;
|
||||||
|
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE,
|
||||||
|
Diligent::MAP_FLAG_DISCARD, 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);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For USAGE_DEFAULT or USAGE_IMMUTABLE, use UpdateBuffer
|
||||||
|
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, static_cast<Diligent::Uint64>(offset), static_cast<Diligent::Uint64>(length), bufferObj.data.data() + offset, Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
@@ -50,6 +91,25 @@ namespace MG_GL::GL {
|
|||||||
static_cast<long long>(size));
|
static_cast<long long>(size));
|
||||||
GLenum result = MG_State::CopyBufferRange(readTarget, writeTarget, readOffset, writeOffset, size);
|
GLenum result = MG_State::CopyBufferRange(readTarget, writeTarget, readOffset, writeOffset, size);
|
||||||
if (result == GL_NO_ERROR) {
|
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;
|
||||||
|
auto itsrc = MG_Diligent::g_BufferMap.find(srcBuffer);
|
||||||
|
auto itdst = MG_Diligent::g_BufferMap.find(dstBuffer);
|
||||||
|
if (itsrc == MG_Diligent::g_BufferMap.end() || itdst == MG_Diligent::g_BufferMap.end()) return;
|
||||||
|
|
||||||
|
Diligent::IBuffer* pSrcBuffer = itsrc->second;
|
||||||
|
Diligent::IBuffer* pDstBuffer = itdst->second;
|
||||||
|
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
@@ -78,6 +138,31 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::LogE("glUnmapBuffer failed: %s", MG_Util::Debug::GLEnumToString(err));
|
MG_Util::Debug::LogE("glUnmapBuffer failed: %s", MG_Util::Debug::GLEnumToString(err));
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint buffer = MG_State_T::bufferState->currentBindings_[target];
|
||||||
|
auto& bufferObj = *MG_State_T::bufferState->GetBufferObject(buffer);
|
||||||
|
|
||||||
|
auto it = MG_Diligent::g_BufferMap.find(buffer);
|
||||||
|
if (it == MG_Diligent::g_BufferMap.end())
|
||||||
|
return GL_FALSE;
|
||||||
|
Diligent::IBuffer* pBuffer = it->second;
|
||||||
|
if (pBuffer) {
|
||||||
|
const auto& Desc = pBuffer->GetDesc();
|
||||||
|
if (Desc.Usage == Diligent::USAGE_STAGING || Desc.Usage == Diligent::USAGE_DYNAMIC || Desc.Usage == Diligent::USAGE_UNIFIED) {
|
||||||
|
void * data;
|
||||||
|
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE,
|
||||||
|
Diligent::MAP_FLAG_DISCARD, data);
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
memcpy(data, bufferObj.data.data(), bufferObj.data.size());
|
||||||
|
MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For USAGE_DEFAULT or USAGE_IMMUTABLE, use UpdateBuffer
|
||||||
|
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, 0, bufferObj.data.size(), bufferObj.data.data(), Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MG_Util::Debug::LogD("glUnmapBuffer succeeded");
|
MG_Util::Debug::LogD("glUnmapBuffer succeeded");
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
@@ -112,8 +197,69 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::LogD("glBufferData, target: %s, size: %zd, data: %p, usage: %s",
|
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));
|
MG_Util::Debug::GLEnumToString(target), size, data, MG_Util::Debug::GLEnumToString(usage));
|
||||||
GLenum result = MG_State::CommitBufferStorage(target, size, data, 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;
|
||||||
|
auto& bufferObj = *MG_State_T::bufferState->GetBufferObject(buffer);
|
||||||
|
if (bufferObj.isDynamic) return; // Dynamic buffer should be created by glDraw*
|
||||||
|
if (size <= 0) return; // ignore 0-sized reallocation
|
||||||
|
|
||||||
|
bufferObj.dirty = false;
|
||||||
|
|
||||||
|
auto it = MG_Diligent::g_BufferMap.find(buffer);
|
||||||
|
if (it == MG_Diligent::g_BufferMap.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Diligent::IBuffer*& pBuffer = it->second;
|
||||||
|
|
||||||
|
Diligent::BufferDesc BuffDesc;
|
||||||
|
std::string name;
|
||||||
|
BuffDesc.Size = static_cast<Diligent::Uint64>(size);
|
||||||
|
|
||||||
|
switch (target) {
|
||||||
|
case GL_ARRAY_BUFFER:
|
||||||
|
// BuffDesc.BindFlags = Diligent::BIND_VERTEX_BUFFER;
|
||||||
|
name += std::format("VBO {}", buffer);
|
||||||
|
break;
|
||||||
|
case GL_ELEMENT_ARRAY_BUFFER:
|
||||||
|
// BuffDesc.BindFlags = Diligent::BIND_INDEX_BUFFER;
|
||||||
|
name += std::format("IBO {}", buffer);
|
||||||
|
break;
|
||||||
|
case GL_UNIFORM_BUFFER:
|
||||||
|
// BuffDesc.BindFlags = Diligent::BIND_UNIFORM_BUFFER;
|
||||||
|
name += std::format("UBO {}", buffer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BuffDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE;
|
||||||
|
name += std::format("SRV {}", buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuffDesc.BindFlags |= Diligent::BIND_VERTEX_BUFFER |
|
||||||
|
Diligent::BIND_INDEX_BUFFER |
|
||||||
|
Diligent::BIND_UNIFORM_BUFFER;
|
||||||
|
BuffDesc.Name = name.c_str();
|
||||||
|
BuffDesc.Usage = Diligent::USAGE_DEFAULT;
|
||||||
|
|
||||||
|
if (!pBuffer || (pBuffer && pBuffer->GetDesc().Size != bufferObj.data.size()) ) {
|
||||||
|
if (pBuffer) {
|
||||||
|
pBuffer->Release();
|
||||||
|
pBuffer = nullptr;
|
||||||
|
}
|
||||||
|
Diligent::BufferData BuffData;
|
||||||
|
// Initial data must not be null for immutable buffers
|
||||||
|
BuffData.pData = BuffDesc.Usage != Diligent::USAGE_IMMUTABLE ? nullptr : bufferObj.data.data();
|
||||||
|
BuffData.DataSize = static_cast<Diligent::Uint64>(size);
|
||||||
|
MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, &BuffData, &pBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data != nullptr && BuffDesc.Usage != Diligent::USAGE_IMMUTABLE) {
|
||||||
|
MG_Diligent::g_pContext->UpdateBuffer(pBuffer, 0,
|
||||||
|
static_cast<Diligent::Uint64>(size), data,
|
||||||
|
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -142,6 +288,7 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::LogD("Generated buffer names:");
|
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_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]);
|
||||||
|
MG_Diligent::g_BufferMap[buffers[i]] = nullptr;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -174,13 +321,57 @@ namespace MG_GL::GL {
|
|||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(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;
|
||||||
|
|
||||||
|
auto& bufferObj = *MG_State_T::bufferState->GetBufferObject(buffer);
|
||||||
|
if (bufferObj.isDynamic) return; // Dynamic buffer should be created by glDraw*
|
||||||
|
|
||||||
|
auto it = MG_Diligent::g_BufferMap.find(buffer);
|
||||||
|
if (it == MG_Diligent::g_BufferMap.end())
|
||||||
|
return;
|
||||||
|
Diligent::IBuffer* pBuffer = it->second;
|
||||||
|
if (pBuffer) {
|
||||||
|
const auto& Desc = pBuffer->GetDesc();
|
||||||
|
if (Desc.Usage == Diligent::USAGE_STAGING || Desc.Usage == Diligent::USAGE_DYNAMIC || Desc.Usage == Diligent::USAGE_UNIFIED) {
|
||||||
|
void* pMappedData = nullptr;
|
||||||
|
MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE, Diligent::MAP_FLAG_DISCARD, pMappedData);
|
||||||
|
if (pMappedData)
|
||||||
|
{
|
||||||
|
memcpy(static_cast<Diligent::Uint8*>(pMappedData) + offset, data, size);
|
||||||
|
MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE);
|
||||||
|
} else {
|
||||||
|
MG_Util::Debug::LogE("Failed to map buffer for BufferSubData");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For USAGE_DEFAULT or USAGE_IMMUTABLE, use UpdateBuffer
|
||||||
|
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) {
|
void DeleteBuffers(GLsizei n, const GLuint *buffers) {
|
||||||
MG_Util::Debug::LogD("glDeleteBuffers, n: %d, buffers: %p", n, buffers);
|
MG_Util::Debug::LogD("glDeleteBuffers, n: %d, buffers: %p", n, buffers);
|
||||||
|
|
||||||
GLenum result = MG_State::DeleteBuffers(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) {
|
||||||
|
auto it = MG_Diligent::g_BufferMap.find(buffer);
|
||||||
|
if (it != MG_Diligent::g_BufferMap.end()) {
|
||||||
|
if (it->second) {
|
||||||
|
it->second->Release();
|
||||||
|
}
|
||||||
|
MG_Diligent::g_BufferMap.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_GL_BUFFER_H
|
#ifndef MOBILEGL_GL_BUFFER_H
|
||||||
#define MOBILEGL_GL_BUFFER_H
|
#define MOBILEGL_GL_BUFFER_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
||||||
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
|
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
|
||||||
|
|||||||
@@ -2,23 +2,100 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GL_Common.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
|
void CreateRenderPassAndFramebuffer(GLuint framebuffer,
|
||||||
|
const FramebufferObject& fbo,
|
||||||
|
MG_Diligent::GLFramebufferInfo& fbInfo);
|
||||||
|
|
||||||
void Clear(GLbitfield mask) {
|
void Clear(GLbitfield mask) {
|
||||||
MG_Util::Debug::LogD("glClear, mask: 0x%X", mask);
|
GLuint drawFramebuffer = MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER];
|
||||||
GLenum result = MG_State::glClear(mask);
|
if (drawFramebuffer == 0) {
|
||||||
if (result == GL_NO_ERROR) {
|
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;
|
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;
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("Setting render targets: %zu color attachments", fbInfo.ColorRTVs.size());
|
||||||
|
MG_Diligent::g_pContext->SetRenderTargets(
|
||||||
|
static_cast<Diligent::Uint32>(fbInfo.ColorRTVs.size()),
|
||||||
|
fbInfo.ColorRTVs.data(),
|
||||||
|
fbInfo.pDepthStencilRTV,
|
||||||
|
::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
|
||||||
|
);
|
||||||
|
|
||||||
|
// if (MG_Diligent::IsInRenderPass) {
|
||||||
|
// MG_Util::Debug::LogD("Ending render pass before clear operation");
|
||||||
|
// MG_Diligent::g_pContext->EndRenderPass();
|
||||||
|
// MG_Diligent::IsInRenderPass = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// MG_Util::Debug::LogD("Beginning render pass for clear operation");
|
||||||
|
|
||||||
|
// if (!fbInfo.pRenderPass) {
|
||||||
|
// MG_GL::GL::CreateRenderPassAndFramebuffer(drawFramebuffer,
|
||||||
|
// *MG_State_T::framebufferState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER), fbInfo);
|
||||||
|
// }
|
||||||
|
// Diligent::BeginRenderPassAttribs beginAttribs;
|
||||||
|
// beginAttribs.pRenderPass = fbInfo.pRenderPass;
|
||||||
|
// beginAttribs.pFramebuffer = fbInfo.pFramebuffer;
|
||||||
|
// beginAttribs.StateTransitionMode = Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
|
||||||
|
// beginAttribs.ClearValueCount = 0;
|
||||||
|
// beginAttribs.pClearValues = nullptr;
|
||||||
|
|
||||||
|
// MG_Diligent::g_pContext->BeginRenderPass(beginAttribs);
|
||||||
|
// MG_Diligent::IsInRenderPass = true;
|
||||||
|
|
||||||
|
if (mask & GL_COLOR_BUFFER_BIT) {
|
||||||
|
for (size_t i = 0; i < fbInfo.ColorRTVs.size(); ++i) {
|
||||||
|
if (fbInfo.ColorRTVs[i]) {
|
||||||
|
MG_Util::Debug::LogD("Clearing color attachment %zu", 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_Util::Debug::LogD("Clearing depth/stencil (flags: %u)", clearFlags);
|
||||||
|
MG_Diligent::g_pContext->ClearDepthStencil(
|
||||||
|
fbInfo.pDepthStencilRTV,
|
||||||
|
static_cast<Diligent::CLEAR_DEPTH_STENCIL_FLAGS>(clearFlags),
|
||||||
|
commonState.clearDepth,
|
||||||
|
0,
|
||||||
|
Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MG_Util::Debug::LogD("Ending render pass after clear operation");
|
||||||
|
// MG_Diligent::g_pContext->EndRenderPass();
|
||||||
|
// MG_Diligent::IsInRenderPass = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Enable(GLenum cap) {
|
void Enable(GLenum cap) {
|
||||||
MG_Util::Debug::LogD("glEnable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
|
MG_Util::Debug::LogD("glEnable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
|
||||||
GLenum result = MG_State::glEnable(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error enabling capability: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error enabling capability: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -26,7 +103,10 @@ namespace MG_GL::GL {
|
|||||||
void Disable(GLenum cap) {
|
void Disable(GLenum cap) {
|
||||||
MG_Util::Debug::LogD("glDisable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
|
MG_Util::Debug::LogD("glDisable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
|
||||||
GLenum result = MG_State::glDisable(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error disabling capability: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error disabling capability: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -36,7 +116,10 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::GLEnumToString(sfactor),
|
MG_Util::Debug::GLEnumToString(sfactor),
|
||||||
MG_Util::Debug::GLEnumToString(dfactor));
|
MG_Util::Debug::GLEnumToString(dfactor));
|
||||||
GLenum result = MG_State::glBlendFunc(sfactor, 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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error setting blend func: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error setting blend func: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -48,7 +131,10 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::GLEnumToString(srcAlpha),
|
MG_Util::Debug::GLEnumToString(srcAlpha),
|
||||||
MG_Util::Debug::GLEnumToString(dstAlpha));
|
MG_Util::Debug::GLEnumToString(dstAlpha));
|
||||||
GLenum result = MG_State::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, 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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error setting separate blend func: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error setting separate blend func: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -56,7 +142,10 @@ namespace MG_GL::GL {
|
|||||||
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||||
MG_Util::Debug::LogD("glClearColor, rgba: [%.2f, %.2f, %.2f, %.2f]", red, green, blue, alpha);
|
MG_Util::Debug::LogD("glClearColor, rgba: [%.2f, %.2f, %.2f, %.2f]", red, green, blue, alpha);
|
||||||
GLenum result = MG_State::glClearColor(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error setting clear color: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error setting clear color: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -64,7 +153,10 @@ namespace MG_GL::GL {
|
|||||||
void ClearDepth(GLdouble depth) {
|
void ClearDepth(GLdouble depth) {
|
||||||
MG_Util::Debug::LogD("glClearDepth, depth: %.3f", depth);
|
MG_Util::Debug::LogD("glClearDepth, depth: %.3f", depth);
|
||||||
GLenum result = MG_State::glClearDepth(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error setting clear depth: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error setting clear depth: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -72,7 +164,10 @@ namespace MG_GL::GL {
|
|||||||
void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
|
void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
|
||||||
MG_Util::Debug::LogD("glColorMask, rgba: [%d, %d, %d, %d]", red, green, blue, alpha);
|
MG_Util::Debug::LogD("glColorMask, rgba: [%d, %d, %d, %d]", red, green, blue, alpha);
|
||||||
GLenum result = MG_State::glColorMask(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error setting color mask: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error setting color mask: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -80,7 +175,10 @@ namespace MG_GL::GL {
|
|||||||
void DepthFunc(GLenum func) {
|
void DepthFunc(GLenum func) {
|
||||||
MG_Util::Debug::LogD("glDepthFunc, func: %s", MG_Util::Debug::GLEnumToString(func));
|
MG_Util::Debug::LogD("glDepthFunc, func: %s", MG_Util::Debug::GLEnumToString(func));
|
||||||
GLenum result = MG_State::glDepthFunc(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error setting depth func: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error setting depth func: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -88,7 +186,10 @@ namespace MG_GL::GL {
|
|||||||
void DepthMask(GLboolean flag) {
|
void DepthMask(GLboolean flag) {
|
||||||
MG_Util::Debug::LogD("glDepthMask, flag: %d", flag);
|
MG_Util::Debug::LogD("glDepthMask, flag: %d", flag);
|
||||||
GLenum result = MG_State::glDepthMask(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error setting depth mask: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error setting depth mask: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -97,16 +198,20 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::LogD("glViewport, x: %d, y: %d, width: %d, height: %d",
|
MG_Util::Debug::LogD("glViewport, x: %d, y: %d, width: %d, height: %d",
|
||||||
x, y, width, height);
|
x, y, width, height);
|
||||||
GLenum result = MG_State::glViewport(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error setting viewport: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error setting viewport: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelStorei(GLenum pname, GLint param) {
|
void PixelStorei(GLenum pname, GLint param) {
|
||||||
MG_Util::Debug::LogD("glPixelStorei, pname: %d, param: %d", pname, param);
|
MG_Util::Debug::LogD("glPixelStorei, pname: %s, param: %d", MG_Util::Debug::GLEnumToString(pname), param);
|
||||||
GLenum result = MG_State::SetPixelStoreInt(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;
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_GL_COMMON_H
|
#ifndef MOBILEGL_GL_COMMON_H
|
||||||
#define MOBILEGL_GL_COMMON_H
|
#define MOBILEGL_GL_COMMON_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
void ClearDepth(GLdouble depth);
|
void ClearDepth(GLdouble depth);
|
||||||
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,15 +4,17 @@
|
|||||||
|
|
||||||
#ifndef MOBILEGL_GL_DRAWING_H
|
#ifndef MOBILEGL_GL_DRAWING_H
|
||||||
#define MOBILEGL_GL_DRAWING_H
|
#define MOBILEGL_GL_DRAWING_H
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
|
bool IsSamplerType(GLenum type);
|
||||||
|
Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type);
|
||||||
|
void PrepareForDraw(GLenum mode, GLsizei* pCount, GLenum& type, const void*& pIndices);
|
||||||
|
|
||||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
|
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||||
void DrawArrays(GLenum mode, GLint first, GLsizei count);
|
void DrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||||
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
|
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
|
||||||
void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount);
|
void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount);
|
||||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex);
|
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex);
|
||||||
void DrawBuffer(GLenum buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //MOBILEGL_GL_DRAWING_H
|
#endif //MOBILEGL_GL_DRAWING_H
|
||||||
|
|||||||
@@ -2,13 +2,235 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GL_Framebuffer.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
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;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
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::LogD("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 = framebuffer != 0 ? fbInfo.ColorRTVs[i]->GetDesc().Format:
|
||||||
|
// MG_Diligent::g_pSwapChain->GetDesc().ColorBufferFormat;
|
||||||
|
// 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: FramebufferDesc Details:");
|
||||||
|
// MG_Util::Debug::LogD(" Name: %s", FBDesc.Name ? FBDesc.Name : "N/A");
|
||||||
|
// MG_Util::Debug::LogD(" pRenderPass: %p", FBDesc.pRenderPass);
|
||||||
|
// MG_Util::Debug::LogD(" AttachmentCount: %u", FBDesc.AttachmentCount);
|
||||||
|
// for (Diligent::Uint32 i = 0; i < FBDesc.AttachmentCount; ++i) {
|
||||||
|
// if (FBDesc.ppAttachments && FBDesc.ppAttachments[i]) {
|
||||||
|
// Diligent::ITexture* pTexture = FBDesc.ppAttachments[i]->GetTexture();
|
||||||
|
// if (pTexture) {
|
||||||
|
// const auto& texDesc = pTexture->GetDesc();
|
||||||
|
// MG_Util::Debug::LogD(" Attachment %u: Texture '%s', Dim: %ux%u",
|
||||||
|
// i, texDesc.Name ? texDesc.Name : "N/A", texDesc.Width, texDesc.Height);
|
||||||
|
// } else {
|
||||||
|
// MG_Util::Debug::LogW(" Attachment %u: TextureView's texture is nullptr", i);
|
||||||
|
// }
|
||||||
|
// } else if (!FBDesc.ppAttachments) {
|
||||||
|
// MG_Util::Debug::LogW(" FBDesc.ppAttachments is nullptr. Cannot access attachment %u.", i);
|
||||||
|
// } else {
|
||||||
|
// MG_Util::Debug::LogD(" Attachment %u: nullptr", i);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// MG_Util::Debug::LogD(" Width: %u", FBDesc.Width);
|
||||||
|
// MG_Util::Debug::LogD(" Height: %u", FBDesc.Height);
|
||||||
|
// MG_Util::Debug::LogD(" NumArraySlices: %u", FBDesc.NumArraySlices);
|
||||||
|
// MG_Util::Debug::LogD(" fbInfo.pFramebuffer: %p", fbInfo.pFramebuffer);
|
||||||
|
|
||||||
|
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) {
|
void GenFramebuffers(GLsizei n, GLuint* framebuffers) {
|
||||||
MG_Util::Debug::LogD("glGenFramebuffers, n: %d, framebuffers: %p", n, framebuffers);
|
MG_Util::Debug::LogD("glGenFramebuffers, n: %d, framebuffers: %p", n, framebuffers);
|
||||||
GLenum result = MG_State::CreateFramebuffers(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Framebuffer generation failed: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Framebuffer generation failed: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -21,32 +243,258 @@ namespace MG_GL::GL {
|
|||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Failed to delete framebuffer %u: %s",
|
MG_Util::Debug::LogE("Failed to delete framebuffer %u: %s",
|
||||||
framebuffers[i], MG_Util::Debug::GLEnumToString(result));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindFramebuffer(GLenum target, GLuint framebuffer) {
|
void BindFramebuffer(GLenum target, GLuint framebuffer) {
|
||||||
MG_Util::Debug::LogD("glBindFramebuffer, target: %s, fb: %u",
|
MG_Util::Debug::LogD("BindFramebuffer: Start. Target: %s, Framebuffer: %u",
|
||||||
MG_Util::Debug::GLEnumToString(target), framebuffer);
|
MG_Util::Debug::GLEnumToString(target), framebuffer);
|
||||||
|
|
||||||
GLenum result = MG_State::BindFramebuffer(target, framebuffer);
|
GLenum result = MG_State::BindFramebuffer(target, framebuffer);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) {
|
||||||
|
MG_Util::Debug::LogD("BindFramebuffer: MG_State::BindFramebuffer successful.");
|
||||||
|
|
||||||
|
// if (MG_Diligent::IsInRenderPass) {
|
||||||
|
// MG_Util::Debug::LogD("BindFramebuffer: Ending current render pass.");
|
||||||
|
// MG_Diligent::g_pContext->EndRenderPass();
|
||||||
|
// MG_Diligent::IsInRenderPass = false;
|
||||||
|
// MG_Util::Debug::LogD("BindFramebuffer: Current render pass ended.");
|
||||||
|
// } else {
|
||||||
|
// MG_Util::Debug::LogD("BindFramebuffer: No active render pass to end.");
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
if (framebuffer == 0) {
|
||||||
|
MG_Util::Debug::LogD("BindFramebuffer: Framebuffer is 0 (default framebuffer). Updating default framebuffer.");
|
||||||
|
UpdateDefaultFramebuffer();
|
||||||
|
MG_Util::Debug::LogD("BindFramebuffer: Default framebuffer updated.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FramebufferObject* pFBO = MG_State_T::framebufferState->GetCurrentFBO(target);
|
||||||
|
MG_Util::Debug::LogD("BindFramebuffer: Retrieved FBO from state: %p", pFBO);
|
||||||
|
|
||||||
|
auto it = MG_Diligent::g_FramebufferMap.find(framebuffer);
|
||||||
|
|
||||||
|
if (it == MG_Diligent::g_FramebufferMap.end()) {
|
||||||
|
MG_Util::Debug::LogE("BindFramebuffer: Framebuffer %u not found in g_FramebufferMap. Aborting.", framebuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD("BindFramebuffer: Framebuffer %u found in g_FramebufferMap.", framebuffer);
|
||||||
|
|
||||||
|
MG_Diligent::GLFramebufferInfo& fbInfo = it->second;
|
||||||
|
|
||||||
|
// if (/*!fbInfo.pRenderPass || */!fbInfo.pFramebuffer) {
|
||||||
|
// MG_Util::Debug::LogD("BindFramebuffer: RenderPass or Framebuffer not yet created for framebuffer %u. Creating now.", framebuffer);
|
||||||
|
// CreateRenderPassAndFramebuffer(framebuffer, pFBO ? *pFBO : FramebufferObject(), fbInfo);
|
||||||
|
// MG_Util::Debug::LogD("BindFramebuffer: RenderPass and Framebuffer creation attempted for framebuffer %u.", framebuffer);
|
||||||
|
// } else {
|
||||||
|
// MG_Util::Debug::LogD("BindFramebuffer: RenderPass and Framebuffer already exist for framebuffer %u.", framebuffer);
|
||||||
|
// }
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("BindFramebuffer: Setting render targets. ColorRTVs count: %zu, DepthStencilRTV: %p",
|
||||||
|
fbInfo.ColorRTVs.size(), fbInfo.pDepthStencilRTV);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
MG_Util::Debug::LogD("BindFramebuffer: SetRenderTargets called.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Framebuffer bind error: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Framebuffer bind error: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AttachTexture2DToFramebuffer(GLuint fbo, GLuint texture, GLenum attachment, GLint level) {
|
||||||
|
auto it = MG_Diligent::g_FramebufferMap.find(fbo);
|
||||||
|
if (it == MG_Diligent::g_FramebufferMap.end()) {
|
||||||
|
MG_Util::Debug::LogE("Framebuffer %u not found in map", fbo);
|
||||||
|
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;
|
||||||
|
bool allNull = true;
|
||||||
|
for (const auto& rtv : fbInfo.ColorRTVs) {
|
||||||
|
if (rtv != nullptr) {
|
||||||
|
allNull = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allNull) fbInfo.ColorRTVs.clear();
|
||||||
|
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();
|
||||||
|
fbInfo.pDepthStencilRTV = nullptr;
|
||||||
|
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();
|
||||||
|
fbInfo.ColorRTVs[index] = nullptr;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget,
|
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget,
|
||||||
GLuint texture, GLint level) {
|
GLuint texture, GLint level) {
|
||||||
MG_Util::Debug::LogD("glFramebufferTexture2D, target: %s, attach: %s, textarget: %s, tex: %u, level: %d",
|
MG_Util::Debug::LogD("glFramebufferTexture2D, target: %s, attach: %s, textarget: %s, tex: %u, level: %d",
|
||||||
MG_Util::Debug::GLEnumToString(target),
|
MG_Util::Debug::GLEnumToString(target),
|
||||||
MG_Util::Debug::GLEnumToString(attachment),
|
MG_Util::Debug::GLEnumToString(attachment),
|
||||||
MG_Util::Debug::GLEnumToString(textarget),
|
MG_Util::Debug::GLEnumToString(textarget),
|
||||||
texture, level);
|
texture,
|
||||||
|
level);
|
||||||
|
|
||||||
|
if (target == GL_FRAMEBUFFER) {
|
||||||
|
MG_Util::Debug::LogD("Got target == GL_FRAMEBUFFER, treating as GL_DRAW_FRAMEBUFFER");
|
||||||
|
target = GL_DRAW_FRAMEBUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD(" Current READ_FRAMEBUFFER binding: %u", MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER]);
|
||||||
|
MG_Util::Debug::LogD(" Current DRAW_FRAMEBUFFER binding: %u", MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]);
|
||||||
|
|
||||||
GLenum result = MG_State::AttachTexture2DToFramebuffer(
|
GLenum result = MG_State::AttachTexture2DToFramebuffer(
|
||||||
target, attachment, textarget, texture, level
|
target, attachment, textarget, texture, level
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) {
|
||||||
|
// if (target == GL_FRAMEBUFFER) {
|
||||||
|
// if (MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER] == MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]) {
|
||||||
|
// MG_Util::Debug::LogD(" Target is GL_FRAMEBUFFER and READ/DRAW bindings are the same (%u). Applying to GL_DRAW_FRAMEBUFFER.",
|
||||||
|
// MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]);
|
||||||
|
// target = GL_DRAW_FRAMEBUFFER;
|
||||||
|
// } else {
|
||||||
|
// MG_Util::Debug::LogD(" Target is GL_FRAMEBUFFER and READ/DRAW bindings differ. Applying to both if non-zero.");
|
||||||
|
// if (MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER] != 0) {
|
||||||
|
// MG_Util::Debug::LogD(" Attaching to READ_FRAMEBUFFER: %u", MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER]);
|
||||||
|
// AttachTexture2DToFramebuffer(MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER],
|
||||||
|
// texture, attachment, level);
|
||||||
|
// }
|
||||||
|
// if (MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER] != 0) {
|
||||||
|
// MG_Util::Debug::LogD(" Attaching to DRAW_FRAMEBUFFER: %u", MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]);
|
||||||
|
// AttachTexture2DToFramebuffer(MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER],
|
||||||
|
// texture, attachment, level);
|
||||||
|
// }
|
||||||
|
// MG_Util::Debug::LogD("FramebufferTexture2D completed successfully after separate READ/DRAW attachments.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
GLuint fboToModify = MG_State_T::framebufferState->currentBindings_[target];
|
||||||
|
MG_Util::Debug::LogD(" Target is %s. Applying to bound FBO: %u",
|
||||||
|
MG_Util::Debug::GLEnumToString(target), fboToModify);
|
||||||
|
AttachTexture2DToFramebuffer(fboToModify,
|
||||||
|
texture, attachment, level);
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("FramebufferTexture2D completed successfully for target %s (FBO %u).", MG_Util::Debug::GLEnumToString(target), fboToModify);
|
||||||
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Texture attachment failed: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Texture attachment failed: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -56,8 +504,7 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::GLEnumToString(target));
|
MG_Util::Debug::GLEnumToString(target));
|
||||||
GLenum result = MG_State::ValidateFramebufferCompleteness(target);
|
GLenum result = MG_State::ValidateFramebufferCompleteness(target);
|
||||||
if (result >= GL_FRAMEBUFFER_COMPLETE) {
|
if (result >= GL_FRAMEBUFFER_COMPLETE) {
|
||||||
MG_Util::Debug::LogD("Framebuffer status: %s",
|
MG_Util::Debug::LogD("Framebuffer status: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
MG_Util::Debug::GLEnumToString(result));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
@@ -68,6 +515,92 @@ namespace MG_GL::GL {
|
|||||||
|
|
||||||
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
|
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
|
||||||
// TODO
|
// if (MG_Diligent::IsInRenderPass) {
|
||||||
|
// MG_Util::Debug::LogD("Ending current render pass.");
|
||||||
|
// MG_Diligent::g_pContext->EndRenderPass();
|
||||||
|
// MG_Diligent::IsInRenderPass = false;
|
||||||
|
// MG_Util::Debug::LogD("Current render pass ended.");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// explicitly unbind the texture
|
||||||
|
MG_Diligent::g_pContext->SetRenderTargets(0, nullptr, nullptr, Diligent::RESOURCE_STATE_TRANSITION_MODE_NONE);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawBuffer(GLenum buf) {
|
||||||
|
MG_Util::Debug::LogD("glDrawBuffer, buf: %s", MG_Util::Debug::GLEnumToString(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawBuffers(GLsizei n, const GLenum *bufs) {
|
||||||
|
MG_Util::Debug::LogD("glDrawBuffers, n: %d, bufs: [", n);
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
MG_Util::Debug::LogD("%s,", MG_Util::Debug::GLEnumToString(bufs[i]));
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD("]");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadBuffer(GLenum buf) {
|
||||||
|
MG_Util::Debug::LogD("glReadBuffer, buf: %s", MG_Util::Debug::GLEnumToString(buf));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,15 +5,18 @@
|
|||||||
#ifndef MOBILEGL_GL_FRAMEBUFFER_H
|
#ifndef MOBILEGL_GL_FRAMEBUFFER_H
|
||||||
#define MOBILEGL_GL_FRAMEBUFFER_H
|
#define MOBILEGL_GL_FRAMEBUFFER_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
|
void UpdateDefaultFramebuffer();
|
||||||
|
|
||||||
void GenFramebuffers(GLsizei n, GLuint* framebuffers);
|
void GenFramebuffers(GLsizei n, GLuint* framebuffers);
|
||||||
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
|
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
|
||||||
void BindFramebuffer(GLenum target, GLuint framebuffer);
|
void BindFramebuffer(GLenum target, GLuint framebuffer);
|
||||||
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||||
GLenum CheckFramebufferStatus(GLenum target);
|
GLenum CheckFramebufferStatus(GLenum target);
|
||||||
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||||
|
void DrawBuffer(GLenum buf);
|
||||||
|
void DrawBuffers(GLsizei n, const GLenum *bufs);
|
||||||
|
void ReadBuffer(GLenum mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //MOBILEGL_GL_FRAMEBUFFER_H
|
#endif //MOBILEGL_GL_FRAMEBUFFER_H
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GLFuncsDefinitions.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
#define DECLARE_GL_FUNCTION_STUB_HEAD(type,name,...) \
|
#define DECLARE_GL_FUNCTION_STUB_HEAD(type,name,...) \
|
||||||
MG_EXPORT type gl##name(__VA_ARGS__) {
|
MG_EXPORT type gl##name(__VA_ARGS__) {
|
||||||
@@ -57,7 +57,7 @@ DECLARE_GL_FUNCTION_HEAD(void, CompileShader, GLuint shader) DECLARE_GL_FUNCTION
|
|||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexImage2D, target,level,internalformat,width,height,border,imageSize,data)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexImage2D, target,level,internalformat,width,height,border,imageSize,data)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexSubImage2D, target,level,xoffset,yoffset,width,height,format,imageSize,data)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexSubImage2D, target,level,xoffset,yoffset,width,height,format,imageSize,data)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTexImage2D, target,level,internalformat,x,y,width,height,border)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTexImage2D, target,level,internalformat,x,y,width,height,border)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTexSubImage2D, target,level,xoffset,yoffset,x,y,width,height)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CopyTexSubImage2D, target,level,xoffset,yoffset,x,y,width,height)
|
||||||
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateProgram) DECLARE_GL_FUNCTION_END(GLuint, CreateProgram)
|
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateProgram) DECLARE_GL_FUNCTION_END(GLuint, CreateProgram)
|
||||||
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateShader, GLenum type) DECLARE_GL_FUNCTION_END(GLuint, CreateShader, type)
|
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateShader, GLenum type) DECLARE_GL_FUNCTION_END(GLuint, CreateShader, type)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CullFace, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CullFace, mode)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CullFace, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CullFace, mode)
|
||||||
@@ -174,7 +174,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4f, GLuint index, GLfloat x, GLf
|
|||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4fv, GLuint index, const GLfloat *v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4fv, index,v)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4fv, GLuint index, const GLfloat *v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4fv, index,v)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribPointer, index,size,type,normalized,stride,pointer)
|
DECLARE_GL_FUNCTION_HEAD(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribPointer, index,size,type,normalized,stride,pointer)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, Viewport, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Viewport, x,y,width,height)
|
DECLARE_GL_FUNCTION_HEAD(void, Viewport, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Viewport, x,y,width,height)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ReadBuffer, GLenum src) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReadBuffer, src)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, ReadBuffer, GLenum src) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ReadBuffer, src)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawRangeElements, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawRangeElements, mode,start,end,count,type,indices)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawRangeElements, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawRangeElements, mode,start,end,count,type,indices)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage3D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage3D, target,level,internalformat,width,height,depth,border,format,type,pixels)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage3D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage3D, target,level,internalformat,width,height,depth,border,format,type,pixels)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexSubImage3D, target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexSubImage3D, target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)
|
||||||
@@ -190,7 +190,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryiv, GLenum target, GLenum pname, GLi
|
|||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname, GLuint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectuiv, id,pname,params)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname, GLuint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectuiv, id,pname,params)
|
||||||
DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target)
|
DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void **params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferPointerv, target,pname,params)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void **params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferPointerv, target,pname,params)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawBuffers, GLsizei n, const GLenum *bufs) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawBuffers, n,bufs)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawBuffers, GLsizei n, const GLenum *bufs) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawBuffers, n,bufs)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x3fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x3fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x2fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x2fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x4fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x4fv, location,count,transpose,value)
|
||||||
|
|||||||
@@ -5,6 +5,4 @@
|
|||||||
#ifndef MOBILEGL_GL_FUNCS_DEFINITIONS_H
|
#ifndef MOBILEGL_GL_FUNCS_DEFINITIONS_H
|
||||||
#define MOBILEGL_GL_FUNCS_DEFINITIONS_H
|
#define MOBILEGL_GL_FUNCS_DEFINITIONS_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
#endif //MOBILEGL_GL_FUNCS_DEFINITIONS_H
|
#endif //MOBILEGL_GL_FUNCS_DEFINITIONS_H
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "BackendInfo.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_GL::Getter {
|
namespace MG_GL::Getter {
|
||||||
const std::string GetBackendName() {
|
const std::string GetBackendName() {
|
||||||
@@ -12,6 +12,17 @@ namespace MG_GL::Getter {
|
|||||||
return "Metal";
|
return "Metal";
|
||||||
#elif BACKEND_TYPE == BACKEND_GLES
|
#elif BACKEND_TYPE == BACKEND_GLES
|
||||||
return "OpenGL ES";
|
return "OpenGL ES";
|
||||||
|
#elif BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
switch (MG_Diligent::DILIGENT_BACKEND_TYPE) {
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_VULKAN:
|
||||||
|
return "DiligentEngine (Vulkan)";
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_METAL:
|
||||||
|
return "DiligentEngine (Metal)";
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_OPENGL:
|
||||||
|
return "DiligentEngine (OpenGL)";
|
||||||
|
default:
|
||||||
|
return "DiligentEngine (Unknown Backend)";
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return "<Unknown Backend>";
|
return "<Unknown Backend>";
|
||||||
#endif
|
#endif
|
||||||
@@ -24,11 +35,78 @@ namespace MG_GL::Getter {
|
|||||||
return "MobileGlumtl";
|
return "MobileGlumtl";
|
||||||
#elif BACKEND_TYPE == BACKEND_GLES
|
#elif BACKEND_TYPE == BACKEND_GLES
|
||||||
return "MobileGlues";
|
return "MobileGlues";
|
||||||
|
#elif BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
switch (MG_Diligent::DILIGENT_BACKEND_TYPE) {
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_VULKAN:
|
||||||
|
return "MobileGlued-vk";
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_METAL:
|
||||||
|
return "MobileGlued-mtl";
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_OPENGL:
|
||||||
|
return "MobileGlued-gl";
|
||||||
|
default:
|
||||||
|
return "MobileGlued-unknown";
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return "<Unknown MobileGL Version>";
|
return "<Unknown MobileGL Version>";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string GetBackendGfxAPIName() {
|
||||||
|
#if BACKEND_TYPE == BACKEND_VULKAN
|
||||||
|
return "Vulkan";
|
||||||
|
#elif BACKEND_TYPE == BACKEND_METAL
|
||||||
|
return "Metal";
|
||||||
|
#elif BACKEND_TYPE == BACKEND_GLES
|
||||||
|
return "OpenGL ES";
|
||||||
|
#elif BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
switch (MG_Diligent::DILIGENT_BACKEND_TYPE) {
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_VULKAN:
|
||||||
|
return "Vulkan";
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_METAL:
|
||||||
|
return "Metal";
|
||||||
|
case MG_Constants::Backend::BACKEND_DILIGENT_OPENGL:
|
||||||
|
return "OpenGL";
|
||||||
|
default:
|
||||||
|
return "<unknown>";
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return "<Unknown Backend>";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string GetGPUName() {
|
||||||
|
#if BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
if (MG_Diligent::g_pDevice)
|
||||||
|
return MG_Diligent::g_pDevice->GetAdapterInfo().Description;
|
||||||
|
|
||||||
|
return "<not set yet>";
|
||||||
|
#else
|
||||||
|
return "<unknown GPU>";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t GetBackendGfxAPIVersionMajor() {
|
||||||
|
#if BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
if (MG_Diligent::g_pDevice)
|
||||||
|
return MG_Diligent::g_pDevice->GetDeviceInfo().APIVersion.Major;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t GetBackendGfxAPIVersionMinor() {
|
||||||
|
#if BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
if (MG_Diligent::g_pDevice)
|
||||||
|
return MG_Diligent::g_pDevice->GetDeviceInfo().APIVersion.Minor;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void LogMGInfo() {
|
void LogMGInfo() {
|
||||||
std::string MGName = MG_GL::Getter::GetMGName() + " (MobileGL Core)";
|
std::string MGName = MG_GL::Getter::GetMGName() + " (MobileGL Core)";
|
||||||
|
|
||||||
@@ -79,6 +157,8 @@ namespace MG_GL::Getter {
|
|||||||
std::to_string(minor)+"." + std::to_string(patch);
|
std::to_string(minor)+"." + std::to_string(patch);
|
||||||
#elif BACKEND_TYPE == BACKEND_GLES
|
#elif BACKEND_TYPE == BACKEND_GLES
|
||||||
backendVersion = std::string((const char*)::GLES::glGetString(GL_VERSION));
|
backendVersion = std::string((const char*)::GLES::glGetString(GL_VERSION));
|
||||||
|
#elif BACKEND_TYPE == BACKEND_DILIGENT
|
||||||
|
backendVersion = "Diligent";
|
||||||
#else
|
#else
|
||||||
backendVersion = "<Unknown Backend>";
|
backendVersion = "<Unknown Backend>";
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
#ifndef MOBILEGL_BACKENDINFO_H
|
#ifndef MOBILEGL_BACKENDINFO_H
|
||||||
#define MOBILEGL_BACKENDINFO_H
|
#define MOBILEGL_BACKENDINFO_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::Getter {
|
namespace MG_GL::Getter {
|
||||||
|
const std::string GetGPUName();
|
||||||
const std::string GetBackendName();
|
const std::string GetBackendName();
|
||||||
|
const std::string GetBackendGfxAPIName();
|
||||||
|
const uint32_t GetBackendGfxAPIVersionMajor();
|
||||||
|
const uint32_t GetBackendGfxAPIVersionMinor();
|
||||||
const std::string GetMGName();
|
const std::string GetMGName();
|
||||||
void LogMGInfo();
|
void LogMGInfo();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GL_Getter.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
static std::string rendererString;
|
static std::string rendererString;
|
||||||
@@ -15,7 +15,7 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::LogD("glGetString, name: %s", MG_Util::Debug::GLEnumToString(name));
|
MG_Util::Debug::LogD("glGetString, name: %s", MG_Util::Debug::GLEnumToString(name));
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case GL_VENDOR:
|
case GL_VENDOR:
|
||||||
return (const GLubyte *)"MobileGL-Dev";
|
return (const GLubyte *)"MobileGL-Dev (BZLZHH, Swung0x48, Tungsten)";
|
||||||
case GL_VERSION: {
|
case GL_VERSION: {
|
||||||
static std::string versionStr;
|
static std::string versionStr;
|
||||||
if (versionStr.empty()) {
|
if (versionStr.empty()) {
|
||||||
@@ -44,7 +44,11 @@ namespace MG_GL::GL {
|
|||||||
}
|
}
|
||||||
return (const GLubyte *)rendererString.c_str();
|
return (const GLubyte *)rendererString.c_str();
|
||||||
*/
|
*/
|
||||||
return (const GLubyte *)(MG_GL::Getter::GetMGName() + " (MobileGL Core) Renderer").c_str();
|
return (const GLubyte *)std::format("{} | {} {}.{}",
|
||||||
|
MG_GL::Getter::GetGPUName(),
|
||||||
|
MG_GL::Getter::GetBackendGfxAPIName(),
|
||||||
|
MG_GL::Getter::GetBackendGfxAPIVersionMajor(),
|
||||||
|
MG_GL::Getter::GetBackendGfxAPIVersionMinor()).c_str();
|
||||||
}
|
}
|
||||||
case GL_SHADING_LANGUAGE_VERSION:
|
case GL_SHADING_LANGUAGE_VERSION:
|
||||||
return (const GLubyte *) "4.50 MobileGL with glslang";
|
return (const GLubyte *) "4.50 MobileGL with glslang";
|
||||||
@@ -183,7 +187,7 @@ namespace MG_GL::GL {
|
|||||||
break;
|
break;
|
||||||
case GL_MAX_VERTEX_ATTRIBS:
|
case GL_MAX_VERTEX_ATTRIBS:
|
||||||
// TODO: Check the real value
|
// TODO: Check the real value
|
||||||
params[0] = 64;
|
params[0] = MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Texture state
|
// Texture state
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_GL_GETTER_H
|
#ifndef MOBILEGL_GL_GETTER_H
|
||||||
#define MOBILEGL_GL_GETTER_H
|
#define MOBILEGL_GL_GETTER_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
const GLubyte* GetString(GLenum name);
|
const GLubyte* GetString(GLenum name);
|
||||||
const GLubyte* GetStringi(GLenum name, GLuint index);
|
const GLubyte* GetStringi(GLenum name, GLuint index);
|
||||||
|
|||||||
@@ -2,15 +2,197 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GL_Program.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
|
void CreateDefaultUBO(MG_Diligent::GLProgramInfo& programInfo, size_t uboSize) {
|
||||||
|
MG_Util::Debug::LogD("CreateDefaultUBO for program, size = %zu", uboSize);
|
||||||
|
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("UBO size is 0, default UBO not created.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t RecordUniformOffsets(MG_Diligent::GLProgramInfo& programInfo, const MG_Global::unordered_map<GLuint, std::string>& shaderSources) {
|
||||||
|
MG_Util::Debug::LogD("RecordUniformOffsets for program %u using SPIRV-Cross", programInfo.id);
|
||||||
|
size_t uboTotalSize = 0;
|
||||||
|
programInfo.uniformOffsets.clear();
|
||||||
|
|
||||||
|
GLuint reflectionShaderId = 0;
|
||||||
|
for (auto shaderId : programInfo.AttachedShadersID) {
|
||||||
|
auto& shaderObj = MG_State_T::programState->shaders_[shaderId];
|
||||||
|
MG_Util::Debug::LogD(" Checking attached shader %u, type: %s", shaderId, MG_Util::Debug::GLEnumToString(shaderObj.type));
|
||||||
|
if (shaderObj.type == GL_VERTEX_SHADER) {
|
||||||
|
reflectionShaderId = shaderId;
|
||||||
|
MG_Util::Debug::LogD(" Found vertex shader %u for reflection.", reflectionShaderId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!reflectionShaderId && !programInfo.AttachedShadersID.empty()) {
|
||||||
|
reflectionShaderId = programInfo.AttachedShadersID[0];
|
||||||
|
MG_Util::Debug::LogD(" No vertex shader found, using first attached shader %u for reflection.", reflectionShaderId);
|
||||||
|
}
|
||||||
|
if (!reflectionShaderId) {
|
||||||
|
MG_Util::Debug::LogW(" No suitable shader found for UBO reflection.");
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD(" Using shader %u for UBO reflection.", reflectionShaderId);
|
||||||
|
auto itSource = shaderSources.find(reflectionShaderId);
|
||||||
|
if (itSource == shaderSources.end()) {
|
||||||
|
MG_Util::Debug::LogE(" Could not find source for reflection shader %u.", reflectionShaderId);
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD(" Found source for shader %u.", reflectionShaderId);
|
||||||
|
MG_Util::Debug::LogD(" Shader source for reflection:\n%s", itSource->second.c_str());
|
||||||
|
std::string infoLog;
|
||||||
|
auto spirv = MG_Util::Program::CompileGLSLToSPIRV(
|
||||||
|
MG_State_T::programState->shaders_[reflectionShaderId].type,
|
||||||
|
itSource->second,
|
||||||
|
infoLog,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
if (spirv.empty()) {
|
||||||
|
MG_Util::Debug::LogE("GLSL to SPIR-V compilation failed for shader %u: %s", reflectionShaderId, infoLog.c_str());
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD(" Successfully compiled GLSL to SPIR-V for shader %u.", reflectionShaderId);
|
||||||
|
|
||||||
|
spvc_context context = nullptr;
|
||||||
|
spvc_parsed_ir ir = nullptr;
|
||||||
|
spvc_compiler compiler = nullptr;
|
||||||
|
spvc_resources resources = nullptr;
|
||||||
|
|
||||||
|
if (spvc_context_create(&context) != SPVC_SUCCESS) {
|
||||||
|
MG_Util::Debug::LogE("SPIRV-Cross: Failed to create context: %s", spvc_context_get_last_error_string(context));
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spvc_context_parse_spirv(context, spirv.data(), spirv.size(), &ir) != SPVC_SUCCESS) {
|
||||||
|
MG_Util::Debug::LogE("SPIRV-Cross: Failed to parse SPIR-V: %s", spvc_context_get_last_error_string(context));
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler) != SPVC_SUCCESS) {
|
||||||
|
MG_Util::Debug::LogE("SPIRV-Cross: Failed to create compiler: %s", spvc_context_get_last_error_string(context));
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD(" spvc_context_create_compiler successful.");
|
||||||
|
|
||||||
|
if (spvc_compiler_create_shader_resources(compiler, &resources) != SPVC_SUCCESS) {
|
||||||
|
MG_Util::Debug::LogE("SPIRV-Cross: Failed to create shader resources: %s", spvc_context_get_last_error_string(context));
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD(" spvc_compiler_create_shader_resources successful.");
|
||||||
|
|
||||||
|
const spvc_reflected_resource* ubo_list = nullptr;
|
||||||
|
size_t ubo_count = 0;
|
||||||
|
if (spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &ubo_list, &ubo_count) != SPVC_SUCCESS) {
|
||||||
|
MG_Util::Debug::LogE("SPIRV-Cross: Failed to get resource list for UBO: %s", spvc_context_get_last_error_string(context));
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD(" Found %zu UBO resources.", ubo_count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ubo_count; i++) {
|
||||||
|
const char* name = ubo_list[i].name;
|
||||||
|
if (!name || strcmp(name, "MG_DEFAULT_UBO") != 0) {
|
||||||
|
MG_Util::Debug::LogD(" Skipping UBO '%s'.", name ? name : "<unnamed>");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD(" Found UBO 'MG_DEFAULT_UBO'.");
|
||||||
|
spvc_type_id ubo_type_id = ubo_list[i].type_id;
|
||||||
|
spvc_type ubo_type = spvc_compiler_get_type_handle(compiler, ubo_type_id);
|
||||||
|
|
||||||
|
size_t currentUboSize = 0;
|
||||||
|
if (spvc_compiler_get_declared_struct_size(compiler, ubo_type, ¤tUboSize) != SPVC_SUCCESS) {
|
||||||
|
MG_Util::Debug::LogE("SPIRV-Cross: Failed to get declared struct size: %s", spvc_context_get_last_error_string(context));
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
uboTotalSize = currentUboSize;
|
||||||
|
MG_Util::Debug::LogD(" UBO 'MG_DEFAULT_UBO' total size: %zu", uboTotalSize);
|
||||||
|
|
||||||
|
size_t member_count = spvc_type_get_num_member_types(ubo_type);
|
||||||
|
for (size_t member_index = 0; member_index < member_count; member_index++) {
|
||||||
|
const char* member_name = programInfo.uniformBufferNames[member_index].c_str();
|
||||||
|
|
||||||
|
unsigned offset;
|
||||||
|
spvc_compiler_type_struct_member_offset(compiler, ubo_type, member_index, &offset);
|
||||||
|
|
||||||
|
if (member_name) {
|
||||||
|
programInfo.uniformOffsets[member_name] = offset;
|
||||||
|
MG_Util::Debug::LogD(
|
||||||
|
" Uniform '%s' offset = %u (via SPIRV-Cross)",
|
||||||
|
member_name,
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
MG_Util::Debug::LogD("RecordUniformOffsets completed for program %u, UBO total size: %zu", programInfo.id, uboTotalSize);
|
||||||
|
return uboTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_SHORT: return Diligent::VT_INT16;
|
||||||
|
case GL_UNSIGNED_SHORT: return Diligent::VT_UINT16;
|
||||||
|
case GL_BYTE: return Diligent::VT_INT8;
|
||||||
|
case GL_UNSIGNED_BYTE: return Diligent::VT_UINT8;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GLuint CreateShader(GLenum type) {
|
GLuint CreateShader(GLenum type) {
|
||||||
MG_Util::Debug::LogD("glCreateShader, type: %s", MG_Util::Debug::GLEnumToString(type));
|
MG_Util::Debug::LogD("glCreateShader, type: %s", MG_Util::Debug::GLEnumToString(type));
|
||||||
GLuint shader;
|
GLuint shader;
|
||||||
GLenum result = MG_State::CreateShader(type, &shader);
|
GLenum result = MG_State::CreateShader(type, &shader);
|
||||||
if (result == GL_NO_ERROR) {
|
if (result == GL_NO_ERROR) {
|
||||||
MG_Util::Debug::LogD("Created shader ID: %u", shader);
|
MG_Util::Debug::LogD("Created shader ID: %u", shader);
|
||||||
|
MG_Diligent::g_ShaderMap[shader] = nullptr;
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
@@ -34,15 +216,29 @@ namespace MG_GL::GL {
|
|||||||
void DeleteShader(GLuint shader) {
|
void DeleteShader(GLuint shader) {
|
||||||
MG_Util::Debug::LogD("glDeleteShader, shader: %u", shader);
|
MG_Util::Debug::LogD("glDeleteShader, shader: %u", shader);
|
||||||
GLenum result = MG_State::DeleteShader(shader);
|
GLenum result = MG_State::DeleteShader(shader);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) {
|
||||||
|
// Do not delete the shader object since it may be used in glDraw*.
|
||||||
|
/*
|
||||||
|
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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error deleting shader: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogW("Error deleting shader: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteProgram(GLuint program) {
|
void DeleteProgram(GLuint program) {
|
||||||
MG_Util::Debug::LogD("glDeleteProgram, program: %u", program);
|
MG_Util::Debug::LogD("glDeleteProgram, program: %u", program);
|
||||||
GLenum result = MG_State::DeleteProgram(program);
|
GLenum result = MG_State::DeleteProgram(program);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error deleting program: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error deleting program: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -50,13 +246,20 @@ namespace MG_GL::GL {
|
|||||||
void AttachShader(GLuint program, GLuint shader) {
|
void AttachShader(GLuint program, GLuint shader) {
|
||||||
MG_Util::Debug::LogD("glAttachShader, program: %u, shader: %u", program, shader);
|
MG_Util::Debug::LogD("glAttachShader, program: %u, shader: %u", program, shader);
|
||||||
GLenum result = MG_State::LinkShaderToProgram(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error attaching shader: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error attaching shader: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint* length) {
|
void ShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint* length) {
|
||||||
MG_Util::Debug::LogD("glShaderSource, shader: %u, count: %d", shader, count);
|
MG_Util::Debug::LogD("glShaderSource, shader: %u, count: %d", shader, count);
|
||||||
|
if (count > 0 && string != nullptr && string[0] != nullptr) {
|
||||||
|
MG_Util::Debug::LogD("Shader source for shader %u:\n%s", shader, string[0]);
|
||||||
|
} else {
|
||||||
|
MG_Util::Debug::LogD("Shader source for shader %u is empty or null.", shader);
|
||||||
|
}
|
||||||
GLenum result = MG_State::UploadShaderSource(shader, count, (const GLchar **)string, length);
|
GLenum result = MG_State::UploadShaderSource(shader, count, (const GLchar **)string, length);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) return;
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
@@ -65,31 +268,206 @@ namespace MG_GL::GL {
|
|||||||
|
|
||||||
void CompileShader(GLuint shader) {
|
void CompileShader(GLuint shader) {
|
||||||
MG_Util::Debug::LogD("glCompileShader, shader: %u", shader);
|
MG_Util::Debug::LogD("glCompileShader, shader: %u", shader);
|
||||||
|
// Defer actual compilation to LinkProgram
|
||||||
GLenum result = MG_State::BuildShaderStage(shader);
|
GLenum result = MG_State::BuildShaderStage(shader);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) return;
|
||||||
MG_State::SetError(result);
|
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) {
|
void LinkProgram(GLuint program) {
|
||||||
MG_Util::Debug::LogD("glLinkProgram, program: %u", program);
|
MG_Util::Debug::LogD("glLinkProgram, program: %u", program);
|
||||||
GLenum result = MG_State::FinalizeProgramPipeline(program);
|
GLenum result = MG_State::FinalizeProgramPipeline(program);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result != GL_NO_ERROR) {
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error linking program: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error linking program: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& programInfo = MG_Diligent::g_ProgramMap[program];
|
||||||
|
auto& programObj = MG_State_T::programState->programs_[program];
|
||||||
|
|
||||||
|
programInfo.id = program;
|
||||||
|
|
||||||
|
for (const auto& shaderId : programObj.attachedShaders) {
|
||||||
|
programInfo.AttachedShadersID.push_back(shaderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Global::unordered_map<GLuint, std::string> shaderSources;
|
||||||
|
MG_Global::unordered_map<GLuint, std::string> finalShaderSources;
|
||||||
|
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) {
|
||||||
|
shaderSources[it->first] = it->second.source;
|
||||||
|
// MG_Util::Program::RenameGLSLBuiltinsForVulkan(shaderSources[it->first]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Program::GenerateDefaultUBOForGLSL_Multi(shaderSources, programInfo.uniformBufferNames);
|
||||||
|
MG_Util::Debug::LogD("LinkProgram: uniformBufferNames for %u:", program);
|
||||||
|
for (auto& name: programInfo.uniformBufferNames) {
|
||||||
|
MG_Util::Debug::LogD(" %s", name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
std::string shaderSource;
|
||||||
|
if (it->second.type == GL_VERTEX_SHADER) {
|
||||||
|
std::string infoLog;
|
||||||
|
|
||||||
|
const char* fragmentShaderSource = nullptr;
|
||||||
|
for (GLuint otherShaderId : programObj.attachedShaders) {
|
||||||
|
if (otherShaderId != shaderId && MG_State_T::programState->shaders_[otherShaderId].type == GL_FRAGMENT_SHADER) {
|
||||||
|
fragmentShaderSource = shaderSources[otherShaderId].c_str();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto spirv = MG_Util::Program::CompileGLSLToSPIRV(it->second.type,
|
||||||
|
shaderSources[shaderId],
|
||||||
|
infoLog, true, GL_FRAGMENT_SHADER, fragmentShaderSource);
|
||||||
|
if (spirv.empty()) {
|
||||||
|
MG_Util::Debug::LogE("Failed to compile vertex shader %u: %s", shaderId,
|
||||||
|
infoLog.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderSource = MG_Util::Program::BindInputLayoutLocationsForGLSL(spirv,
|
||||||
|
programObj.attribLocations);
|
||||||
|
} else if (it->second.type == GL_FRAGMENT_SHADER) {
|
||||||
|
std::string infoLog;
|
||||||
|
|
||||||
|
const char* vertexShaderSource = nullptr;
|
||||||
|
for (GLuint otherShaderId : programObj.attachedShaders) {
|
||||||
|
if (otherShaderId != shaderId && MG_State_T::programState->shaders_[otherShaderId].type == GL_VERTEX_SHADER) {
|
||||||
|
vertexShaderSource = shaderSources[otherShaderId].c_str();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spirv = MG_Util::Program::CompileGLSLToSPIRV(it->second.type,
|
||||||
|
shaderSources[shaderId],
|
||||||
|
infoLog, true,
|
||||||
|
GL_VERTEX_SHADER, vertexShaderSource);
|
||||||
|
if (spirv.empty()) {
|
||||||
|
MG_Util::Debug::LogE("Failed to compile fragment shader %u to SPIRV: %s", shaderId,
|
||||||
|
infoLog.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderSource = MG_Util::Program::CompileSPIRVToGLSL(spirv, 450, false, true);
|
||||||
|
} else {
|
||||||
|
shaderSource = it->second.source;
|
||||||
|
}
|
||||||
|
finalShaderSources[it->first] = shaderSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("Shader sources after UBO generation for program %u:", program);
|
||||||
|
for (const auto& [shaderId, source] : finalShaderSources) {
|
||||||
|
MG_Util::Debug::LogD(" Program %u Shader %u:\n%s", program, shaderId, source.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uboTotalSize = RecordUniformOffsets(programInfo, finalShaderSources);
|
||||||
|
CreateDefaultUBO(programInfo, uboTotalSize);
|
||||||
|
|
||||||
|
// 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 = finalShaderSources[shaderId];
|
||||||
|
MG_Util::Program::RenameGLSLBuiltinsForVulkan(sourceStr);
|
||||||
|
MG_Util::Debug::LogD("Shader ID: %u, type: %s\nConverted source:\n%s",
|
||||||
|
shaderId, MG_Util::Debug::GLEnumToString(shaderType), sourceStr.c_str());
|
||||||
|
|
||||||
|
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;
|
||||||
|
Diligent::RefCntAutoPtr<Diligent::IDataBlob> pMsg;
|
||||||
|
MG_Diligent::g_pDevice->CreateShader(ShaderCI, &pShader, &pMsg);
|
||||||
|
|
||||||
|
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. \ncompiler info:\n%s", shaderId, program, pMsg->GetConstDataPtr<char>());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Shader already compiled, just add to programInfo
|
||||||
|
programInfo.AttachedShaders.push_back(MG_Diligent::g_ShaderMap[shaderId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
programInfo.inputLayout.clear();
|
||||||
|
|
||||||
|
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
|
||||||
|
if (!pVAO) return;
|
||||||
|
|
||||||
|
// for (const auto& [index, attrib] : pVAO->attribs) {
|
||||||
|
for (uint32_t index = 0; index < MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS; ++index) {
|
||||||
|
const auto& attrib = pVAO->attribs[index];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
programObj.linked = true;
|
||||||
|
programObj.linkStatus = GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UseProgram(GLuint program) {
|
void UseProgram(GLuint program) {
|
||||||
MG_Util::Debug::LogD("glUseProgram, program: %u", program);
|
MG_Util::Debug::LogD("glUseProgram, program: %u", program);
|
||||||
GLenum result = MG_State::ActivateRenderProgram(program);
|
GLenum result = MG_State::ActivateRenderProgram(program);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error using program: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error using program: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindAttribLocation(GLuint program, GLuint index, const GLchar* name) {
|
void BindAttribLocation(GLuint program, GLuint index, const GLchar* name) {
|
||||||
MG_Util::Debug::LogD("glBindAttribLocation, program: %u, index: %u, name: %s", program, index, name);
|
MG_Util::Debug::LogD("glBindAttribLocation, program: %u, index: %u, name: %s", program, index, name);
|
||||||
GLenum result = MG_State::DefineProgramAttributeBinding(program, index, name);
|
GLenum result = MG_State::DefineProgramAttributeLocation(program, index, name);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) return;
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error binding attribute: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error binding attribute: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
@@ -97,7 +475,7 @@ namespace MG_GL::GL {
|
|||||||
|
|
||||||
GLint GetAttribLocation(GLuint program, const GLchar* name) {
|
GLint GetAttribLocation(GLuint program, const GLchar* name) {
|
||||||
MG_Util::Debug::LogD("glGetAttribLocation, program: %u, name: %s", program, name);
|
MG_Util::Debug::LogD("glGetAttribLocation, program: %u, name: %s", program, name);
|
||||||
GLint location = MG_State::QueryProgramAttributeBinding(program, name);
|
GLint location = MG_State::QueryProgramAttributeLocation(program, name);
|
||||||
if (location != -1) return location;
|
if (location != -1) return location;
|
||||||
MG_State::SetError(GL_INVALID_OPERATION);
|
MG_State::SetError(GL_INVALID_OPERATION);
|
||||||
MG_Util::Debug::LogE("Attribute not found: %s", name);
|
MG_Util::Debug::LogE("Attribute not found: %s", name);
|
||||||
@@ -119,7 +497,7 @@ namespace MG_GL::GL {
|
|||||||
GLenum result = MG_State::QueryProgramStateIntVector(program, pname, params);
|
GLenum result = MG_State::QueryProgramStateIntVector(program, pname, params);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) return;
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error getting program param: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogW("Error getting program param: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetShaderiv(GLuint shader, GLenum pname, GLint* params) {
|
void GetShaderiv(GLuint shader, GLenum pname, GLint* params) {
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
#ifndef MOBILEGL_GL_PROGRAM_H
|
#ifndef MOBILEGL_GL_PROGRAM_H
|
||||||
#define MOBILEGL_GL_PROGRAM_H
|
#define MOBILEGL_GL_PROGRAM_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
|
Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type);
|
||||||
|
|
||||||
GLuint CreateShader(GLenum type);
|
GLuint CreateShader(GLenum type);
|
||||||
GLuint CreateProgram();
|
GLuint CreateProgram();
|
||||||
void DeleteShader(GLuint shader);
|
void DeleteShader(GLuint shader);
|
||||||
|
|||||||
@@ -2,9 +2,187 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GL_Texture.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
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::FILTER_TYPE ConvertCompareFilter(Diligent::FILTER_TYPE& filter, bool compare) {
|
||||||
|
if (compare) {
|
||||||
|
switch (filter) {
|
||||||
|
case Diligent::FILTER_TYPE_POINT: return Diligent::FILTER_TYPE_COMPARISON_POINT;
|
||||||
|
case Diligent::FILTER_TYPE_LINEAR: return Diligent::FILTER_TYPE_COMPARISON_LINEAR;
|
||||||
|
case Diligent::FILTER_TYPE_ANISOTROPIC: return Diligent::FILTER_TYPE_COMPARISON_ANISOTROPIC;
|
||||||
|
default: return filter;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (filter) {
|
||||||
|
case Diligent::FILTER_TYPE_COMPARISON_POINT: return Diligent::FILTER_TYPE_POINT;
|
||||||
|
case Diligent::FILTER_TYPE_COMPARISON_LINEAR: return Diligent::FILTER_TYPE_LINEAR;
|
||||||
|
case Diligent::FILTER_TYPE_COMPARISON_ANISOTROPIC: return Diligent::FILTER_TYPE_ANISOTROPIC;
|
||||||
|
default: return filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompareFilter(Diligent::FILTER_TYPE filter) {
|
||||||
|
switch (filter) {
|
||||||
|
case Diligent::FILTER_TYPE_COMPARISON_POINT: return true;
|
||||||
|
case Diligent::FILTER_TYPE_COMPARISON_LINEAR: return true;
|
||||||
|
case Diligent::FILTER_TYPE_COMPARISON_ANISOTROPIC: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FillFilterTypeFromGLEnum(GLenum pname, GLenum param, Diligent::FILTER_TYPE& minFilter, Diligent::FILTER_TYPE& magFilter, Diligent::FILTER_TYPE& mipFilter) {
|
||||||
|
if (pname == GL_TEXTURE_COMPARE_MODE) {
|
||||||
|
bool compare = (param == GL_COMPARE_REF_TO_TEXTURE);
|
||||||
|
minFilter = ConvertCompareFilter(minFilter, compare);
|
||||||
|
magFilter = ConvertCompareFilter(magFilter, compare);
|
||||||
|
mipFilter = ConvertCompareFilter(mipFilter, compare);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Diligent::FILTER_TYPE* pFilter = nullptr;
|
||||||
|
if (pname == GL_TEXTURE_MIN_FILTER) {
|
||||||
|
pFilter = &minFilter;
|
||||||
|
} else if (pname == GL_TEXTURE_MAG_FILTER) {
|
||||||
|
pFilter = &magFilter;
|
||||||
|
} else {
|
||||||
|
MG_Util::Debug::LogD("FillFilterTypeFromGLEnum: not allowed pname!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Diligent::FILTER_TYPE& filter = *pFilter;
|
||||||
|
|
||||||
|
bool filterIsCompare = IsCompareFilter(filter);
|
||||||
|
bool mipFilterIsCompare = IsCompareFilter(mipFilter);
|
||||||
|
|
||||||
|
switch (param) {
|
||||||
|
case GL_NEAREST:
|
||||||
|
filter = Diligent::FILTER_TYPE_POINT;
|
||||||
|
if (pname == GL_TEXTURE_MIN_FILTER)
|
||||||
|
mipFilter = Diligent::FILTER_TYPE_POINT;
|
||||||
|
break;
|
||||||
|
case GL_LINEAR:
|
||||||
|
filter = Diligent::FILTER_TYPE_LINEAR;
|
||||||
|
if (pname == GL_TEXTURE_MIN_FILTER)
|
||||||
|
mipFilter = Diligent::FILTER_TYPE_POINT;
|
||||||
|
break;
|
||||||
|
case GL_NEAREST_MIPMAP_NEAREST:
|
||||||
|
filter = Diligent::FILTER_TYPE_POINT;
|
||||||
|
mipFilter = Diligent::FILTER_TYPE_POINT;
|
||||||
|
break;
|
||||||
|
case GL_LINEAR_MIPMAP_NEAREST:
|
||||||
|
filter = Diligent::FILTER_TYPE_LINEAR;
|
||||||
|
mipFilter = Diligent::FILTER_TYPE_POINT;
|
||||||
|
break;
|
||||||
|
case GL_NEAREST_MIPMAP_LINEAR:
|
||||||
|
filter = Diligent::FILTER_TYPE_POINT;
|
||||||
|
mipFilter = Diligent::FILTER_TYPE_LINEAR;
|
||||||
|
break;
|
||||||
|
case GL_LINEAR_MIPMAP_LINEAR:
|
||||||
|
filter = Diligent::FILTER_TYPE_LINEAR;
|
||||||
|
mipFilter = Diligent::FILTER_TYPE_LINEAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = ConvertCompareFilter(filter, filterIsCompare);
|
||||||
|
mipFilter = ConvertCompareFilter(mipFilter, mipFilterIsCompare);
|
||||||
|
}
|
||||||
|
|
||||||
|
Diligent::COMPARISON_FUNCTION ConvertComparsionFunc(GLint param) {
|
||||||
|
switch (param) {
|
||||||
|
case GL_LEQUAL: return Diligent::COMPARISON_FUNC_LESS_EQUAL;
|
||||||
|
case GL_GEQUAL: return Diligent::COMPARISON_FUNC_GREATER_EQUAL;
|
||||||
|
case GL_LESS: return Diligent::COMPARISON_FUNC_LESS;
|
||||||
|
case GL_GREATER: return Diligent::COMPARISON_FUNC_GREATER;
|
||||||
|
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:
|
||||||
|
MG_Util::Debug::LogE("%s: not handled param: %s", __func__, MG_Util::Debug::GLEnumToString(param));
|
||||||
|
return Diligent::COMPARISON_FUNC_NEVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
MG_Util::Debug::LogE("%s: not handled param: %s", __func__, MG_Util::Debug::GLEnumToString(param));
|
||||||
|
return Diligent::TEXTURE_ADDRESS_WRAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ActiveTexture(GLenum texture) {
|
void ActiveTexture(GLenum texture) {
|
||||||
MG_Util::Debug::LogD("glActiveTexture, texture: %d", texture);
|
MG_Util::Debug::LogD("glActiveTexture, texture: %d", texture);
|
||||||
GLenum result = MG_State::BindTextureUnit(texture);
|
GLenum result = MG_State::BindTextureUnit(texture);
|
||||||
@@ -17,8 +195,9 @@ namespace MG_GL::GL {
|
|||||||
void BindTexture(GLenum target, GLuint texture) {
|
void BindTexture(GLenum target, GLuint texture) {
|
||||||
MG_Util::Debug::LogD("glBindTexture, target: %d, texture: %d", target, texture);
|
MG_Util::Debug::LogD("glBindTexture, target: %d, texture: %d", target, texture);
|
||||||
GLenum result = MG_State::BindTexture(target, texture);
|
GLenum result = MG_State::BindTexture(target, texture);
|
||||||
if (result == GL_NO_ERROR)
|
if (result == GL_NO_ERROR) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -26,8 +205,27 @@ namespace MG_GL::GL {
|
|||||||
void DeleteTextures(GLsizei n, const GLuint* textures) {
|
void DeleteTextures(GLsizei n, const GLuint* textures) {
|
||||||
MG_Util::Debug::LogD("glDeleteTextures, n: %d, textures: %p", n, textures);
|
MG_Util::Debug::LogD("glDeleteTextures, n: %d, textures: %p", n, textures);
|
||||||
GLenum result = MG_State::DeleteTextures(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;
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
@@ -35,52 +233,453 @@ namespace MG_GL::GL {
|
|||||||
void GenTextures(GLsizei n, GLuint* textures) {
|
void GenTextures(GLsizei n, GLuint* textures) {
|
||||||
MG_Util::Debug::LogD("glGenTextures, n: %d, textures: %p", n, textures);
|
MG_Util::Debug::LogD("glGenTextures, n: %d, textures: %p", n, textures);
|
||||||
GLenum result = MG_State::CreateTextures(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;
|
return;
|
||||||
|
}
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Diligent::Uint32 CalculateMipLevels(GLsizei width, GLsizei height) {
|
||||||
|
Diligent::Uint32 levels = 1;
|
||||||
|
GLsizei size = std::max(width, height);
|
||||||
|
|
||||||
|
while (size > 1) {
|
||||||
|
size >>= 1;
|
||||||
|
levels++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return levels;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
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",
|
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);
|
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;
|
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);
|
||||||
|
if (texIt != MG_Diligent::g_TextureMap.end()) {
|
||||||
|
pTexture = texIt->second;
|
||||||
|
}
|
||||||
|
auto srvIt = MG_Diligent::g_TextureViewMap.find(boundTextureID);
|
||||||
|
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;
|
||||||
|
bool isBaseLevel = (level == 0);
|
||||||
|
|
||||||
|
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 (isBaseLevel &&
|
||||||
|
(existingDesc.Width != static_cast<Diligent::Uint32>(width) ||
|
||||||
|
existingDesc.Height != static_cast<Diligent::Uint32>(height) ||
|
||||||
|
existingDesc.Format != newFormat)) {
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("TexImage2D: Base level 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);
|
||||||
|
|
||||||
|
needCreateTexture = true;
|
||||||
|
} else if (level >= static_cast<GLint>(existingDesc.MipLevels)) {
|
||||||
|
MG_Util::Debug::LogD("TexImage2D: Level %d exceeds current mip levels (%d). Recreating texture.",
|
||||||
|
level, existingDesc.MipLevels);
|
||||||
|
needCreateTexture = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needCreateTexture) {
|
||||||
|
if (pSRV) {
|
||||||
|
MG_Util::Debug::LogD("TexImage2D: Releasing existing SRV %p", (void*)pSRV);
|
||||||
|
pSRV->Release();
|
||||||
|
MG_Diligent::g_TextureViewMap[boundTextureID] = nullptr;
|
||||||
|
pSRV = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTexture) {
|
||||||
|
MG_Util::Debug::LogD("TexImage2D: Releasing existing texture %p", (void*)pTexture);
|
||||||
|
pTexture->Release();
|
||||||
|
MG_Diligent::g_TextureMap[boundTextureID] = nullptr;
|
||||||
|
pTexture = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Diligent::Uint32 mipLevels = 1;
|
||||||
|
if (isBaseLevel) {
|
||||||
|
mipLevels = CalculateMipLevels(width, height);
|
||||||
|
} else if (pTexture) {
|
||||||
|
mipLevels = pTexture->GetDesc().MipLevels;
|
||||||
|
}
|
||||||
|
|
||||||
|
Diligent::TextureDesc TexDesc;
|
||||||
|
if constexpr (MG_Global::Common::LogLevel <= MG_Constants::Common::LOG_LEVEL_DEBUG) {
|
||||||
|
TexDesc.Name = std::format("GL Texture {}", boundTextureID).c_str();
|
||||||
|
}
|
||||||
|
TexDesc.Type = Diligent::RESOURCE_DIM_TEX_2D;
|
||||||
|
TexDesc.Width = width;
|
||||||
|
TexDesc.Height = height;
|
||||||
|
TexDesc.Format = newFormat;
|
||||||
|
TexDesc.MipLevels = mipLevels;
|
||||||
|
|
||||||
|
bool isDepthStencil = false;
|
||||||
|
switch (internalFormat) {
|
||||||
|
case GL_DEPTH_COMPONENT:
|
||||||
|
case GL_DEPTH_COMPONENT16:
|
||||||
|
case GL_DEPTH_COMPONENT24:
|
||||||
|
case GL_DEPTH_COMPONENT32:
|
||||||
|
case GL_DEPTH_COMPONENT32F:
|
||||||
|
case GL_DEPTH_STENCIL:
|
||||||
|
case GL_DEPTH24_STENCIL8:
|
||||||
|
case GL_DEPTH32F_STENCIL8:
|
||||||
|
isDepthStencil = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
isDepthStencil = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDepthStencil) {
|
||||||
|
TexDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE | Diligent::BIND_DEPTH_STENCIL;
|
||||||
|
} else {
|
||||||
|
TexDesc.BindFlags = Diligent::BIND_SHADER_RESOURCE | Diligent::BIND_RENDER_TARGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("TexImage2D: Creating new Diligent texture with Width: %d, Height: %d, Format: %d, MipLevels: %u",
|
||||||
|
width, height, newFormat, mipLevels);
|
||||||
|
|
||||||
|
Diligent::ITexture* newTexture = nullptr;
|
||||||
|
MG_Diligent::g_pDevice->CreateTexture(TexDesc, nullptr, &newTexture);
|
||||||
|
|
||||||
|
if (newTexture) {
|
||||||
|
MG_Util::Debug::LogD("TexImage2D: Created new Diligent texture %p for GL name %u.",
|
||||||
|
(void*)newTexture, boundTextureID);
|
||||||
|
|
||||||
|
Diligent::TextureViewDesc SRVDesc;
|
||||||
|
SRVDesc.ViewType = Diligent::TEXTURE_VIEW_SHADER_RESOURCE;
|
||||||
|
SRVDesc.TextureDim = Diligent::RESOURCE_DIM_TEX_2D;
|
||||||
|
SRVDesc.MostDetailedMip = 0;
|
||||||
|
SRVDesc.NumMipLevels = TexDesc.MipLevels;
|
||||||
|
|
||||||
|
Diligent::ITextureView* newSRV = nullptr;
|
||||||
|
newTexture->CreateView(SRVDesc, &newSRV);
|
||||||
|
MG_Util::Debug::LogD("TexImage2D: Created new SRV %p for texture.", (void*)newSRV);
|
||||||
|
|
||||||
|
MG_Diligent::g_TextureMap[boundTextureID] = newTexture;
|
||||||
|
MG_Diligent::g_TextureViewMap[boundTextureID] = newSRV;
|
||||||
|
|
||||||
|
pTexture = newTexture;
|
||||||
|
pSRV = newSRV;
|
||||||
|
} else {
|
||||||
|
MG_Util::Debug::LogE("TexImage2D: Failed to create new texture!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
UpdateBox.MinZ = 0;
|
||||||
|
UpdateBox.MaxZ = 1;
|
||||||
|
|
||||||
|
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 for level %d.", level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
|
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
|
||||||
MG_Util::Debug::LogD("glTexParameterf, target: %d, pname: %d, param: %f", target, pname, param);
|
MG_Util::Debug::LogD("glTexParameterf, target: %d, pname: %d, param: %f", target, pname, param);
|
||||||
GLenum result = MG_State::SetTexturePropertyFloat(target, pname, param);
|
GLenum result = MG_State::SetTexturePropertyFloat(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;
|
return;
|
||||||
MG_State::SetError(result);
|
}
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
|
||||||
|
// TODO: Fix sampler
|
||||||
|
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("TexParameterf: 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:
|
||||||
|
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_MAG_FILTER:
|
||||||
|
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
|
||||||
|
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;
|
||||||
|
case GL_TEXTURE_MIN_LOD:
|
||||||
|
SamDesc.MinLOD = (float)param;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_MAX_LOD:
|
||||||
|
SamDesc.MaxLOD = param;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_COMPARE_FUNC:
|
||||||
|
SamDesc.ComparisonFunc = ConvertComparsionFunc(param);
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_COMPARE_MODE:
|
||||||
|
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MG_Util::Debug::LogE("%s: not handled pname: %s", __func__, MG_Util::Debug::GLEnumToString(pname));
|
||||||
|
}
|
||||||
|
|
||||||
|
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("TexParameterf: Updated sampler for texture %u", boundTextureID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TexParameteri(GLenum target, GLenum pname, GLint param) {
|
void TexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||||
MG_Util::Debug::LogD("glTexParameteri, target: %d, pname: %d, param: %d", target, pname, param);
|
MG_Util::Debug::LogD("glTexParameteri, target: %d, pname: %d, param: %d", target, pname, param);
|
||||||
GLenum result = MG_State::SetTexturePropertyInt(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;
|
return;
|
||||||
MG_State::SetError(result);
|
}
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
|
||||||
|
// TODO: Fix sampler
|
||||||
|
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:
|
||||||
|
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_MAG_FILTER:
|
||||||
|
FillFilterTypeFromGLEnum(pname, param, SamDesc.MagFilter, SamDesc.MagFilter, SamDesc.MipFilter);
|
||||||
|
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;
|
||||||
|
case GL_TEXTURE_MIN_LOD:
|
||||||
|
SamDesc.MinLOD = (float)param;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_MAX_LOD:
|
||||||
|
SamDesc.MaxLOD = (float)param;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_COMPARE_FUNC:
|
||||||
|
SamDesc.ComparisonFunc = ConvertComparsionFunc(param);
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_COMPARE_MODE:
|
||||||
|
FillFilterTypeFromGLEnum(pname, param, SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MG_Util::Debug::LogE("%s: not handled pname: %s", __func__, MG_Util::Debug::GLEnumToString(pname));
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
|
||||||
GLsizei height, GLenum format, GLenum type, const void* pixels) {
|
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",
|
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);
|
target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||||
|
|
||||||
GLenum result = MG_State::UpdateTextureRegion2D(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;
|
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);
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("TexSubImage2D: bound texture: GL name %u", boundTextureID);
|
||||||
|
|
||||||
|
if (boundTextureID == 0) {
|
||||||
|
MG_Util::Debug::LogD("TexSubImage2D: No texture bound to active unit. Skipping update.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Diligent::ITexture* pTexture = nullptr;
|
||||||
|
auto texIt = MG_Diligent::g_TextureMap.find(boundTextureID);
|
||||||
|
if (texIt != MG_Diligent::g_TextureMap.end()) {
|
||||||
|
pTexture = texIt->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pTexture) {
|
||||||
|
MG_Util::Debug::LogW("TexSubImage2D: Diligent texture not found for GL name %u", boundTextureID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& texDesc = pTexture->GetDesc();
|
||||||
|
if (!(texDesc.BindFlags & Diligent::BIND_SHADER_RESOURCE)) {
|
||||||
|
MG_Util::Debug::LogE("TexSubImage2D: Texture %u does not have BIND_SHADER_RESOURCE flag", boundTextureID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rowLength = MG_State::QueryPixelStoreInt(GL_UNPACK_ROW_LENGTH);
|
||||||
|
rowLength = ((rowLength > 0) ? rowLength : width);
|
||||||
|
auto skipRows = MG_State::QueryPixelStoreInt(GL_UNPACK_SKIP_ROWS);
|
||||||
|
auto skipPixels = MG_State::QueryPixelStoreInt(GL_UNPACK_SKIP_PIXELS);
|
||||||
|
auto bpp = GetBytesPerPixel(format, type);
|
||||||
|
char* pixelStart = (char*)pixels + bpp * (rowLength * skipRows + skipPixels);
|
||||||
|
|
||||||
|
Diligent::TextureSubResData SubResData;
|
||||||
|
SubResData.Stride = rowLength * bpp;
|
||||||
|
SubResData.pData = pixelStart;
|
||||||
|
|
||||||
|
Diligent::Box UpdateBox;
|
||||||
|
UpdateBox.MinX = xoffset;
|
||||||
|
UpdateBox.MaxX = xoffset + width;
|
||||||
|
UpdateBox.MinY = yoffset;
|
||||||
|
UpdateBox.MaxY = yoffset + height;
|
||||||
|
UpdateBox.MinZ = 0;
|
||||||
|
UpdateBox.MaxZ = 1;
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("TexSubImage2D: Got GL_UNPACK_ROW_LENGTH = %d", rowLength);
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("TexSubImage2D: Updating region [%d,%d]-[%d,%d] at level %d, %d bytes",
|
||||||
|
xoffset, yoffset, xoffset+width, yoffset+height, level, width * height * GetBytesPerPixel(format, type));
|
||||||
|
|
||||||
|
// if (MG_Diligent::IsInRenderPass) {
|
||||||
|
// MG_Diligent::g_pContext->EndRenderPass();
|
||||||
|
// MG_Diligent::IsInRenderPass = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
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("TexSubImage2D: Update completed successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) {
|
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) {
|
||||||
MG_Util::Debug::LogD("glGetTexLevelParameteriv, target: %d, level: %d, pname: %d, params: %p",
|
MG_Util::Debug::LogD("glGetTexLevelParameteriv, target: %d, level: %d, pname: %d, params: %p",
|
||||||
target, level, pname, params);
|
target, level, pname, params);
|
||||||
@@ -90,4 +689,10 @@ namespace MG_GL::GL {
|
|||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||||
|
MG_Util::Debug::LogD("glCopyTexSubImage2D, target: %d, level: %d, xoffset: %d, yoffset: %d, x: %d, y: %d, width: %d, height: %d",
|
||||||
|
target, level, xoffset, yoffset, x, y, width, height);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_GL_TEXTURE_H
|
#ifndef MOBILEGL_GL_TEXTURE_H
|
||||||
#define MOBILEGL_GL_TEXTURE_H
|
#define MOBILEGL_GL_TEXTURE_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
void ActiveTexture(GLenum texture);
|
void ActiveTexture(GLenum texture);
|
||||||
void BindTexture(GLenum target, GLuint texture);
|
void BindTexture(GLenum target, GLuint texture);
|
||||||
@@ -17,6 +15,7 @@ namespace MG_GL::GL {
|
|||||||
void TexParameteri(GLenum target, GLenum pname, GLint param);
|
void TexParameteri(GLenum target, GLenum pname, GLint param);
|
||||||
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
|
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
|
||||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
|
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
|
||||||
|
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //MOBILEGL_GL_TEXTURE_H
|
#endif //MOBILEGL_GL_TEXTURE_H
|
||||||
|
|||||||
@@ -2,13 +2,15 @@
|
|||||||
// Created by BZLZHH on 2025/3/15.
|
// Created by BZLZHH on 2025/3/15.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GL_VertexArray.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
void GenVertexArrays(GLsizei n, GLuint* arrays) {
|
void GenVertexArrays(GLsizei n, GLuint* arrays) {
|
||||||
MG_Util::Debug::LogD("glGenVertexArrays, n: %d, arrays: %p", n, arrays);
|
MG_Util::Debug::LogD("glGenVertexArrays, n: %d, arrays: %p", n, arrays);
|
||||||
GLenum result = MG_State::GenVertexArraysNames(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_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_GL_VERTEXARRAY_H
|
#ifndef MOBILEGL_GL_VERTEXARRAY_H
|
||||||
#define MOBILEGL_GL_VERTEXARRAY_H
|
#define MOBILEGL_GL_VERTEXARRAY_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
void GenVertexArrays(GLsizei n, GLuint* arrays);
|
void GenVertexArrays(GLsizei n, GLuint* arrays);
|
||||||
void BindVertexArray(GLuint array);
|
void BindVertexArray(GLuint array);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by Swung 0x48 on 2025/6/20.
|
// Created by Swung 0x48 on 2025/6/20.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GLXFuncsDefinitions.h"
|
#include "../../../../Includes.h"
|
||||||
|
|
||||||
MG_EXPORT void* glXGetProcAddress(const char *name) {
|
MG_EXPORT void* glXGetProcAddress(const char *name) {
|
||||||
return MG_GL::GLX::GetProcAddress(name);
|
return MG_GL::GLX::GetProcAddress(name);
|
||||||
|
|||||||
@@ -5,6 +5,4 @@
|
|||||||
#ifndef MOBILEGL_GLX_FUNCS_DEFINITIONS_H
|
#ifndef MOBILEGL_GLX_FUNCS_DEFINITIONS_H
|
||||||
#define MOBILEGL_GLX_FUNCS_DEFINITIONS_H
|
#define MOBILEGL_GLX_FUNCS_DEFINITIONS_H
|
||||||
|
|
||||||
#include "../../../../Includes.h"
|
|
||||||
|
|
||||||
#endif //MOBILEGL_GLX_FUNCS_DEFINITIONS_H
|
#endif //MOBILEGL_GLX_FUNCS_DEFINITIONS_H
|
||||||
|
|||||||
@@ -4,38 +4,33 @@
|
|||||||
|
|
||||||
// TODO: Add more gl error check for buffer state manager.
|
// TODO: Add more gl error check for buffer state manager.
|
||||||
|
|
||||||
#include "BufferState.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
GLenum BufferState::GenName(GLuint *buffer) {
|
//GLenum BufferState::GenName(GLuint *buffer) {
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: GenName");
|
// MG_Util::Debug::LogD("MG_State: Buffer: GenName");
|
||||||
if (!buffer)
|
// if (!buffer)
|
||||||
return GL_INVALID_VALUE;
|
// return GL_INVALID_VALUE;
|
||||||
|
//
|
||||||
GLuint id = 0;
|
// GLuint id = 0;
|
||||||
if (freeId_.empty()) {
|
// if (freeId_.empty()) {
|
||||||
id = lastId_++;
|
// id = lastId_++;
|
||||||
} else {
|
// } else {
|
||||||
id = freeId_.back();
|
// id = freeId_.back();
|
||||||
freeId_.pop_back();
|
// freeId_.pop_back();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
*buffer = id;
|
// *buffer = id;
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: Gen new name %d", id);
|
// MG_Util::Debug::LogD("MG_State: Buffer: Gen new name %d", id);
|
||||||
|
//
|
||||||
return GL_NO_ERROR;
|
// return GL_NO_ERROR;
|
||||||
}
|
//}
|
||||||
|
|
||||||
GLenum BufferState::GenNameN(GLsizei n, GLuint* buffers) {
|
GLenum BufferState::GenNameN(GLsizei n, GLuint* buffers) {
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN called with n=%d", n);
|
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN called with n=%d", n);
|
||||||
if (n < 0) return GL_INVALID_VALUE;
|
if (n < 0 || buffers == nullptr) return GL_INVALID_VALUE;
|
||||||
|
|
||||||
|
indexGenerator_.Generate(n, buffers);
|
||||||
|
|
||||||
for (GLsizei i = 0; i < n; ++i) {
|
|
||||||
GLenum result = GenName(&buffers[i]);
|
|
||||||
if (result != GL_NO_ERROR) {
|
|
||||||
MG_Util::Debug::LogE("MG_State: Buffer: GenNameN failed with error 0x%x", result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN created buffers successfully");
|
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN created buffers successfully");
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -48,7 +43,14 @@ GLenum BufferState::Create(GLuint buffer) {
|
|||||||
if (ValidateAllocatedHandle(buffer))
|
if (ValidateAllocatedHandle(buffer))
|
||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
|
|
||||||
BufferObject& obj = buffers_[buffer];
|
if (bufferObjects_.size() <= buffer) {
|
||||||
|
bufferObjects_.resize(buffer + 1);
|
||||||
|
}
|
||||||
|
if (bufferObjects_[buffer] == nullptr) {
|
||||||
|
bufferObjects_[buffer] = std::make_unique<BufferObject>();
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferObject& obj = *GetBufferObject(buffer);
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", buffer);
|
MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", buffer);
|
||||||
obj.generated = true;
|
obj.generated = true;
|
||||||
obj.dirty = true;
|
obj.dirty = true;
|
||||||
@@ -71,9 +73,12 @@ GLenum BufferState::CommitStorage(GLenum target, GLsizeiptr size, const void* da
|
|||||||
if (it == currentBindings_.end() || it->second == 0)
|
if (it == currentBindings_.end() || it->second == 0)
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
|
|
||||||
BufferObject& obj = buffers_[it->second];
|
BufferObject& obj = *GetBufferObject(it->second);
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage get buffer object %u at target 0x%x",it->second,target);
|
MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage get buffer object %u at target 0x%x",it->second,target);
|
||||||
obj.usage = usage;
|
obj.usage = usage;
|
||||||
|
obj.isDynamic = (usage == GL_DYNAMIC_DRAW || usage == GL_DYNAMIC_READ ||
|
||||||
|
usage == GL_DYNAMIC_COPY || usage == GL_STREAM_DRAW);
|
||||||
|
obj.data.reserve(std::bit_ceil((size_t)size));
|
||||||
obj.data.resize(size);
|
obj.data.resize(size);
|
||||||
if (data) {
|
if (data) {
|
||||||
memcpy(obj.data.data(), data, size);
|
memcpy(obj.data.data(), data, size);
|
||||||
@@ -94,7 +99,7 @@ GLenum BufferState::CommitStorageRegion(GLenum target, GLintptr offset, GLsizeip
|
|||||||
if (it == currentBindings_.end() || it->second == 0)
|
if (it == currentBindings_.end() || it->second == 0)
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
|
|
||||||
BufferObject& obj = buffers_[it->second];
|
BufferObject& obj = *GetBufferObject(it->second);
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: BufferSubData get buffer object %u at target 0x%x", it->second, target);
|
MG_Util::Debug::LogD("MG_State: Buffer: BufferSubData get buffer object %u at target 0x%x", it->second, target);
|
||||||
|
|
||||||
if (static_cast<size_t>(offset + size) > obj.data.size()) return GL_INVALID_VALUE;
|
if (static_cast<size_t>(offset + size) > obj.data.size()) return GL_INVALID_VALUE;
|
||||||
@@ -123,7 +128,7 @@ GLenum BufferState::AcquireBufferMemoryRange(GLenum target, GLintptr offset, GLs
|
|||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferObject& obj = buffers_[it->second];
|
BufferObject& obj = *GetBufferObject(it->second);
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemoryRange operating on buffer %u", it->second);
|
MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemoryRange operating on buffer %u", it->second);
|
||||||
if (obj.isMapped) {
|
if (obj.isMapped) {
|
||||||
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: buffer %u is already mapped", it->second);
|
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: buffer %u is already mapped", it->second);
|
||||||
@@ -159,7 +164,7 @@ GLenum BufferState::SyncBufferMemory(GLenum target, GLintptr offset, GLsizeiptr
|
|||||||
if (it == currentBindings_.end() || it->second == 0)
|
if (it == currentBindings_.end() || it->second == 0)
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
|
|
||||||
BufferObject& obj = buffers_[it->second];
|
BufferObject& obj = *GetBufferObject(it->second);
|
||||||
if (!obj.isMapped || !(obj.mapAccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT))
|
if (!obj.isMapped || !(obj.mapAccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT))
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
|
|
||||||
@@ -183,8 +188,8 @@ GLenum BufferState::CopyBufferRange(GLenum readTarget, GLenum writeTarget, GLint
|
|||||||
if (readBuffer == 0 || writeBuffer == 0 || readBuffer == writeBuffer)
|
if (readBuffer == 0 || writeBuffer == 0 || readBuffer == writeBuffer)
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
|
|
||||||
BufferObject& src = buffers_[readBuffer];
|
BufferObject& src = *GetBufferObject(readBuffer);
|
||||||
BufferObject& dst = buffers_[writeBuffer];
|
BufferObject& dst = *GetBufferObject(writeBuffer);
|
||||||
|
|
||||||
if (static_cast<size_t>(readOffset + size) > src.data.size() ||
|
if (static_cast<size_t>(readOffset + size) > src.data.size() ||
|
||||||
static_cast<size_t>(writeOffset + size) > dst.data.size())
|
static_cast<size_t>(writeOffset + size) > dst.data.size())
|
||||||
@@ -204,7 +209,7 @@ GLenum BufferState::AcquireBufferMemory(GLenum target, GLenum access, void** map
|
|||||||
default:
|
default:
|
||||||
flags = access;
|
flags = access;
|
||||||
}
|
}
|
||||||
return AcquireBufferMemoryRange(target, 0, buffers_[currentBindings_[target]].data.size(), flags, mappedPointer);
|
return AcquireBufferMemoryRange(target, 0, GetBufferObject(currentBindings_[target])->data.size(), flags, mappedPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum BufferState::ReleaseBufferMemory(GLenum target) {
|
GLenum BufferState::ReleaseBufferMemory(GLenum target) {
|
||||||
@@ -215,7 +220,7 @@ GLenum BufferState::ReleaseBufferMemory(GLenum target) {
|
|||||||
if (it == currentBindings_.end() || it->second == 0)
|
if (it == currentBindings_.end() || it->second == 0)
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
|
|
||||||
BufferObject& obj = buffers_[it->second];
|
BufferObject& obj = *GetBufferObject(it->second);
|
||||||
if (!obj.isMapped)
|
if (!obj.isMapped)
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
|
|
||||||
@@ -232,28 +237,28 @@ GLenum BufferState::ReleaseBufferMemory(GLenum target) {
|
|||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferState::ValidateAllocatedHandle(GLuint buffer) {
|
bool BufferState::ValidateAllocatedHandle(GLuint buffer) const {
|
||||||
bool isValid = buffers_.find(buffer) != buffers_.end();
|
bool isValid = buffer != 0 && bufferObjects_.size() > buffer && bufferObjects_[buffer] != nullptr;
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, isValid);
|
MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, isValid);
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferState::ValidateGeneratedName(GLuint buffer) {
|
bool BufferState::ValidateGeneratedName(GLuint buffer) const {
|
||||||
bool inFreeList = std::find(freeId_.begin(), freeId_.end(), buffer) != freeId_.end();
|
bool isValid = indexGenerator_.IsValid(buffer);
|
||||||
bool lessThanLast = buffer < lastId_; // lastId_ is not generated yet
|
MG_Util::Debug::LogD("MG_State: Buffer: ValidateGeneratedName called on buffer %u returns %s", buffer, isValid ? "true" : "false");
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: ValidateGeneratedName called on buffer %u returns %d", buffer, lessThanLast && !inFreeList);
|
return isValid;
|
||||||
return lessThanLast && !inFreeList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferState::Delete(GLuint buffer) {
|
void BufferState::Delete(GLuint buffer) {
|
||||||
buffers_.erase(buffer);
|
MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer);
|
||||||
if (ValidateGeneratedName(buffer))
|
if (bufferObjects_.size() > buffer)
|
||||||
// TODO: Prevent the object that uses a freeId from conflicting with legacy object in the backend.
|
bufferObjects_[buffer].reset();
|
||||||
//freeId_.emplace_back(buffer);
|
indexGenerator_.Delete(buffer);
|
||||||
|
|
||||||
for (auto& [target, id] : currentBindings_) {
|
for (auto& [target, id] : currentBindings_) {
|
||||||
if (id == buffer) id = 0;
|
if (id == buffer) id = 0;
|
||||||
}
|
}
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer);
|
MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u successfully", buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum BufferState::DeleteN(GLsizei n, const GLuint* buffers) {
|
GLenum BufferState::DeleteN(GLsizei n, const GLuint* buffers) {
|
||||||
@@ -268,8 +273,9 @@ GLenum BufferState::DeleteN(GLsizei n, const GLuint* buffers) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BufferState::IsValidTarget_(GLenum target) {
|
bool BufferState::IsValidTarget_(GLenum target) {
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: IsValidTarget_ called with target=0x%x,result=%d", target, !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end()));
|
bool ret = MG_Constants::Common::Contains(target, MG_Constants::Buffer::VALID_TARGETS);
|
||||||
return !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end());
|
MG_Util::Debug::LogD("MG_State: Buffer: IsValidTarget_ called with target=0x%x,result=%d", target, ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const {
|
GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const {
|
||||||
@@ -282,7 +288,7 @@ GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* p
|
|||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Buffer::VALID_PARAM_NAMES.find(pname) == MG_Constants::Buffer::VALID_PARAM_NAMES.end()) {
|
if (!MG_Constants::Common::Contains(pname, MG_Constants::Buffer::VALID_PARAM_NAMES)) {
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,12 +297,12 @@ GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* p
|
|||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
GLuint bufferId = bindingIt->second;
|
GLuint bufferId = bindingIt->second;
|
||||||
auto bufferIt = buffers_.find(bufferId);
|
|
||||||
if (bufferIt == buffers_.end()) {
|
if (!ValidateAllocatedHandle(bufferId)) {
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BufferObject& buffer = bufferIt->second;
|
const BufferObject& buffer = *bufferObjects_[bufferId];
|
||||||
|
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_BUFFER_ACCESS:
|
case GL_BUFFER_ACCESS:
|
||||||
@@ -326,3 +332,14 @@ GLuint BufferState::GetCurrentBinding(GLenum target) const {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BufferState::BufferObject* BufferState::GetBufferObject(GLuint buffer) {
|
||||||
|
if (bufferObjects_.size() <= buffer) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
// if (bufferObjects_[buffer] == nullptr) {
|
||||||
|
// raise(SIGTRAP);
|
||||||
|
//// bufferObjects_[buffer] = std::make_unique<BufferObject>();
|
||||||
|
// }
|
||||||
|
return bufferObjects_[buffer].get();
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,14 +4,8 @@
|
|||||||
|
|
||||||
#ifndef MOBILEGL_BUFFERSTATE_H
|
#ifndef MOBILEGL_BUFFERSTATE_H
|
||||||
#define MOBILEGL_BUFFERSTATE_H
|
#define MOBILEGL_BUFFERSTATE_H
|
||||||
#define MOBILEGL_GLSTATE_H
|
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
class BufferState {
|
class BufferState {
|
||||||
template <typename K, typename V>
|
|
||||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct BufferObject {
|
struct BufferObject {
|
||||||
GLenum usage = GL_STATIC_DRAW;
|
GLenum usage = GL_STATIC_DRAW;
|
||||||
@@ -20,6 +14,7 @@ public:
|
|||||||
bool dirty = false; // TODO: encapsulate this with an public API to RHI
|
bool dirty = false; // TODO: encapsulate this with an public API to RHI
|
||||||
bool isMapped = false;
|
bool isMapped = false;
|
||||||
bool generated = false;
|
bool generated = false;
|
||||||
|
bool isDynamic = false;
|
||||||
GLenum accessMode = GL_READ_WRITE;
|
GLenum accessMode = GL_READ_WRITE;
|
||||||
GLintptr mapOffset = 0;
|
GLintptr mapOffset = 0;
|
||||||
GLsizeiptr mapLength = 0;
|
GLsizeiptr mapLength = 0;
|
||||||
@@ -27,7 +22,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Return: the validity of the operation, according to OpenGL 3 standard
|
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||||
GLenum GenName(GLuint* buffer);
|
// GLenum GenName(GLuint* buffer);
|
||||||
GLenum GenNameN(GLsizei n, GLuint* buffers);
|
GLenum GenNameN(GLsizei n, GLuint* buffers);
|
||||||
GLenum Create(GLuint buffer);
|
GLenum Create(GLuint buffer);
|
||||||
GLenum Bind(GLenum target, GLuint buffer);
|
GLenum Bind(GLenum target, GLuint buffer);
|
||||||
@@ -41,16 +36,20 @@ public:
|
|||||||
GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const;
|
GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const;
|
||||||
GLenum DeleteN(GLsizei n, const GLuint* buffers);
|
GLenum DeleteN(GLsizei n, const GLuint* buffers);
|
||||||
|
|
||||||
bool ValidateAllocatedHandle(GLuint buffer);
|
bool ValidateAllocatedHandle(GLuint buffer) const;
|
||||||
bool ValidateGeneratedName(GLuint buffer);
|
bool ValidateGeneratedName(GLuint buffer) const;
|
||||||
void Delete(GLuint buffer);
|
void Delete(GLuint buffer);
|
||||||
GLuint GetCurrentBinding(GLenum target) const;
|
GLuint GetCurrentBinding(GLenum target) const;
|
||||||
|
|
||||||
unordered_map<GLenum, GLuint> currentBindings_;
|
BufferObject* GetBufferObject(GLuint buffer);
|
||||||
unordered_map<GLuint, BufferObject> buffers_;
|
|
||||||
|
MG_Global::unordered_map<GLenum, GLuint> currentBindings_;
|
||||||
|
// MG_Global::unordered_map<GLuint, BufferObject> buffers_;
|
||||||
private:
|
private:
|
||||||
std::vector<GLuint> freeId_;
|
// std::vector<GLuint> freeId_;
|
||||||
GLuint lastId_ = 1;
|
// GLuint lastId_ = 1;
|
||||||
|
IndexGenerator<GLuint> indexGenerator_;
|
||||||
|
std::vector<std::unique_ptr<BufferObject>> bufferObjects_;
|
||||||
|
|
||||||
static bool IsValidTarget_(GLenum target);
|
static bool IsValidTarget_(GLenum target);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/4/30.
|
// Created by BZLZHH on 2025/4/30.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "CommonState.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
CommonState::CommonState() {
|
CommonState::CommonState() {
|
||||||
pixelStoreParams[GL_PACK_ALIGNMENT] = 4;
|
pixelStoreParams[GL_PACK_ALIGNMENT] = 4;
|
||||||
@@ -10,7 +10,7 @@ CommonState::CommonState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLenum CommonState::SetPixelStoreInt(GLenum pname, GLint param) {
|
GLenum CommonState::SetPixelStoreInt(GLenum pname, GLint param) {
|
||||||
if (MG_Constants::PixelStore::VALID_PARAM_NAMES.find(pname) == MG_Constants::PixelStore::VALID_PARAM_NAMES.end()) {
|
if (!MG_Constants::Common::Contains(pname, MG_Constants::PixelStore::VALID_PARAM_NAMES)) {
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ GLint CommonState::QueryPixelStoreInt(GLenum pname) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLenum CommonState::Enable(GLenum cap) {
|
GLenum CommonState::Enable(GLenum cap) {
|
||||||
if (MG_Constants::CommonState::VALID_CAPS.find(cap) == MG_Constants::CommonState::VALID_CAPS.end()) {
|
if (!MG_Constants::Common::Contains(cap, MG_Constants::CommonState::VALID_CAPS)) {
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
capabilities[cap] = true;
|
capabilities[cap] = true;
|
||||||
@@ -69,7 +69,7 @@ GLenum CommonState::Enable(GLenum cap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLenum CommonState::Disable(GLenum cap) {
|
GLenum CommonState::Disable(GLenum cap) {
|
||||||
if (MG_Constants::CommonState::VALID_CAPS.find(cap) == MG_Constants::CommonState::VALID_CAPS.end()) {
|
if (!MG_Constants::Common::Contains(cap, MG_Constants::CommonState::VALID_CAPS)) {
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
capabilities[cap] = false;
|
capabilities[cap] = false;
|
||||||
@@ -77,8 +77,8 @@ GLenum CommonState::Disable(GLenum cap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLenum CommonState::BlendFunc(GLenum sfactor, GLenum dfactor) {
|
GLenum CommonState::BlendFunc(GLenum sfactor, GLenum dfactor) {
|
||||||
if (MG_Constants::Blend::VALID_FACTORS.find(sfactor) == MG_Constants::Blend::VALID_FACTORS.end() ||
|
if (!MG_Constants::Common::Contains(sfactor, MG_Constants::Blend::VALID_FACTORS) ||
|
||||||
MG_Constants::Blend::VALID_FACTORS.find(dfactor) == MG_Constants::Blend::VALID_FACTORS.end()) {
|
!MG_Constants::Common::Contains(dfactor, MG_Constants::Blend::VALID_FACTORS)) {
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +89,10 @@ GLenum CommonState::BlendFunc(GLenum sfactor, GLenum dfactor) {
|
|||||||
|
|
||||||
GLenum CommonState::BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
|
GLenum CommonState::BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
|
||||||
GLenum srcAlpha, GLenum dstAlpha) {
|
GLenum srcAlpha, GLenum dstAlpha) {
|
||||||
if (MG_Constants::Blend::VALID_FACTORS.find(srcRGB) == MG_Constants::Blend::VALID_FACTORS.end() ||
|
if (!MG_Constants::Common::Contains(srcRGB, MG_Constants::Blend::VALID_FACTORS) ||
|
||||||
MG_Constants::Blend::VALID_FACTORS.find(dstRGB) == MG_Constants::Blend::VALID_FACTORS.end() ||
|
!MG_Constants::Common::Contains(dstRGB, MG_Constants::Blend::VALID_FACTORS) ||
|
||||||
MG_Constants::Blend::VALID_FACTORS.find(srcAlpha) == MG_Constants::Blend::VALID_FACTORS.end() ||
|
!MG_Constants::Common::Contains(srcAlpha, MG_Constants::Blend::VALID_FACTORS) ||
|
||||||
MG_Constants::Blend::VALID_FACTORS.find(dstAlpha) == MG_Constants::Blend::VALID_FACTORS.end()) {
|
!MG_Constants::Common::Contains(dstAlpha, MG_Constants::Blend::VALID_FACTORS)) {
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
blendSrcRGB = srcRGB;
|
blendSrcRGB = srcRGB;
|
||||||
@@ -133,10 +133,11 @@ GLenum CommonState::ColorMask(GLboolean red, GLboolean green, GLboolean blue, GL
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLenum CommonState::DepthFunc(GLenum func) {
|
GLenum CommonState::DepthFunc(GLenum func) {
|
||||||
if (MG_Constants::Depth::VALID_FUNCS.find(func) == MG_Constants::Depth::VALID_FUNCS.end()) {
|
if (!MG_Constants::Common::Contains(func, MG_Constants::Depth::VALID_FUNCS)) {
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
depthFunc = func;
|
depthFunc = func;
|
||||||
|
MG_Util::Debug::LogD("%s(%s)", __func__, MG_Util::Debug::GLEnumToString(func));
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,8 @@
|
|||||||
|
|
||||||
#ifndef MOBILEGL_COMMONSTATE_H
|
#ifndef MOBILEGL_COMMONSTATE_H
|
||||||
#define MOBILEGL_COMMONSTATE_H
|
#define MOBILEGL_COMMONSTATE_H
|
||||||
#define MOBILEGL_GLSTATE_H
|
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
class CommonState {
|
class CommonState {
|
||||||
template <typename K, typename V>
|
|
||||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
|
||||||
public:
|
public:
|
||||||
// Viewport
|
// Viewport
|
||||||
GLint viewport[4] = {0, 0, 0, 0};
|
GLint viewport[4] = {0, 0, 0, 0};
|
||||||
@@ -19,7 +14,7 @@ public:
|
|||||||
GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
|
GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
|
||||||
|
|
||||||
// Pixel storage parameters
|
// Pixel storage parameters
|
||||||
unordered_map<GLenum, GLint> pixelStoreParams;
|
MG_Global::unordered_map<GLenum, GLint> pixelStoreParams;
|
||||||
|
|
||||||
// Blend state
|
// Blend state
|
||||||
GLenum blendSrcRGB = GL_ONE;
|
GLenum blendSrcRGB = GL_ONE;
|
||||||
@@ -37,7 +32,7 @@ public:
|
|||||||
GLboolean depthMask = GL_TRUE;
|
GLboolean depthMask = GL_TRUE;
|
||||||
|
|
||||||
// Capability enables
|
// Capability enables
|
||||||
unordered_map<GLenum, bool> capabilities;
|
MG_Global::unordered_map<GLenum, bool> capabilities;
|
||||||
|
|
||||||
CommonState();
|
CommonState();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/4/4.
|
// Created by BZLZHH on 2025/4/4.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GLState.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
std::queue<GLenum> MG_State_T::glErrorQueue;
|
std::queue<GLenum> MG_State_T::glErrorQueue;
|
||||||
TextureState* MG_State_T::textureState = nullptr;
|
TextureState* MG_State_T::textureState = nullptr;
|
||||||
@@ -298,12 +298,12 @@ namespace MG_State {
|
|||||||
return MG_State_T::programState->ActivateRenderProgram(program);
|
return MG_State_T::programState->ActivateRenderProgram(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name) {
|
GLenum DefineProgramAttributeLocation(GLuint program, GLuint index, const GLchar* name) {
|
||||||
return MG_State_T::programState->DefineProgramAttributeBinding(program, index, name);
|
return MG_State_T::programState->DefineProgramAttributeLocation(program, index, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint QueryProgramAttributeBinding(GLuint program, const GLchar* name) {
|
GLint QueryProgramAttributeLocation(GLuint program, const GLchar* name) {
|
||||||
return MG_State_T::programState->QueryProgramAttributeBinding(program, name);
|
return MG_State_T::programState->QueryProgramAttributeLocation(program, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name) {
|
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name) {
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_GLSTATE_H
|
#ifndef MOBILEGL_GLSTATE_H
|
||||||
#define MOBILEGL_GLSTATE_H
|
#define MOBILEGL_GLSTATE_H
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
struct MG_State_T {
|
struct MG_State_T {
|
||||||
static std::queue<GLenum> glErrorQueue;
|
static std::queue<GLenum> glErrorQueue;
|
||||||
static TextureState* textureState;
|
static TextureState* textureState;
|
||||||
@@ -95,8 +93,8 @@ namespace MG_State {
|
|||||||
GLenum BuildShaderStage(GLuint shader);
|
GLenum BuildShaderStage(GLuint shader);
|
||||||
GLenum FinalizeProgramPipeline(GLuint program);
|
GLenum FinalizeProgramPipeline(GLuint program);
|
||||||
GLenum ActivateRenderProgram(GLuint program);
|
GLenum ActivateRenderProgram(GLuint program);
|
||||||
GLenum DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name);
|
GLenum DefineProgramAttributeLocation(GLuint program, GLuint index, const GLchar* name);
|
||||||
GLint QueryProgramAttributeBinding(GLuint program, const GLchar* name);
|
GLint QueryProgramAttributeLocation(GLuint program, const GLchar* name);
|
||||||
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name);
|
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name);
|
||||||
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
|
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
|
||||||
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
|
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
|
||||||
|
|||||||
@@ -5,10 +5,6 @@
|
|||||||
// TODO: Add more gl error check for framebuffer state manager.
|
// TODO: Add more gl error check for framebuffer state manager.
|
||||||
// TODO: Check if the state machine really meets up to OpenGL 3 standard.
|
// TODO: Check if the state machine really meets up to OpenGL 3 standard.
|
||||||
|
|
||||||
#include "FramebufferState.h"
|
|
||||||
|
|
||||||
// Re-Include Includes.h, cuz of the absence of GLState.h
|
|
||||||
#undef MOBILEGL_GLSTATE_H
|
|
||||||
#include "../../../Includes.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
GLenum FramebufferState::Create(GLuint* framebuffer) {
|
GLenum FramebufferState::Create(GLuint* framebuffer) {
|
||||||
@@ -42,7 +38,7 @@ GLenum FramebufferState::Delete(GLuint framebuffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLenum FramebufferState::Bind(GLenum target, GLuint framebuffer) {
|
GLenum FramebufferState::Bind(GLenum target, GLuint framebuffer) {
|
||||||
if (MG_Constants::Framebuffer::VALID_TARGETS.find(target) == MG_Constants::Framebuffer::VALID_TARGETS.end())
|
if (!MG_Constants::Common::Contains(target, MG_Constants::Framebuffer::VALID_TARGETS))
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
if (framebuffer != 0 && !ValidateHandle(framebuffer))
|
if (framebuffer != 0 && !ValidateHandle(framebuffer))
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
@@ -57,10 +53,28 @@ GLenum FramebufferState::Bind(GLenum target, GLuint framebuffer) {
|
|||||||
|
|
||||||
GLenum FramebufferState::AttachTexture2D(GLenum target, GLenum attachment,
|
GLenum FramebufferState::AttachTexture2D(GLenum target, GLenum attachment,
|
||||||
GLenum textarget, GLuint texture, GLint level) {
|
GLenum textarget, GLuint texture, GLint level) {
|
||||||
if (MG_Constants::Framebuffer::VALID_ATTACHMENTS.find(attachment) == MG_Constants::Framebuffer::VALID_ATTACHMENTS.end() ||
|
if (!MG_Constants::Common::Contains(attachment, MG_Constants::Framebuffer::VALID_ATTACHMENTS) ||
|
||||||
MG_Constants::Texture::VALID_TARGETS.find(textarget) == MG_Constants::Texture::VALID_TARGETS.end())
|
!MG_Constants::Common::Contains(textarget, MG_Constants::Texture::VALID_TARGETS))
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER;
|
if (target == GL_FRAMEBUFFER) {
|
||||||
|
target = GL_DRAW_FRAMEBUFFER;
|
||||||
|
|
||||||
|
// if (currentBindings_[GL_READ_FRAMEBUFFER] == currentBindings_[GL_DRAW_FRAMEBUFFER]) {
|
||||||
|
// target = GL_DRAW_FRAMEBUFFER;
|
||||||
|
// } else {
|
||||||
|
// if (currentBindings_[GL_READ_FRAMEBUFFER] != 0) {
|
||||||
|
// GLenum err = AttachTexture2D(GL_READ_FRAMEBUFFER, attachment, textarget, texture, level);
|
||||||
|
// if (err != GL_NO_ERROR)
|
||||||
|
// return err;
|
||||||
|
// }
|
||||||
|
// if (currentBindings_[GL_DRAW_FRAMEBUFFER] != 0) {
|
||||||
|
// GLenum err = AttachTexture2D(GL_DRAW_FRAMEBUFFER, attachment, textarget, texture, level);
|
||||||
|
// if (err != GL_NO_ERROR)
|
||||||
|
// return err;
|
||||||
|
// }
|
||||||
|
// return GL_NO_ERROR;
|
||||||
|
// }
|
||||||
|
}
|
||||||
FramebufferObject* fbo = GetCurrentFBO(target);
|
FramebufferObject* fbo = GetCurrentFBO(target);
|
||||||
if (!fbo) return GL_INVALID_OPERATION;
|
if (!fbo) return GL_INVALID_OPERATION;
|
||||||
if (texture != 0 && !MG_State_T::textureState->IsTexture(texture))
|
if (texture != 0 && !MG_State_T::textureState->IsTexture(texture))
|
||||||
|
|||||||
@@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
#ifndef MOBILEGL_FRAMEBUFFERSTATE_H
|
#ifndef MOBILEGL_FRAMEBUFFERSTATE_H
|
||||||
#define MOBILEGL_FRAMEBUFFERSTATE_H
|
#define MOBILEGL_FRAMEBUFFERSTATE_H
|
||||||
#define MOBILEGL_GLSTATE_H
|
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
struct FramebufferAttachment {
|
struct FramebufferAttachment {
|
||||||
GLenum type = GL_NONE;
|
GLenum type = GL_NONE;
|
||||||
@@ -17,7 +14,7 @@ struct FramebufferAttachment {
|
|||||||
|
|
||||||
struct FramebufferObject {
|
struct FramebufferObject {
|
||||||
bool generated = false;
|
bool generated = false;
|
||||||
ankerl::unordered_map<GLenum, FramebufferAttachment> attachments;
|
MG_Global::unordered_map<GLenum, FramebufferAttachment> attachments;
|
||||||
GLenum status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
|
GLenum status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
|
||||||
GLsizei width = 0;
|
GLsizei width = 0;
|
||||||
GLsizei height = 0;
|
GLsizei height = 0;
|
||||||
@@ -35,10 +32,10 @@ public:
|
|||||||
GLenum ValidateCompleteness(GLenum target);
|
GLenum ValidateCompleteness(GLenum target);
|
||||||
FramebufferObject* GetCurrentFBO(GLenum target);
|
FramebufferObject* GetCurrentFBO(GLenum target);
|
||||||
|
|
||||||
ankerl::unordered_map<GLenum, GLuint> currentBindings_; // READ/DRAW
|
MG_Global::unordered_map<GLenum, GLuint> currentBindings_; // READ/DRAW
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ankerl::unordered_map<GLuint, FramebufferObject> framebuffers_;
|
MG_Global::unordered_map<GLuint, FramebufferObject> framebuffers_;
|
||||||
std::set<GLuint> freeIds_;
|
std::set<GLuint> freeIds_;
|
||||||
GLuint lastId_ = 0;
|
GLuint lastId_ = 0;
|
||||||
bool ValidateHandle(GLuint framebuffer);
|
bool ValidateHandle(GLuint framebuffer);
|
||||||
|
|||||||
@@ -4,11 +4,6 @@
|
|||||||
// TODO: Add more gl error check for buffer state manager.
|
// TODO: Add more gl error check for buffer state manager.
|
||||||
// TODO: Check if the state machine really meets up to OpenGL 3 standard.
|
// TODO: Check if the state machine really meets up to OpenGL 3 standard.
|
||||||
|
|
||||||
#include "ProgramState.h"
|
|
||||||
|
|
||||||
// Re-Include Includes.h, cuz of the absence of Program/DebugTool.h and Program/GLSLTool.cpp.
|
|
||||||
#undef MOBILEGL_GLSLTOOL_H
|
|
||||||
#undef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
|
||||||
#include "../../../Includes.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
ProgramState::ProgramState() {
|
ProgramState::ProgramState() {
|
||||||
@@ -110,7 +105,21 @@ GLenum ProgramState::FinalizeProgramPipeline(GLuint program) {
|
|||||||
std::vector<std::vector<unsigned>> allSpirv =
|
std::vector<std::vector<unsigned>> allSpirv =
|
||||||
MG_Util::Program::CompileMultipleShadersToSPIRV(*this, prog, prog.infoLog);
|
MG_Util::Program::CompileMultipleShadersToSPIRV(*this, prog, prog.infoLog);
|
||||||
|
|
||||||
|
if (!prog.infoLog.empty() || allSpirv.empty()) {
|
||||||
|
prog.linked = UncertainBool::False;
|
||||||
|
prog.linkStatus = GL_FALSE;
|
||||||
|
prog.infoLog = "Program linking failed during SPIR-V compilation: " + prog.infoLog;
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: FinalizeProgramPipeline error: %s", prog.infoLog.c_str());
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
MG_Util::Program::ReflectSPIRVUniforms(allSpirv, prog, prog.infoLog);
|
MG_Util::Program::ReflectSPIRVUniforms(allSpirv, prog, prog.infoLog);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < prog.attachedShaders.size(); ++i) {
|
||||||
|
GLuint shaderId = prog.attachedShaders[i];
|
||||||
|
shaders_[shaderId].source = MG_Util::Program::CompileSPIRVToGLSL(allSpirv[i], 450, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (!prog.infoLog.empty()) {
|
if (!prog.infoLog.empty()) {
|
||||||
prog.linked = UncertainBool::False;
|
prog.linked = UncertainBool::False;
|
||||||
prog.linkStatus = GL_FALSE;
|
prog.linkStatus = GL_FALSE;
|
||||||
@@ -119,9 +128,7 @@ GLenum ProgramState::FinalizeProgramPipeline(GLuint program) {
|
|||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& [name, index] : prog.attribBindings) {
|
// TODO: Support explicitly assign attrib locations in the shaders.
|
||||||
prog.attribLocations[name] = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
prog.linked = {UncertainBool::Unknown, UncertainBool::True};
|
prog.linked = {UncertainBool::Unknown, UncertainBool::True};
|
||||||
prog.linkStatus = GL_TRUE;
|
prog.linkStatus = GL_TRUE;
|
||||||
@@ -147,28 +154,28 @@ GLenum ProgramState::ActivateRenderProgram(GLuint program) {
|
|||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name) {
|
GLenum ProgramState::DefineProgramAttributeLocation(GLuint program, GLuint index, const GLchar* name) {
|
||||||
MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeBinding called, program=%u, index=%u, name=%s",
|
MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeLocation called, program=%u, index=%u, name=%s",
|
||||||
program, index, name);
|
program, index, name);
|
||||||
if (!ValidateProgram_(program)) {
|
if (!ValidateProgram_(program)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeBinding error: invalid program id %u", program);
|
MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeLocation error: invalid program id %u", program);
|
||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
if (index >= GL_MAX_VERTEX_ATTRIBS) {
|
if (index >= GL_MAX_VERTEX_ATTRIBS) {
|
||||||
MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeBinding error: index %u out of range", index);
|
MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeLocation error: index %u out of range", index);
|
||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
programs_[program].attribBindings[name] = index;
|
programs_[program].attribLocations[name] = index;
|
||||||
MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeBinding success: %s -> %u", name, index);
|
MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeLocation success: %s -> %u", name, index);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint ProgramState::QueryProgramAttributeBinding(GLuint program, const GLchar* name) {
|
GLint ProgramState::QueryProgramAttributeLocation(GLuint program, const GLchar* name) {
|
||||||
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeBinding called, program=%u, name=%s",
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeLocation called, program=%u, name=%s",
|
||||||
program, name);
|
program, name);
|
||||||
if (!ValidateProgram_(program)) {
|
if (!ValidateProgram_(program)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Program: QueryProgramAttributeBinding error: invalid program id %u", program);
|
MG_Util::Debug::LogE("MG_State: Program: QueryProgramAttributeLocation error: invalid program id %u", program);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,11 +183,27 @@ GLint ProgramState::QueryProgramAttributeBinding(GLuint program, const GLchar* n
|
|||||||
auto it = prog.attribLocations.find(name);
|
auto it = prog.attribLocations.find(name);
|
||||||
if (it != prog.attribLocations.end()) {
|
if (it != prog.attribLocations.end()) {
|
||||||
GLint loc = it->second;
|
GLint loc = it->second;
|
||||||
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeBinding success: %s -> %d", name, loc);
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeLocation success: %s -> %d", name, loc);
|
||||||
return loc;
|
return loc;
|
||||||
|
} else {
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: QueryProgramAttributeLocation warning: name '%s' not found, generating new one...", name);
|
||||||
|
// Find the next available location
|
||||||
|
GLint loc = (GLint)prog.attribLocations.size();
|
||||||
|
bool locInUse;
|
||||||
|
do {
|
||||||
|
locInUse = false;
|
||||||
|
for (const auto& pair : prog.attribLocations) {
|
||||||
|
if (pair.second == loc) {
|
||||||
|
locInUse = true;
|
||||||
|
loc++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (locInUse);
|
||||||
|
prog.attribLocations[name] = loc;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeLocation success: %s -> %d", name, loc);
|
||||||
|
return prog.attribLocations[name];
|
||||||
}
|
}
|
||||||
MG_Util::Debug::LogW("MG_State: Program: QueryProgramAttributeBinding warning: name '%s' not found", name);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params) {
|
GLenum ProgramState::QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params) {
|
||||||
@@ -408,26 +431,26 @@ GLuint ProgramState::GetCurrentProgram() const {
|
|||||||
return currentProgram_;
|
return currentProgram_;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderObject ProgramState::GetShaderObject(GLuint shader) const {
|
const ShaderObject* ProgramState::GetShaderObject(GLuint shader) const {
|
||||||
MG_Util::Debug::LogD("MG_State: Program: GetShaderObject called, shader=%u", shader);
|
MG_Util::Debug::LogD("MG_State: Program: GetShaderObject called, shader=%u", shader);
|
||||||
auto it = shaders_.find(shader);
|
auto it = shaders_.find(shader);
|
||||||
if (it == shaders_.end()) {
|
if (it == shaders_.end()) {
|
||||||
MG_Util::Debug::LogW("MG_State: Program: GetShaderObject warning: invalid shader id %u", shader);
|
MG_Util::Debug::LogW("MG_State: Program: GetShaderObject warning: invalid shader id %u", shader);
|
||||||
return ShaderObject();
|
return nullptr;
|
||||||
}
|
}
|
||||||
MG_Util::Debug::LogD("MG_State: Program: GetShaderObject success, returning object");
|
MG_Util::Debug::LogD("MG_State: Program: GetShaderObject success, returning object");
|
||||||
return it->second;
|
return &(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramObject ProgramState::GetProgramObject(GLuint program) const {
|
const ProgramObject* ProgramState::GetProgramObject(GLuint program) const {
|
||||||
MG_Util::Debug::LogD("MG_State: Program: GetProgramObject called, program=%u", program);
|
MG_Util::Debug::LogD("MG_State: Program: GetProgramObject called, program=%u", program);
|
||||||
auto it = programs_.find(program);
|
auto it = programs_.find(program);
|
||||||
if (it == programs_.end()) {
|
if (it == programs_.end()) {
|
||||||
MG_Util::Debug::LogW("MG_State: Program: GetProgramObject warning: invalid program id %u", program);
|
MG_Util::Debug::LogW("MG_State: Program: GetProgramObject warning: invalid program id %u", program);
|
||||||
return ProgramObject();
|
return nullptr;
|
||||||
}
|
}
|
||||||
MG_Util::Debug::LogD("MG_State: Program: GetProgramObject success, returning object");
|
MG_Util::Debug::LogD("MG_State: Program: GetProgramObject success, returning object");
|
||||||
return it->second;
|
return &(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgramState::ValidateProgram_(GLuint program) {
|
bool ProgramState::ValidateProgram_(GLuint program) {
|
||||||
@@ -451,7 +474,7 @@ void ProgramState::CleanupShaders_() {
|
|||||||
}
|
}
|
||||||
if (!inUse) {
|
if (!inUse) {
|
||||||
MG_Util::Debug::LogD("MG_State: Program: CleanupShaders_ deleting shader %u", it->first);
|
MG_Util::Debug::LogD("MG_State: Program: CleanupShaders_ deleting shader %u", it->first);
|
||||||
freeShaderIds_.insert(it->first);
|
// freeShaderIds_.insert(it->first);
|
||||||
it = shaders_.erase(it);
|
it = shaders_.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,6 @@
|
|||||||
|
|
||||||
#ifndef MOBILEGL_PROGRAMSTATE_H
|
#ifndef MOBILEGL_PROGRAMSTATE_H
|
||||||
#define MOBILEGL_PROGRAMSTATE_H
|
#define MOBILEGL_PROGRAMSTATE_H
|
||||||
#define MOBILEGL_GLSTATE_H
|
|
||||||
#define MOBILEGL_PROGRAM_DEBUGTOOL_H
|
|
||||||
#define MOBILEGL_GLSLTOOL_H
|
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
struct ShaderObject {
|
struct ShaderObject {
|
||||||
GLenum type;
|
GLenum type;
|
||||||
@@ -41,17 +36,16 @@ struct ProgramObject {
|
|||||||
bool dirty;
|
bool dirty;
|
||||||
GLint linkStatus;
|
GLint linkStatus;
|
||||||
std::string infoLog;
|
std::string infoLog;
|
||||||
ankerl::unordered_map<std::string, GLint> attribBindings;
|
MG_Global::unordered_map<std::string, GLint> attribLocations;
|
||||||
ankerl::unordered_map<std::string, GLint> attribLocations;
|
MG_Global::unordered_map<std::string, GLint> uniformLocations;
|
||||||
ankerl::unordered_map<std::string, GLint> uniformLocations;
|
MG_Global::unordered_map<std::string, UniformValue> uniformValues;
|
||||||
ankerl::unordered_map<std::string, UniformValue> uniformValues;
|
|
||||||
bool markedForDeletion;
|
bool markedForDeletion;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProgramState {
|
class ProgramState {
|
||||||
public:
|
public:
|
||||||
ankerl::unordered_map<GLuint, ShaderObject> shaders_;
|
MG_Global::unordered_map<GLuint, ShaderObject> shaders_;
|
||||||
ankerl::unordered_map<GLuint, ProgramObject> programs_;
|
MG_Global::unordered_map<GLuint, ProgramObject> programs_;
|
||||||
std::set<GLuint> freeShaderIds_;
|
std::set<GLuint> freeShaderIds_;
|
||||||
std::set<GLuint> freeProgramIds_;
|
std::set<GLuint> freeProgramIds_;
|
||||||
GLuint lastShaderId_ = 0;
|
GLuint lastShaderId_ = 0;
|
||||||
@@ -71,8 +65,8 @@ public:
|
|||||||
GLenum BuildShaderStage(GLuint shader);
|
GLenum BuildShaderStage(GLuint shader);
|
||||||
GLenum FinalizeProgramPipeline(GLuint program);
|
GLenum FinalizeProgramPipeline(GLuint program);
|
||||||
GLenum ActivateRenderProgram(GLuint program);
|
GLenum ActivateRenderProgram(GLuint program);
|
||||||
GLenum DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name);
|
GLenum DefineProgramAttributeLocation(GLuint program, GLuint index, const GLchar* name);
|
||||||
GLint QueryProgramAttributeBinding(GLuint program, const GLchar* name);
|
GLint QueryProgramAttributeLocation(GLuint program, const GLchar* name);
|
||||||
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name);
|
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name);
|
||||||
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
|
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
|
||||||
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
|
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
|
||||||
@@ -110,8 +104,8 @@ public:
|
|||||||
DECLARE_MATRIX_FUNCTIONS(4x3, GL_FLOAT_MAT4x3)
|
DECLARE_MATRIX_FUNCTIONS(4x3, GL_FLOAT_MAT4x3)
|
||||||
#undef DECLARE_MATRIX_FUNCTIONS
|
#undef DECLARE_MATRIX_FUNCTIONS
|
||||||
|
|
||||||
ProgramObject GetProgramObject(GLuint program) const;
|
const ProgramObject* GetProgramObject(GLuint program) const;
|
||||||
ShaderObject GetShaderObject(GLuint program) const;
|
const ShaderObject* GetShaderObject(GLuint program) const;
|
||||||
GLuint GetCurrentProgram() const;
|
GLuint GetCurrentProgram() const;
|
||||||
bool SetProgramStatus(GLuint program, GLboolean status);
|
bool SetProgramStatus(GLuint program, GLboolean status);
|
||||||
bool SetShaderStatus(GLuint shader, GLboolean status);
|
bool SetShaderStatus(GLuint shader, GLboolean status);
|
||||||
|
|||||||
@@ -2,11 +2,6 @@
|
|||||||
// Created by BZLZHH on 2025/5/3.
|
// Created by BZLZHH on 2025/5/3.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "ShaderObject.h"
|
|
||||||
|
|
||||||
// Re-Include Includes.h, cuz of the absence of Program/DebugTool.h and Program/GLSLTool.cpp.
|
|
||||||
#undef MOBILEGL_GLSLTOOL_H
|
|
||||||
#undef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
|
||||||
#include "../../../Includes.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
GLenum ProgramState::CreateShader(GLenum type, GLuint* shader) {
|
GLenum ProgramState::CreateShader(GLenum type, GLuint* shader) {
|
||||||
@@ -42,10 +37,6 @@ GLenum ProgramState::DeleteShader(GLuint shader) {
|
|||||||
MG_Util::Debug::LogE("MG_State: Program: DeleteShader error: invalid shader id %u", shader);
|
MG_Util::Debug::LogE("MG_State: Program: DeleteShader error: invalid shader id %u", shader);
|
||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
if (shaders_[shader].markedForDeletion) {
|
|
||||||
MG_Util::Debug::LogW("MG_State: Program: DeleteShader warning: shader %u already marked for deletion", shader);
|
|
||||||
return GL_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool inUse = false;
|
bool inUse = false;
|
||||||
for (auto& [progId, program] : programs_) {
|
for (auto& [progId, program] : programs_) {
|
||||||
|
|||||||
@@ -5,8 +5,4 @@
|
|||||||
#ifndef MOBILEGL_SHADEROBJECT_H
|
#ifndef MOBILEGL_SHADEROBJECT_H
|
||||||
#define MOBILEGL_SHADEROBJECT_H
|
#define MOBILEGL_SHADEROBJECT_H
|
||||||
|
|
||||||
#define MOBILEGL_GLSTATE_H
|
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
#endif //MOBILEGL_SHADEROBJECT_H
|
#endif //MOBILEGL_SHADEROBJECT_H
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
// Created by BZLZHH on 2025/4/4.
|
// Created by BZLZHH on 2025/4/4.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "TextureState.h"
|
|
||||||
|
|
||||||
// Re-Include Includes.h, cuz of the absence of GLState.h
|
|
||||||
#undef MOBILEGL_GLSTATE_H
|
|
||||||
#include "../../../Includes.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
// TextureObject
|
// TextureObject
|
||||||
@@ -121,7 +117,7 @@ GLenum TextureState::CreateN(GLsizei n, GLuint* textures) {
|
|||||||
|
|
||||||
GLenum TextureState::Bind(GLenum target, GLuint texture) {
|
GLenum TextureState::Bind(GLenum target, GLuint texture) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: Bind called with target=0x%x, texture=%u", target, texture);
|
MG_Util::Debug::LogD("MG_State: Texture: Bind called with target=0x%x, texture=%u", target, texture);
|
||||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: Bind invalid target=0x%x", target);
|
MG_Util::Debug::LogE("MG_State: Texture: Bind invalid target=0x%x", target);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
@@ -146,7 +142,6 @@ GLenum TextureState::Bind(GLenum target, GLuint texture) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TextureUnitState& unit = textureUnits_[activeTextureUnit_];
|
TextureUnitState& unit = textureUnits_[activeTextureUnit_];
|
||||||
TextureObject* texObj = nullptr;
|
TextureObject* texObj = nullptr;
|
||||||
auto it = this->textures.find(texture);
|
auto it = this->textures.find(texture);
|
||||||
@@ -498,12 +493,12 @@ GLenum TextureState::UpdateRegion2D(GLenum target, GLint level, GLint xoffset,
|
|||||||
|
|
||||||
GLenum TextureState::SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloat param) {
|
GLenum TextureState::SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloat param) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyFloat called target=0x%x, pname=0x%x, param=%f", target, pname, param);
|
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyFloat called target=0x%x, pname=0x%x, param=%f", target, pname, param);
|
||||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid target=0x%x", target);
|
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid target=0x%x", target);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.end()) {
|
if (!MG_Constants::Common::Contains(pname, MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid pname=0x%x", pname);
|
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid pname=0x%x", pname);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
@@ -550,12 +545,12 @@ GLenum TextureState::SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloa
|
|||||||
|
|
||||||
GLenum TextureState::SetTexturePropertyInt(GLenum target, GLenum pname, GLint param) {
|
GLenum TextureState::SetTexturePropertyInt(GLenum target, GLenum pname, GLint param) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyInt called target=0x%x, pname=0x%x, param=%d", target, pname, param);
|
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyInt called target=0x%x, pname=0x%x, param=%d", target, pname, param);
|
||||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid target=0x%x", target);
|
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid target=0x%x", target);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.end()) {
|
if (!MG_Constants::Common::Contains(pname, MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid pname=0x%x", pname);
|
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid pname=0x%x", pname);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
@@ -646,7 +641,7 @@ GLenum TextureState::DeleteN(GLsizei n, const GLuint* textures) {
|
|||||||
|
|
||||||
GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params) {
|
GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: QueryLevelPropertyIntVector called target=0x%x, level=%d, pname=0x%x", target, level, pname);
|
MG_Util::Debug::LogD("MG_State: Texture: QueryLevelPropertyIntVector called target=0x%x, level=%d, pname=0x%x", target, level, pname);
|
||||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: QueryLevelPropertyIntVector invalid target=0x%x", target);
|
MG_Util::Debug::LogE("MG_State: Texture: QueryLevelPropertyIntVector invalid target=0x%x", target);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
@@ -656,7 +651,7 @@ GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLe
|
|||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES.end()) {
|
if (!MG_Constants::Common::Contains(pname, MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: QueryLevelPropertyIntVector invalid pname=0x%x", pname);
|
MG_Util::Debug::LogE("MG_State: Texture: QueryLevelPropertyIntVector invalid pname=0x%x", pname);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
@@ -700,7 +695,7 @@ GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLe
|
|||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
unordered_map<GLuint, TextureObject>::iterator texIt;
|
MG_Global::unordered_map<GLuint, TextureObject>::iterator texIt;
|
||||||
|
|
||||||
if (!isProxyTexture) {
|
if (!isProxyTexture) {
|
||||||
texIt = textures.find(boundTexture);
|
texIt = textures.find(boundTexture);
|
||||||
@@ -806,7 +801,7 @@ GLenum TextureState::CheckUploadingTexture2DValidity_(GLenum target, GLint level
|
|||||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||||
GLenum type, const void* data) {
|
GLenum type, const void* data) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: CheckUploadingTexture2DValidity_ called target=0x%x, level=%d", target, level);
|
MG_Util::Debug::LogD("MG_State: Texture: CheckUploadingTexture2DValidity_ called target=0x%x, level=%d", target, level);
|
||||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid target=0x%x", target);
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid target=0x%x", target);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
@@ -846,17 +841,17 @@ GLenum TextureState::CheckUploadingTexture2DValidity_(GLenum target, GLint level
|
|||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_INTERNAL_FORMATS.find(internalFormat) == MG_Constants::Texture::VALID_INTERNAL_FORMATS.end()) {
|
if (!MG_Constants::Common::Contains((GLenum)internalFormat, MG_Constants::Texture::VALID_INTERNAL_FORMATS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid internalFormat=0x%x", internalFormat);
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid internalFormat=0x%x", internalFormat);
|
||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_FORMATS.find(format) == MG_Constants::Texture::VALID_FORMATS.end()) {
|
if (!MG_Constants::Common::Contains((GLenum)format, MG_Constants::Texture::VALID_FORMATS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid format=0x%x", format);
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid format=0x%x", format);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_TYPES.find(type) == MG_Constants::Texture::VALID_TYPES.end()) {
|
if (!MG_Constants::Common::Contains((GLenum)type, MG_Constants::Texture::VALID_TYPES)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid type=0x%x", type);
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ invalid type=0x%x", type);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
@@ -928,7 +923,7 @@ GLenum TextureState::CheckUpdatingTextureRegion2DValidity_(GLenum target, GLint
|
|||||||
MG_Util::Debug::LogD("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ called target=0x%x, level=%d, x=%d, y=%d, w=%d, h=%d",
|
MG_Util::Debug::LogD("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ called target=0x%x, level=%d, x=%d, y=%d, w=%d, h=%d",
|
||||||
target, level, xoffset, yoffset, width, height);
|
target, level, xoffset, yoffset, width, height);
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
if (!MG_Constants::Common::Contains(target, MG_Constants::Texture::VALID_TARGETS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid target=0x%x", target);
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid target=0x%x", target);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
@@ -978,12 +973,12 @@ GLenum TextureState::CheckUpdatingTextureRegion2DValidity_(GLenum target, GLint
|
|||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_FORMATS.find(format) == MG_Constants::Texture::VALID_FORMATS.end()) {
|
if (!MG_Constants::Common::Contains(format, MG_Constants::Texture::VALID_FORMATS)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid format=0x%x", format);
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid format=0x%x", format);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MG_Constants::Texture::VALID_TYPES.find(type) == MG_Constants::Texture::VALID_TYPES.end()) {
|
if (!MG_Constants::Common::Contains(type, MG_Constants::Texture::VALID_TYPES)) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid type=0x%x", type);
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ invalid type=0x%x", type);
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
#ifndef MOBILEGL_TEXTURESTATE_H
|
#ifndef MOBILEGL_TEXTURESTATE_H
|
||||||
#define MOBILEGL_TEXTURESTATE_H
|
#define MOBILEGL_TEXTURESTATE_H
|
||||||
#define MOBILEGL_GLSTATE_H
|
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
struct ComponentSizes {
|
struct ComponentSizes {
|
||||||
GLint red = 0;
|
GLint red = 0;
|
||||||
@@ -19,10 +16,8 @@ struct ComponentSizes {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TextureParams {
|
struct TextureParams {
|
||||||
template <typename K, typename V>
|
MG_Global::unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
||||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
MG_Global::unordered_map<GLenum, GLint> texPropertiesInt;
|
||||||
unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
|
||||||
unordered_map<GLenum, GLint> texPropertiesInt;
|
|
||||||
struct MipmapLevel {
|
struct MipmapLevel {
|
||||||
GLsizei width = 0;
|
GLsizei width = 0;
|
||||||
GLsizei height = 0;
|
GLsizei height = 0;
|
||||||
@@ -33,7 +28,7 @@ struct TextureParams {
|
|||||||
bool hasData = false;
|
bool hasData = false;
|
||||||
bool dirty = false; // TODO: encapsulate this with an public API to RHI
|
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 {
|
class TextureObject {
|
||||||
@@ -47,35 +42,31 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class TextureUnitState {
|
class TextureUnitState {
|
||||||
template <typename K, typename V>
|
|
||||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
|
||||||
private:
|
|
||||||
GLenum activeTarget = GL_TEXTURE_2D;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unordered_map<GLenum, GLuint> boundTextures;
|
|
||||||
void Bind(GLenum target, GLuint texture);
|
void Bind(GLenum target, GLuint texture);
|
||||||
GLuint GetBoundTexture(GLenum target);
|
GLuint GetBoundTexture(GLenum target);
|
||||||
|
|
||||||
|
GLenum activeTarget = GL_TEXTURE_2D;
|
||||||
|
MG_Global::unordered_map<GLenum, GLuint> boundTextures;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureState {
|
class TextureState {
|
||||||
template <typename K, typename V>
|
|
||||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
GLuint lastUsedID_ = 1;
|
GLuint lastUsedID_ = 1;
|
||||||
// ankerl::unordered_set<GLuint> freeIDs_;
|
// MG_Global::unordered_set<GLuint> freeIDs_;
|
||||||
std::vector<GLuint> freeID_;
|
std::vector<GLuint> freeID_;
|
||||||
|
|
||||||
unordered_map<GLenum, TextureObject> proxyTextures_;
|
MG_Global::unordered_map<GLenum, TextureObject> proxyTextures_;
|
||||||
|
|
||||||
static GLint GetUnpackParam_(GLenum pname);
|
static GLint GetUnpackParam_(GLenum pname);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextureState();
|
TextureState();
|
||||||
|
|
||||||
bool IsTextureGenerated(GLuint texture);
|
bool IsTextureGenerated(GLuint texture);
|
||||||
bool IsTexture(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
|
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||||
GLenum BindUnit(GLenum textureUnit);
|
GLenum BindUnit(GLenum textureUnit);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// TODO: Add more gl error check for vertex array state manager.
|
// TODO: Add more gl error check for vertex array state manager.
|
||||||
|
|
||||||
#include "VertexArrayState.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
VertexArrayState::VertexArrayState() {
|
VertexArrayState::VertexArrayState() {
|
||||||
vaos_[0];
|
vaos_[0];
|
||||||
@@ -107,7 +107,7 @@ bool VertexArrayState::ValidateAllocatedHandle(GLuint array) {
|
|||||||
GLenum VertexArrayState::EnableAttrib(GLuint index) {
|
GLenum VertexArrayState::EnableAttrib(GLuint index) {
|
||||||
if (!ValidateAllocatedHandle(currentVao_))
|
if (!ValidateAllocatedHandle(currentVao_))
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
if (index >= MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
||||||
GetCurrentVAO()->attribs[index].enabled = true;
|
GetCurrentVAO()->attribs[index].enabled = true;
|
||||||
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
|
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ GLenum VertexArrayState::EnableAttrib(GLuint index) {
|
|||||||
GLenum VertexArrayState::DisableAttrib(GLuint index) {
|
GLenum VertexArrayState::DisableAttrib(GLuint index) {
|
||||||
if (!ValidateAllocatedHandle(currentVao_))
|
if (!ValidateAllocatedHandle(currentVao_))
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
if (index >= MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
||||||
GetCurrentVAO()->attribs[index].enabled = false;
|
GetCurrentVAO()->attribs[index].enabled = false;
|
||||||
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
|
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type,
|
|||||||
GLuint currentArrayBuffer) {
|
GLuint currentArrayBuffer) {
|
||||||
if (!ValidateAllocatedHandle(currentVao_))
|
if (!ValidateAllocatedHandle(currentVao_))
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
if (index >= MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
||||||
|
|
||||||
VertexAttribState state;
|
VertexAttribState state;
|
||||||
state.size = size;
|
state.size = size;
|
||||||
@@ -142,8 +142,7 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type,
|
|||||||
state.pointer = pointer;
|
state.pointer = pointer;
|
||||||
state.buffer = currentArrayBuffer;
|
state.buffer = currentArrayBuffer;
|
||||||
state.isInteger = isInteger;
|
state.isInteger = isInteger;
|
||||||
if (vaos_[currentVao_].attribs.count(index) && vaos_[currentVao_].attribs[index].enabled)
|
state.enabled = vaos_[currentVao_].attribs[index].enabled;
|
||||||
state.enabled = true;
|
|
||||||
|
|
||||||
vaos_[currentVao_].attribs[index] = state;
|
vaos_[currentVao_].attribs[index] = state;
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,9 @@
|
|||||||
|
|
||||||
#ifndef MOBILEGL_VERTEXARRAYSTATE_H
|
#ifndef MOBILEGL_VERTEXARRAYSTATE_H
|
||||||
#define MOBILEGL_VERTEXARRAYSTATE_H
|
#define MOBILEGL_VERTEXARRAYSTATE_H
|
||||||
#define MOBILEGL_GLSTATE_H
|
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
struct VertexAttribState {
|
struct VertexAttribState {
|
||||||
bool enabled;
|
bool enabled = false;
|
||||||
GLint size = 4;
|
GLint size = 4;
|
||||||
GLenum type = GL_FLOAT;
|
GLenum type = GL_FLOAT;
|
||||||
GLboolean normalized = GL_FALSE;
|
GLboolean normalized = GL_FALSE;
|
||||||
@@ -24,7 +21,7 @@ struct VertexArrayObject {
|
|||||||
bool attribDirty = false;
|
bool attribDirty = false;
|
||||||
bool eboDirty = false;
|
bool eboDirty = false;
|
||||||
GLuint elementBuffer = 0;
|
GLuint elementBuffer = 0;
|
||||||
ankerl::unordered_map<GLuint, VertexAttribState> attribs;
|
std::array<VertexAttribState, MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS> attribs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VertexArrayState {
|
class VertexArrayState {
|
||||||
@@ -50,7 +47,7 @@ public:
|
|||||||
bool ValidateAllocatedHandle(GLuint array);
|
bool ValidateAllocatedHandle(GLuint array);
|
||||||
|
|
||||||
GLuint currentVao_ = 0;
|
GLuint currentVao_ = 0;
|
||||||
ankerl::unordered_map<GLuint, VertexArrayObject> vaos_;
|
MG_Global::unordered_map<GLuint, VertexArrayObject> vaos_;
|
||||||
private:
|
private:
|
||||||
std::set<GLuint> freeIds_;
|
std::set<GLuint> freeIds_;
|
||||||
GLuint lastId_ = 0;
|
GLuint lastId_ = 0;
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// Created by yello on 2025-06-27.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef INDEXGENERATOR_H
|
||||||
|
#define INDEXGENERATOR_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cstddef> // For size_t
|
||||||
|
#include <algorithm> // For std::min
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
template <typename IndexType>
|
||||||
|
class IndexGenerator {
|
||||||
|
public:
|
||||||
|
// 构造函数
|
||||||
|
IndexGenerator() : next_index_(1) {}
|
||||||
|
explicit IndexGenerator(IndexType n) : next_index_(1) {
|
||||||
|
is_valid_.reserve(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成n个新正整数
|
||||||
|
void Generate(size_t n, IndexType *indices) {
|
||||||
|
if (n <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先给出被删除的索引
|
||||||
|
size_t count_from_freed = std::min(n, freed_indices_.size());
|
||||||
|
for (size_t i = 0; i < count_from_freed; ++i) {
|
||||||
|
indices[i] = freed_indices_.back();
|
||||||
|
freed_indices_.pop_back();
|
||||||
|
// 标记为有效,确保is_valid_的大小足够
|
||||||
|
if (indices[i] >= is_valid_.size()) {
|
||||||
|
is_valid_.resize(static_cast<size_t>(indices[i]) + 1, false); // 0代表无效,1代表有效
|
||||||
|
}
|
||||||
|
is_valid_[indices[i]] = true; // 标记为有效
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果还需要更多的索引,则生成新的索引
|
||||||
|
for (size_t i = count_from_freed; i < n; ++i) {
|
||||||
|
indices[i] = next_index_++;
|
||||||
|
// 确保is_valid_的大小足够
|
||||||
|
if (indices[i] >= is_valid_.size()) {
|
||||||
|
is_valid_.resize(static_cast<size_t>(indices[i]) + 1, false);
|
||||||
|
}
|
||||||
|
is_valid_[indices[i]] = true; // 标记为有效
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除一个已经给出的正整数
|
||||||
|
void Delete(IndexType index) {
|
||||||
|
// 检查索引是否有效且未被删除
|
||||||
|
// 这里的检查是为了避免重复删除或删除未生成的索引
|
||||||
|
if (index < is_valid_.size() && is_valid_[index] == true) {
|
||||||
|
is_valid_[index] = false; // 标记为无效
|
||||||
|
freed_indices_.push_back(index); // 添加到已删除列表中
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查一个正整数是否之前已经被给出,并且没有被删除
|
||||||
|
bool IsValid(IndexType index) const {
|
||||||
|
// 如果索引超出is_valid_的范围,或者对应的位置是0,则认为无效
|
||||||
|
return index < is_valid_.size() && is_valid_[index] == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IndexType next_index_; // 下一个将要生成的正整数
|
||||||
|
std::vector<IndexType> freed_indices_; // 存储被删除的索引
|
||||||
|
std::vector<bool> is_valid_; // 标记索引是否有效。0代表无效,1代表有效。
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //INDEXGENERATOR_H
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/4/26.
|
// Created by BZLZHH on 2025/4/26.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "TestDrawing.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
namespace MG_RHI::GLES::Test {
|
namespace MG_RHI::GLES::Test {
|
||||||
constexpr int DISPLAY_COLUMNS = 8;
|
constexpr int DISPLAY_COLUMNS = 8;
|
||||||
@@ -14,6 +14,7 @@ namespace MG_RHI::GLES::Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CheckShaderCompileStatus(GLuint shader, const char* type) {
|
bool CheckShaderCompileStatus(GLuint shader, const char* type) {
|
||||||
|
#if BACKEND_TYPE == BACKEND_GLES
|
||||||
GLint success;
|
GLint success;
|
||||||
::GLES::glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
::GLES::glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@@ -22,10 +23,12 @@ namespace MG_RHI::GLES::Test {
|
|||||||
MG_Util::Debug::LogE("Shader compilation error (%s): %s", type, infoLog);
|
MG_Util::Debug::LogE("Shader compilation error (%s): %s", type, infoLog);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckProgramLinkStatus(GLuint program) {
|
bool CheckProgramLinkStatus(GLuint program) {
|
||||||
|
#if BACKEND_TYPE == BACKEND_GLES
|
||||||
GLint success;
|
GLint success;
|
||||||
::GLES::glGetProgramiv(program, GL_LINK_STATUS, &success);
|
::GLES::glGetProgramiv(program, GL_LINK_STATUS, &success);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@@ -34,11 +37,13 @@ namespace MG_RHI::GLES::Test {
|
|||||||
MG_Util::Debug::LogE("Program link error: %s", infoLog);
|
MG_Util::Debug::LogE("Program link error: %s", infoLog);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use the textures state from MG_RHI(another state?) rather than directly from MG_State
|
// TODO: Use the textures state from MG_RHI(another state?) rather than directly from MG_State
|
||||||
void DrawAllTextures() {
|
void DrawAllTextures() {
|
||||||
|
#if BACKEND_TYPE == BACKEND_GLES
|
||||||
::GLES::glClearColor(1,1,1,1);
|
::GLES::glClearColor(1,1,1,1);
|
||||||
::GLES::glClear(GL_COLOR_BUFFER_BIT);
|
::GLES::glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
@@ -48,8 +53,8 @@ namespace MG_RHI::GLES::Test {
|
|||||||
GLuint quadVBO = 0;
|
GLuint quadVBO = 0;
|
||||||
GLint uTexLoc = -1;
|
GLint uTexLoc = -1;
|
||||||
GLint uMVPLoc = -1;
|
GLint uMVPLoc = -1;
|
||||||
ankerl::unordered_map<GLuint, GLuint> textureCache;
|
MG_Global::unordered_map<GLuint, GLuint> textureCache;
|
||||||
ankerl::unordered_map<GLuint, bool> textureDirty;
|
MG_Global::unordered_map<GLuint, bool> textureDirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ScreenResources sRes;
|
static ScreenResources sRes;
|
||||||
@@ -230,5 +235,6 @@ namespace MG_RHI::GLES::Test {
|
|||||||
::GLES::glUseProgram(origProgram);
|
::GLES::glUseProgram(origProgram);
|
||||||
::GLES::glViewport(origViewport[0], origViewport[1],
|
::GLES::glViewport(origViewport[0], origViewport[1],
|
||||||
origViewport[2], origViewport[3]);
|
origViewport[2], origViewport[3]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_TESTDRAWING_H
|
#ifndef MOBILEGL_TESTDRAWING_H
|
||||||
#define MOBILEGL_TESTDRAWING_H
|
#define MOBILEGL_TESTDRAWING_H
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_RHI::GLES::Test {
|
namespace MG_RHI::GLES::Test {
|
||||||
void DrawAllTextures();
|
void DrawAllTextures();
|
||||||
}
|
}
|
||||||
|
|||||||
+1792
-1033
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_DEBUG_H
|
#ifndef MOBILEGL_DEBUG_H
|
||||||
#define MOBILEGL_DEBUG_H
|
#define MOBILEGL_DEBUG_H
|
||||||
|
|
||||||
#include "../../Includes.h"
|
|
||||||
|
|
||||||
#define FORCE_SYNC_WITH_LOG_FILE 0
|
#define FORCE_SYNC_WITH_LOG_FILE 0
|
||||||
|
|
||||||
namespace MG_Util {
|
namespace MG_Util {
|
||||||
@@ -23,6 +21,7 @@ namespace MG_Util {
|
|||||||
void LogWrite(const char* format, va_list args);
|
void LogWrite(const char* format, va_list args);
|
||||||
|
|
||||||
const char* GLEnumToString(::GLenum value);
|
const char* GLEnumToString(::GLenum value);
|
||||||
|
const char* DiligentBlendFactorToString(Diligent::BLEND_FACTOR value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Created by BZLZHH on 2025/5/3.
|
// Created by BZLZHH on 2025/5/3.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "DebugTool.h"
|
#include "../../Includes.h"
|
||||||
|
|
||||||
namespace MG_Util::Program {
|
namespace MG_Util::Program {
|
||||||
std::string GLTypeToString(GLenum type) {
|
std::string GLTypeToString(GLenum type) {
|
||||||
@@ -54,7 +54,7 @@ namespace MG_Util::Program {
|
|||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << "[";
|
ss << "[";
|
||||||
|
|
||||||
const size_t elemCount = std::min<size_t>(value.count, 16);
|
const size_t elemCount = std::min<size_t>(value.numElements, 16);
|
||||||
|
|
||||||
switch(value.type) {
|
switch(value.type) {
|
||||||
case GL_FLOAT:
|
case GL_FLOAT:
|
||||||
@@ -116,17 +116,17 @@ namespace MG_Util::Program {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DumpUniforms(const ProgramState& state, GLuint program) {
|
void DumpUniforms(const ProgramState& state, GLuint program) {
|
||||||
if (MG_Global::Common::LogLevel > MG_Constants::Common::LOG_LEVEL_DEBUG)
|
if constexpr (MG_Global::Common::LogLevel > MG_Constants::Common::LOG_LEVEL_DEBUG)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto prog = (ProgramObject)state.GetProgramObject(program);
|
auto* prog = state.GetProgramObject(program);
|
||||||
if (!prog.linked.toBool()) {
|
if (!prog->linked.toBool()) {
|
||||||
MG_Util::Debug::LogE("Program %u not linked", program);
|
MG_Util::Debug::LogE("Program %u not linked", program);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MG_Util::Debug::LogD("=== Dumping uniforms for program %u ===", program);
|
MG_Util::Debug::LogD("=== Dumping uniforms for program %u ===", program);
|
||||||
for(const auto& [name, loc] : prog.uniformLocations) {
|
for(const auto& [name, loc] : prog->uniformLocations) {
|
||||||
const auto& value = prog.uniformValues.at(name);
|
const auto& value = prog->uniformValues.at(name);
|
||||||
MG_Util::Debug::LogD("Uniform: %-24s Location: %-4d Type: %-16s Count: %-3d Value: %s",
|
MG_Util::Debug::LogD("Uniform: %-24s Location: %-4d Type: %-16s Count: %-3d Value: %s",
|
||||||
name.c_str(),
|
name.c_str(),
|
||||||
loc,
|
loc,
|
||||||
@@ -142,7 +142,6 @@ namespace MG_Util::Program {
|
|||||||
|
|
||||||
GLuint current = state.GetCurrentProgram();
|
GLuint current = state.GetCurrentProgram();
|
||||||
if (current == 0) {
|
if (current == 0) {
|
||||||
MG_Util::Debug::LogE("No active program");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DumpUniforms(state, current);
|
DumpUniforms(state, current);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#ifndef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
#ifndef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
#define MOBILEGL_PROGRAM_DEBUGTOOL_H
|
#define MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
#include "../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_Util::Program {
|
namespace MG_Util::Program {
|
||||||
std::string GLTypeToString(GLenum type);
|
std::string GLTypeToString(GLenum type);
|
||||||
|
|||||||
+747
-23
@@ -2,10 +2,666 @@
|
|||||||
// Created by BZLZHH on 2025/5/3.
|
// Created by BZLZHH on 2025/5/3.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "GLSLTool.h"
|
#include "../../Includes.h"
|
||||||
|
|
||||||
namespace MG_Util::Program {
|
namespace MG_Util::Program {
|
||||||
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader) {
|
void RenameGLSLBuiltinsForVulkan(std::string &src) {
|
||||||
|
// static const std::vector<std::pair<std::regex, std::string>> rules = {
|
||||||
|
// { std::regex(R"(gl_VertexID)"), "gl_VertexIndex" },
|
||||||
|
// { std::regex(R"(gl_InstanceID)"), "gl_InstanceIndex" }
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// for (auto &rule : rules) {
|
||||||
|
// src = std::regex_replace(src, rule.first, rule.second);
|
||||||
|
// }
|
||||||
|
size_t pos = src.find("gl_VertexID");
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
src.replace(pos, strlen("gl_VertexID"), "gl_VertexIndex");
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = src.find("gl_InstanceID");
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
src.replace(pos, strlen("gl_InstanceID"), "gl_InstanceIndex");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BindInputLayoutLocationsForGLSL(
|
||||||
|
std::vector<uint32_t>& spirv,
|
||||||
|
MG_Global::unordered_map<std::string, GLint>& name_location_map)
|
||||||
|
{
|
||||||
|
spvc_context context = nullptr;
|
||||||
|
spvc_parsed_ir ir = nullptr;
|
||||||
|
spvc_compiler compiler = nullptr;
|
||||||
|
spvc_resources resources = nullptr;
|
||||||
|
spvc_result result = SPVC_SUCCESS;
|
||||||
|
const char* glsl_source = nullptr;
|
||||||
|
std::string output_glsl;
|
||||||
|
|
||||||
|
if ((result = spvc_context_create(&context)) != SPVC_SUCCESS)
|
||||||
|
{
|
||||||
|
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to create context.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result = spvc_context_parse_spirv(context,
|
||||||
|
spirv.data(),
|
||||||
|
spirv.size(),
|
||||||
|
&ir)) != SPVC_SUCCESS)
|
||||||
|
{
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to parse SPIR-V.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result = spvc_context_create_compiler(
|
||||||
|
context,
|
||||||
|
SPVC_BACKEND_GLSL,
|
||||||
|
ir,
|
||||||
|
SPVC_CAPTURE_MODE_TAKE_OWNERSHIP,
|
||||||
|
&compiler)) != SPVC_SUCCESS)
|
||||||
|
{
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to create compiler.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result = spvc_compiler_create_shader_resources(compiler, &resources)) != SPVC_SUCCESS)
|
||||||
|
{
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to create shader resources.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const spvc_reflected_resource* inputs = nullptr;
|
||||||
|
size_t num_inputs = 0;
|
||||||
|
if ((result = spvc_resources_get_resource_list_for_type(
|
||||||
|
resources,
|
||||||
|
SPVC_RESOURCE_TYPE_STAGE_INPUT,
|
||||||
|
&inputs,
|
||||||
|
&num_inputs)) != SPVC_SUCCESS)
|
||||||
|
{
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to get stage inputs.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string, spvc_variable_id> name_to_id;
|
||||||
|
for (size_t i = 0; i < num_inputs; ++i)
|
||||||
|
{
|
||||||
|
name_to_id[inputs[i].name] = inputs[i].id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<GLint> used_locations;
|
||||||
|
|
||||||
|
for (auto& kv : name_location_map)
|
||||||
|
{
|
||||||
|
const auto& name = kv.first;
|
||||||
|
GLint loc = kv.second;
|
||||||
|
auto it = name_to_id.find(name);
|
||||||
|
if (it == name_to_id.end())
|
||||||
|
{
|
||||||
|
MG_Util::Debug::LogW("[SPIRV-Cross] Input name not found: %s", name.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
spvc_compiler_set_decoration(
|
||||||
|
compiler,
|
||||||
|
it->second,
|
||||||
|
SpvDecorationLocation,
|
||||||
|
loc);
|
||||||
|
|
||||||
|
used_locations.insert(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint next_free_loc = 0;
|
||||||
|
for (size_t i = 0; i < num_inputs; ++i)
|
||||||
|
{
|
||||||
|
auto& res = inputs[i];
|
||||||
|
const auto& name = res.name;
|
||||||
|
auto var_id = res.id;
|
||||||
|
|
||||||
|
if (name_location_map.find(name) != name_location_map.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t curr_loc = 0;
|
||||||
|
bool has_loc = false;
|
||||||
|
curr_loc = spvc_compiler_get_decoration(compiler, var_id, SpvDecorationLocation);
|
||||||
|
if (spvc_compiler_has_decoration(compiler, var_id, SpvDecorationLocation))
|
||||||
|
has_loc = true;
|
||||||
|
|
||||||
|
if (has_loc && !used_locations.contains(curr_loc))
|
||||||
|
{
|
||||||
|
used_locations.insert((GLint)curr_loc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (used_locations.count(next_free_loc))
|
||||||
|
++next_free_loc;
|
||||||
|
|
||||||
|
spvc_compiler_set_decoration(
|
||||||
|
compiler,
|
||||||
|
var_id,
|
||||||
|
SpvDecorationLocation,
|
||||||
|
next_free_loc);
|
||||||
|
|
||||||
|
MG_Util::Debug::LogI("[SPIRV-Cross] Auto assigned '%s' to location %d", name, next_free_loc);
|
||||||
|
used_locations.insert(next_free_loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
spvc_compiler_options options = nullptr;
|
||||||
|
spvc_compiler_create_compiler_options(compiler, &options);
|
||||||
|
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, 450);
|
||||||
|
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, SPVC_FALSE);
|
||||||
|
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_FLIP_VERTEX_Y, SPVC_TRUE);
|
||||||
|
spvc_compiler_install_compiler_options(compiler, options);
|
||||||
|
|
||||||
|
if ((result = spvc_compiler_compile(compiler, &glsl_source)) != SPVC_SUCCESS)
|
||||||
|
{
|
||||||
|
MG_Util::Debug::LogE("[SPIRV-Cross] Failed to compile: %s",
|
||||||
|
spvc_context_get_last_error_string(context));
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
output_glsl = glsl_source;
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
MG_Util::Debug::LogI("[SPIRV-Cross] GLSL output:\n%s", output_glsl.c_str());
|
||||||
|
|
||||||
|
size_t pos = output_glsl.find("\n gl_Position.y = -gl_Position.y;\n}");
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
output_glsl.replace(
|
||||||
|
pos,
|
||||||
|
strlen("\n gl_Position.y = -gl_Position.y;\n}"),
|
||||||
|
"\n gl_Position.y = -gl_Position.y;\n gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return output_glsl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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, std::vector<std::string>& outUniformBufferNames) {
|
||||||
|
if (shaderSources.empty()) return;
|
||||||
|
|
||||||
|
outUniformBufferNames.clear();
|
||||||
|
|
||||||
|
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);
|
||||||
|
// save the uniform names in order
|
||||||
|
outUniformBufferNames.emplace_back(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
MG_Util::Debug::LogD("UBO Generated:\n%s", uboBlock.c_str());
|
||||||
|
|
||||||
|
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, bool isVkGLSL) {
|
||||||
std::string infoLog;
|
std::string infoLog;
|
||||||
using namespace glslang;
|
using namespace glslang;
|
||||||
|
|
||||||
@@ -21,8 +677,12 @@ namespace MG_Util::Program {
|
|||||||
shader = new TShader(language);
|
shader = new TShader(language);
|
||||||
const char *src = source.c_str();
|
const char *src = source.c_str();
|
||||||
shader->setStrings(&src, 1);
|
shader->setStrings(&src, 1);
|
||||||
|
if (isVkGLSL) {
|
||||||
|
shader->setPreamble("#define gl_VertexID gl_VertexIndex\n"
|
||||||
|
"#define gl_InstanceID gl_InstanceIndex\n");
|
||||||
|
}
|
||||||
shader->setEnvInput(EShSourceGlsl, language, EShClientVulkan, glslVersion);
|
shader->setEnvInput(EShSourceGlsl, language, EShClientVulkan, glslVersion);
|
||||||
shader->setEnvClient(EShClientOpenGL, EShTargetOpenGL_450);
|
shader->setEnvClient(EShClientOpenGL, isVkGLSL ? EShTargetVulkan_1_3 : EShTargetOpenGL_450);
|
||||||
shader->setEnvTarget(EShTargetSpv, EShTargetSpv_1_6);
|
shader->setEnvTarget(EShTargetSpv, EShTargetSpv_1_6);
|
||||||
shader->setAutoMapLocations(true);
|
shader->setAutoMapLocations(true);
|
||||||
shader->setAutoMapBindings(true);
|
shader->setAutoMapBindings(true);
|
||||||
@@ -30,7 +690,7 @@ namespace MG_Util::Program {
|
|||||||
// Is InitResources() really correct?
|
// Is InitResources() really correct?
|
||||||
TBuiltInResource resources = InitResources();
|
TBuiltInResource resources = InitResources();
|
||||||
|
|
||||||
if (!shader->parse(&resources, glslVersion, true, EShMsgDefault)) {
|
if (!shader->parse(&resources, glslVersion, true, isVkGLSL ? EShMsgVulkanRules : EShMsgDefault)) {
|
||||||
infoLog += "Error: [glslang] Cannot compile the " + GetShaderTypeName(shaderType) + ":\n"
|
infoLog += "Error: [glslang] Cannot compile the " + GetShaderTypeName(shaderType) + ":\n"
|
||||||
+ std::to_string(shader->getInfoLog());
|
+ std::to_string(shader->getInfoLog());
|
||||||
return infoLog;
|
return infoLog;
|
||||||
@@ -45,12 +705,12 @@ namespace MG_Util::Program {
|
|||||||
std::vector<EShLanguage> usedShaderTypes;
|
std::vector<EShLanguage> usedShaderTypes;
|
||||||
TProgram program;
|
TProgram program;
|
||||||
for (GLuint shaderId : prog.attachedShaders) {
|
for (GLuint shaderId : prog.attachedShaders) {
|
||||||
auto shaderObject = state.GetShaderObject(shaderId);
|
auto* shaderObject = state.GetShaderObject(shaderId);
|
||||||
EShLanguage shLanguage = GetEShLanguageByShaderType(shaderObject.type);
|
EShLanguage shLanguage = GetEShLanguageByShaderType(shaderObject->type);
|
||||||
TShader* shader = nullptr;
|
TShader* shader = nullptr;
|
||||||
std::string infoLogOfShader = CompileGLSLToTShader(shaderObject.type, shaderObject.source, shader);
|
std::string infoLogOfShader = CompileGLSLToTShader(shaderObject->type, shaderObject->source, shader);
|
||||||
if (!infoLogOfShader.empty()) {
|
if (!infoLogOfShader.empty()) {
|
||||||
infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderObject.type) +
|
infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderObject->type) +
|
||||||
" :\n" + infoLogOfShader;
|
" :\n" + infoLogOfShader;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -62,6 +722,21 @@ namespace MG_Util::Program {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<glslang::TIoMapResolver> resolver;
|
||||||
|
for (unsigned stage = 0; stage < EShLangCount; stage++) {
|
||||||
|
auto* pResolver = program.getGlslIoResolver((EShLanguage)stage);
|
||||||
|
if (pResolver) {
|
||||||
|
resolver = std::unique_ptr<glslang::TIoMapResolver>(pResolver);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto ioMapper = std::unique_ptr<glslang::TIoMapper>(glslang::GetGlslIoMapper());
|
||||||
|
|
||||||
|
if (!program.mapIO(resolver.get(), ioMapper.get())) {
|
||||||
|
infoLog = "Error: [glslang] Cannot mapIO:\n" + std::to_string(program.getInfoLog());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
SpvOptions spvOptions;
|
SpvOptions spvOptions;
|
||||||
spvOptions.disableOptimizer = false;
|
spvOptions.disableOptimizer = false;
|
||||||
|
|
||||||
@@ -75,21 +750,40 @@ namespace MG_Util::Program {
|
|||||||
return allSpirv;
|
return allSpirv;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string &source, std::string &infoLog) {
|
std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string &source,
|
||||||
|
std::string &infoLog, bool isVkGLSL, GLenum additionalShaderType,
|
||||||
|
const std::string& additionalShaderSource
|
||||||
|
) {
|
||||||
using namespace glslang;
|
using namespace glslang;
|
||||||
|
|
||||||
TShader* shader = nullptr;
|
TShader* shader = nullptr;
|
||||||
std::string infoLogOfShader = CompileGLSLToTShader(shaderType, source, shader);
|
std::string infoLogOfShader = CompileGLSLToTShader(shaderType, source, shader, isVkGLSL);
|
||||||
if (!infoLogOfShader.empty()) {
|
if (!infoLogOfShader.empty()) {
|
||||||
infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderType) + ":\n" + infoLogOfShader;
|
infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderType) + ":\n" + infoLogOfShader;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
TProgram program;
|
TProgram program;
|
||||||
program.addShader(shader);
|
|
||||||
if (!program.link(EShMsgDefault)) {
|
if (additionalShaderType == GL_VERTEX_SHADER)
|
||||||
|
program.addShader(shader);
|
||||||
|
if (additionalShaderType && !additionalShaderSource.empty()) {
|
||||||
|
TShader* additionalShader = nullptr;
|
||||||
|
std::string additionalInfoLog = CompileGLSLToTShader(additionalShaderType, additionalShaderSource, additionalShader, isVkGLSL);
|
||||||
|
if (!additionalInfoLog.empty()) {
|
||||||
|
infoLog = "Error: [glslang] Cannot compile additional " + GetShaderTypeName(additionalShaderType) + ":\n" + additionalInfoLog;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
program.addShader(additionalShader);
|
||||||
|
}
|
||||||
|
if (additionalShaderType != GL_VERTEX_SHADER)
|
||||||
|
program.addShader(shader);
|
||||||
|
|
||||||
|
if (!program.link(isVkGLSL ? EShMsgVulkanRules : EShMsgDefault)) {
|
||||||
infoLog = "Error: [glslang] Cannot link the program of the single shader:\n" + std::to_string(program.getInfoLog());
|
infoLog = "Error: [glslang] Cannot link the program of the single shader:\n" + std::to_string(program.getInfoLog());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
program.mapIO();
|
||||||
|
|
||||||
std::vector<unsigned> spirv;
|
std::vector<unsigned> spirv;
|
||||||
|
|
||||||
SpvOptions spvOptions;
|
SpvOptions spvOptions;
|
||||||
@@ -108,7 +802,7 @@ namespace MG_Util::Program {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ankerl::unordered_set<GLint> used_locations;
|
MG_Global::unordered_set<GLint> used_locations;
|
||||||
GLint auto_location = 0;
|
GLint auto_location = 0;
|
||||||
for (auto spirv: allSpirv) {
|
for (auto spirv: allSpirv) {
|
||||||
spvc_parsed_ir ir = nullptr;
|
spvc_parsed_ir ir = nullptr;
|
||||||
@@ -169,10 +863,42 @@ namespace MG_Util::Program {
|
|||||||
SpvDecorationLocation);
|
SpvDecorationLocation);
|
||||||
GLint final_location;
|
GLint final_location;
|
||||||
|
|
||||||
if (spirv_location > 0) {
|
spvc_type_id type_id = res.type_id;
|
||||||
if (used_locations.find(spirv_location) != used_locations.end()) {
|
spvc_type type = spvc_compiler_get_type_handle(compiler, type_id);
|
||||||
infoLog += "\nLocation conflict for uniform: " + std::string(name);
|
spvc_basetype base_type = spvc_type_get_basetype(type);
|
||||||
continue;
|
GLenum gl_type = GL_NONE;
|
||||||
|
|
||||||
|
if (spirv_location >= 0 && base_type != SPVC_BASETYPE_SAMPLED_IMAGE) {
|
||||||
|
auto conflict_it = used_locations.find(spirv_location);
|
||||||
|
if (conflict_it != used_locations.end()) {
|
||||||
|
// Check if the conflicting uniform is a sampler
|
||||||
|
std::string conflicting_name;
|
||||||
|
for (const auto& entry : prog.uniformLocations) {
|
||||||
|
if (entry.second == spirv_location) {
|
||||||
|
conflicting_name = entry.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(conflicting_name == std::string(name)) {
|
||||||
|
continue;
|
||||||
|
} else if (!conflicting_name.empty() && prog.uniformValues.count(conflicting_name) &&
|
||||||
|
MG_GL::GL::IsSamplerType(prog.uniformValues[conflicting_name].type)) {
|
||||||
|
// Reassign location for the sampler
|
||||||
|
GLint new_sampler_loc = auto_location++;
|
||||||
|
while (used_locations.find(new_sampler_loc) != used_locations.end()) new_sampler_loc++;
|
||||||
|
prog.uniformLocations[conflicting_name] = new_sampler_loc;
|
||||||
|
used_locations.erase(conflict_it); // Remove old sampler location
|
||||||
|
used_locations.insert(new_sampler_loc); // Add new sampler location
|
||||||
|
} else {
|
||||||
|
infoLog += "\nLocation conflict for uniform: " + std::string(name) + " at location " + std::to_string(spirv_location);
|
||||||
|
infoLog += "\nExisting uniforms and locations:";
|
||||||
|
for (const auto& entry : prog.uniformLocations) {
|
||||||
|
infoLog += "\n " + entry.first + ": " + std::to_string(entry.second);
|
||||||
|
}
|
||||||
|
infoLog += "\nUsed locations set:";
|
||||||
|
for (GLint loc : used_locations) infoLog += " " + std::to_string(loc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
final_location = spirv_location;
|
final_location = spirv_location;
|
||||||
} else {
|
} else {
|
||||||
@@ -184,11 +910,6 @@ namespace MG_Util::Program {
|
|||||||
|
|
||||||
used_locations.insert(final_location);
|
used_locations.insert(final_location);
|
||||||
|
|
||||||
spvc_type_id type_id = res.type_id;
|
|
||||||
spvc_type type = spvc_compiler_get_type_handle(compiler, type_id);
|
|
||||||
spvc_basetype base_type = spvc_type_get_basetype(type);
|
|
||||||
GLenum gl_type = GL_NONE;
|
|
||||||
|
|
||||||
if (base_type == SPVC_BASETYPE_SAMPLED_IMAGE) {
|
if (base_type == SPVC_BASETYPE_SAMPLED_IMAGE) {
|
||||||
SpvDim dim = spvc_type_get_image_dimension(type);
|
SpvDim dim = spvc_type_get_image_dimension(type);
|
||||||
bool is_array = spvc_type_get_image_arrayed(type);
|
bool is_array = spvc_type_get_image_arrayed(type);
|
||||||
@@ -401,7 +1122,7 @@ namespace MG_Util::Program {
|
|||||||
spvc_context_destroy(context);
|
spvc_context_destroy(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES) {
|
std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES, bool isVkGLSL) {
|
||||||
spvc_context context = nullptr;
|
spvc_context context = nullptr;
|
||||||
spvc_parsed_ir ir = nullptr;
|
spvc_parsed_ir ir = nullptr;
|
||||||
spvc_compiler compiler_glsl = nullptr;
|
spvc_compiler compiler_glsl = nullptr;
|
||||||
@@ -420,12 +1141,15 @@ namespace MG_Util::Program {
|
|||||||
spvc_compiler_create_shader_resources(compiler_glsl, &resources);
|
spvc_compiler_create_shader_resources(compiler_glsl, &resources);
|
||||||
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count);
|
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count);
|
||||||
spvc_compiler_create_compiler_options(compiler_glsl, &options);
|
spvc_compiler_create_compiler_options(compiler_glsl, &options);
|
||||||
|
|
||||||
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, glslVersion);
|
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, glslVersion);
|
||||||
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, isES ? SPVC_TRUE : SPVC_FALSE);
|
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, isES ? SPVC_TRUE : SPVC_FALSE);
|
||||||
|
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS, isVkGLSL ? SPVC_TRUE : SPVC_FALSE);
|
||||||
spvc_compiler_install_compiler_options(compiler_glsl, options);
|
spvc_compiler_install_compiler_options(compiler_glsl, options);
|
||||||
spvc_compiler_compile(compiler_glsl, &result);
|
spvc_compiler_compile(compiler_glsl, &result);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
MG_Util::Debug::LogE("Failed to compile the shader to GLSL: %s", spvc_context_get_last_error_string(context));
|
||||||
return{};
|
return{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#ifndef MOBILEGL_GLSLTOOL_H
|
#ifndef MOBILEGL_GLSLTOOL_H
|
||||||
#define MOBILEGL_GLSLTOOL_H
|
#define MOBILEGL_GLSLTOOL_H
|
||||||
|
|
||||||
#include "../../Includes.h"
|
|
||||||
|
|
||||||
namespace MG_Util::Program {
|
namespace MG_Util::Program {
|
||||||
inline static TBuiltInResource InitResources()
|
inline static TBuiltInResource InitResources()
|
||||||
{
|
{
|
||||||
@@ -173,11 +171,22 @@ namespace MG_Util::Program {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string& source, std::string& infoLog);
|
std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string& source,
|
||||||
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader);
|
std::string& infoLog, bool isVkGLSL = false, GLenum additionalShaderType = 0,
|
||||||
|
const std::string& additionalShaderSource = {});
|
||||||
|
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source,
|
||||||
|
glslang::TShader *&shader, bool isVkGLSL = false);
|
||||||
std::vector<std::vector<unsigned>> CompileMultipleShadersToSPIRV(const ProgramState& state, ProgramObject& prog, std::string& infoLog);
|
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);
|
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::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES, bool isVkGLSL = false);
|
||||||
|
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, std::vector<std::string>& outUniformBufferNames);
|
||||||
|
std::string BindInputLayoutLocationsForGLSL(std::vector<uint32_t>& spirv,
|
||||||
|
MG_Global::unordered_map<std::string, GLint>&
|
||||||
|
name_location_map);
|
||||||
|
void RenameGLSLBuiltinsForVulkan(std::string &src);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //MOBILEGL_GLSLTOOL_H
|
#endif //MOBILEGL_GLSLTOOL_H
|
||||||
|
|||||||
Reference in New Issue
Block a user