video_core: Rewrite custom textures

This commit is contained in:
GPUCode
2023-02-18 22:36:38 +02:00
parent 77961d2f07
commit c7aa107392
55 changed files with 19911 additions and 931 deletions

3
.gitmodules vendored
View File

@ -70,6 +70,3 @@
[submodule "sirit"]
path = externals/sirit
url = https://github.com/GPUCode/sirit
[submodule "externals/libspng"]
path = externals/libspng
url = https://github.com/randy408/libspng

View File

@ -1,25 +1,27 @@
/*
OpenGL, OpenGL ES loader generated by glad 0.1.36 on Fri Sep 9 09:22:43 2022.
OpenGL, OpenGL ES loader generated by glad 0.1.36 on Tue Feb 21 16:13:52 2023.
Language/Generator: C/C++
Specification: gl
APIs: gl=4.4, gles2=3.2
APIs: gl=4.6, gles2=3.2
Profile: core
Extensions:
GL_ARB_buffer_storage,
GL_ARB_direct_state_access,
GL_ARB_texture_compression_bptc,
GL_EXT_buffer_storage,
GL_EXT_clip_cull_distance
GL_EXT_clip_cull_distance,
GL_EXT_texture_compression_s3tc
Loader: True
Local files: False
Omit khrplatform: False
Reproducible: False
Commandline:
--profile="core" --api="gl=4.4,gles2=3.2" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_EXT_buffer_storage,GL_EXT_clip_cull_distance"
--profile="core" --api="gl=4.6,gles2=3.2" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_ARB_texture_compression_bptc,GL_EXT_buffer_storage,GL_EXT_clip_cull_distance,GL_EXT_texture_compression_s3tc"
Online:
https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D4.4&api=gles2%3D3.2&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_EXT_buffer_storage&extensions=GL_EXT_clip_cull_distance
https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D4.6&api=gles2%3D3.2&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_ARB_texture_compression_bptc&extensions=GL_EXT_buffer_storage&extensions=GL_EXT_clip_cull_distance&extensions=GL_EXT_texture_compression_s3tc
*/
@ -1472,6 +1474,62 @@ typedef void (APIENTRY *GLVULKANPROCNV)(void);
#define GL_QUERY_BUFFER_BINDING 0x9193
#define GL_QUERY_RESULT_NO_WAIT 0x9194
#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
#define GL_CONTEXT_LOST 0x0507
#define GL_NEGATIVE_ONE_TO_ONE 0x935E
#define GL_ZERO_TO_ONE 0x935F
#define GL_CLIP_ORIGIN 0x935C
#define GL_CLIP_DEPTH_MODE 0x935D
#define GL_QUERY_WAIT_INVERTED 0x8E17
#define GL_QUERY_NO_WAIT_INVERTED 0x8E18
#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19
#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A
#define GL_MAX_CULL_DISTANCES 0x82F9
#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
#define GL_TEXTURE_TARGET 0x1006
#define GL_QUERY_TARGET 0x82EA
#define GL_GUILTY_CONTEXT_RESET 0x8253
#define GL_INNOCENT_CONTEXT_RESET 0x8254
#define GL_UNKNOWN_CONTEXT_RESET 0x8255
#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
#define GL_LOSE_CONTEXT_ON_RESET 0x8252
#define GL_NO_RESET_NOTIFICATION 0x8261
#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
#define GL_COLOR_TABLE 0x80D0
#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
#define GL_PROXY_COLOR_TABLE 0x80D3
#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
#define GL_CONVOLUTION_1D 0x8010
#define GL_CONVOLUTION_2D 0x8011
#define GL_SEPARABLE_2D 0x8012
#define GL_HISTOGRAM 0x8024
#define GL_PROXY_HISTOGRAM 0x8025
#define GL_MINMAX 0x802E
#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
#define GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551
#define GL_SPIR_V_BINARY 0x9552
#define GL_PARAMETER_BUFFER 0x80EE
#define GL_PARAMETER_BUFFER_BINDING 0x80EF
#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
#define GL_VERTICES_SUBMITTED 0x82EE
#define GL_PRIMITIVES_SUBMITTED 0x82EF
#define GL_VERTEX_SHADER_INVOCATIONS 0x82F0
#define GL_TESS_CONTROL_SHADER_PATCHES 0x82F1
#define GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2
#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3
#define GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4
#define GL_COMPUTE_SHADER_INVOCATIONS 0x82F5
#define GL_CLIPPING_INPUT_PRIMITIVES 0x82F6
#define GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7
#define GL_POLYGON_OFFSET_CLAMP 0x8E1B
#define GL_SPIR_V_EXTENSIONS 0x9553
#define GL_NUM_SPIR_V_EXTENSIONS 0x9554
#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
#define GL_TRANSFORM_FEEDBACK_OVERFLOW 0x82EC
#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW 0x82ED
#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
#define GL_RED_BITS 0x0D52
#define GL_GREEN_BITS 0x0D53
@ -1501,14 +1559,6 @@ typedef void (APIENTRY *GLVULKANPROCNV)(void);
#define GL_HSL_COLOR 0x92AF
#define GL_HSL_LUMINOSITY 0x92B0
#define GL_PRIMITIVE_BOUNDING_BOX 0x92BE
#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
#define GL_LOSE_CONTEXT_ON_RESET 0x8252
#define GL_GUILTY_CONTEXT_RESET 0x8253
#define GL_INNOCENT_CONTEXT_RESET 0x8254
#define GL_UNKNOWN_CONTEXT_RESET 0x8255
#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
#define GL_NO_RESET_NOTIFICATION 0x8261
#define GL_CONTEXT_LOST 0x0507
#define GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0
#define GL_COMPRESSED_RGBA_ASTC_5x4 0x93B1
#define GL_COMPRESSED_RGBA_ASTC_5x5 0x93B2
@ -3324,73 +3374,12 @@ typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERSPROC)(GLuint first, GLsizei count,
GLAPI PFNGLBINDVERTEXBUFFERSPROC glad_glBindVertexBuffers;
#define glBindVertexBuffers glad_glBindVertexBuffers
#endif
#ifndef GL_ES_VERSION_2_0
#define GL_ES_VERSION_2_0 1
GLAPI int GLAD_GL_ES_VERSION_2_0;
#endif
#ifndef GL_ES_VERSION_3_0
#define GL_ES_VERSION_3_0 1
GLAPI int GLAD_GL_ES_VERSION_3_0;
#endif
#ifndef GL_ES_VERSION_3_1
#define GL_ES_VERSION_3_1 1
GLAPI int GLAD_GL_ES_VERSION_3_1;
typedef void (APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield barriers);
GLAPI PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion;
#define glMemoryBarrierByRegion glad_glMemoryBarrierByRegion
#endif
#ifndef GL_ES_VERSION_3_2
#define GL_ES_VERSION_3_2 1
GLAPI int GLAD_GL_ES_VERSION_3_2;
typedef void (APIENTRYP PFNGLBLENDBARRIERPROC)(void);
GLAPI PFNGLBLENDBARRIERPROC glad_glBlendBarrier;
#define glBlendBarrier glad_glBlendBarrier
typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
GLAPI PFNGLPRIMITIVEBOUNDINGBOXPROC glad_glPrimitiveBoundingBox;
#define glPrimitiveBoundingBox glad_glPrimitiveBoundingBox
typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC)(void);
GLAPI PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus;
#define glGetGraphicsResetStatus glad_glGetGraphicsResetStatus
typedef void (APIENTRYP PFNGLREADNPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
GLAPI PFNGLREADNPIXELSPROC glad_glReadnPixels;
#define glReadnPixels glad_glReadnPixels
typedef void (APIENTRYP PFNGLGETNUNIFORMFVPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
GLAPI PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv;
#define glGetnUniformfv glad_glGetnUniformfv
typedef void (APIENTRYP PFNGLGETNUNIFORMIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLint *params);
GLAPI PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv;
#define glGetnUniformiv glad_glGetnUniformiv
typedef void (APIENTRYP PFNGLGETNUNIFORMUIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint *params);
GLAPI PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv;
#define glGetnUniformuiv glad_glGetnUniformuiv
#endif
#define GL_TEXTURE_TARGET 0x1006
#define GL_QUERY_TARGET 0x82EA
#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
#define GL_MAP_COHERENT_BIT_EXT 0x0080
#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
#define GL_CLIENT_STORAGE_BIT_EXT 0x0200
#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
#define GL_MAX_CLIP_DISTANCES_EXT 0x0D32
#define GL_MAX_CULL_DISTANCES_EXT 0x82F9
#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
#define GL_CLIP_DISTANCE0_EXT 0x3000
#define GL_CLIP_DISTANCE1_EXT 0x3001
#define GL_CLIP_DISTANCE2_EXT 0x3002
#define GL_CLIP_DISTANCE3_EXT 0x3003
#define GL_CLIP_DISTANCE4_EXT 0x3004
#define GL_CLIP_DISTANCE5_EXT 0x3005
#define GL_CLIP_DISTANCE6_EXT 0x3006
#define GL_CLIP_DISTANCE7_EXT 0x3007
#ifndef GL_ARB_buffer_storage
#define GL_ARB_buffer_storage 1
GLAPI int GLAD_GL_ARB_buffer_storage;
#endif
#ifndef GL_ARB_direct_state_access
#define GL_ARB_direct_state_access 1
GLAPI int GLAD_GL_ARB_direct_state_access;
#ifndef GL_VERSION_4_5
#define GL_VERSION_4_5 1
GLAPI int GLAD_GL_VERSION_4_5;
typedef void (APIENTRYP PFNGLCLIPCONTROLPROC)(GLenum origin, GLenum depth);
GLAPI PFNGLCLIPCONTROLPROC glad_glClipControl;
#define glClipControl glad_glClipControl
typedef void (APIENTRYP PFNGLCREATETRANSFORMFEEDBACKSPROC)(GLsizei n, GLuint *ids);
GLAPI PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks;
#define glCreateTransformFeedbacks glad_glCreateTransformFeedbacks
@ -3682,6 +3671,158 @@ GLAPI PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v;
typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTUIVPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
GLAPI PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv;
#define glGetQueryBufferObjectuiv glad_glGetQueryBufferObjectuiv
typedef void (APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield barriers);
GLAPI PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion;
#define glMemoryBarrierByRegion glad_glMemoryBarrierByRegion
typedef void (APIENTRYP PFNGLGETTEXTURESUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
GLAPI PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage;
#define glGetTextureSubImage glad_glGetTextureSubImage
typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void *pixels);
GLAPI PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage;
#define glGetCompressedTextureSubImage glad_glGetCompressedTextureSubImage
typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC)(void);
GLAPI PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus;
#define glGetGraphicsResetStatus glad_glGetGraphicsResetStatus
typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint lod, GLsizei bufSize, void *pixels);
GLAPI PFNGLGETNCOMPRESSEDTEXIMAGEPROC glad_glGetnCompressedTexImage;
#define glGetnCompressedTexImage glad_glGetnCompressedTexImage
typedef void (APIENTRYP PFNGLGETNTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
GLAPI PFNGLGETNTEXIMAGEPROC glad_glGetnTexImage;
#define glGetnTexImage glad_glGetnTexImage
typedef void (APIENTRYP PFNGLGETNUNIFORMDVPROC)(GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
GLAPI PFNGLGETNUNIFORMDVPROC glad_glGetnUniformdv;
#define glGetnUniformdv glad_glGetnUniformdv
typedef void (APIENTRYP PFNGLGETNUNIFORMFVPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
GLAPI PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv;
#define glGetnUniformfv glad_glGetnUniformfv
typedef void (APIENTRYP PFNGLGETNUNIFORMIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLint *params);
GLAPI PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv;
#define glGetnUniformiv glad_glGetnUniformiv
typedef void (APIENTRYP PFNGLGETNUNIFORMUIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint *params);
GLAPI PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv;
#define glGetnUniformuiv glad_glGetnUniformuiv
typedef void (APIENTRYP PFNGLREADNPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
GLAPI PFNGLREADNPIXELSPROC glad_glReadnPixels;
#define glReadnPixels glad_glReadnPixels
typedef void (APIENTRYP PFNGLGETNMAPDVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
GLAPI PFNGLGETNMAPDVPROC glad_glGetnMapdv;
#define glGetnMapdv glad_glGetnMapdv
typedef void (APIENTRYP PFNGLGETNMAPFVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
GLAPI PFNGLGETNMAPFVPROC glad_glGetnMapfv;
#define glGetnMapfv glad_glGetnMapfv
typedef void (APIENTRYP PFNGLGETNMAPIVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLint *v);
GLAPI PFNGLGETNMAPIVPROC glad_glGetnMapiv;
#define glGetnMapiv glad_glGetnMapiv
typedef void (APIENTRYP PFNGLGETNPIXELMAPFVPROC)(GLenum map, GLsizei bufSize, GLfloat *values);
GLAPI PFNGLGETNPIXELMAPFVPROC glad_glGetnPixelMapfv;
#define glGetnPixelMapfv glad_glGetnPixelMapfv
typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVPROC)(GLenum map, GLsizei bufSize, GLuint *values);
GLAPI PFNGLGETNPIXELMAPUIVPROC glad_glGetnPixelMapuiv;
#define glGetnPixelMapuiv glad_glGetnPixelMapuiv
typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVPROC)(GLenum map, GLsizei bufSize, GLushort *values);
GLAPI PFNGLGETNPIXELMAPUSVPROC glad_glGetnPixelMapusv;
#define glGetnPixelMapusv glad_glGetnPixelMapusv
typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEPROC)(GLsizei bufSize, GLubyte *pattern);
GLAPI PFNGLGETNPOLYGONSTIPPLEPROC glad_glGetnPolygonStipple;
#define glGetnPolygonStipple glad_glGetnPolygonStipple
typedef void (APIENTRYP PFNGLGETNCOLORTABLEPROC)(GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
GLAPI PFNGLGETNCOLORTABLEPROC glad_glGetnColorTable;
#define glGetnColorTable glad_glGetnColorTable
typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERPROC)(GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
GLAPI PFNGLGETNCONVOLUTIONFILTERPROC glad_glGetnConvolutionFilter;
#define glGetnConvolutionFilter glad_glGetnConvolutionFilter
typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERPROC)(GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
GLAPI PFNGLGETNSEPARABLEFILTERPROC glad_glGetnSeparableFilter;
#define glGetnSeparableFilter glad_glGetnSeparableFilter
typedef void (APIENTRYP PFNGLGETNHISTOGRAMPROC)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
GLAPI PFNGLGETNHISTOGRAMPROC glad_glGetnHistogram;
#define glGetnHistogram glad_glGetnHistogram
typedef void (APIENTRYP PFNGLGETNMINMAXPROC)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
GLAPI PFNGLGETNMINMAXPROC glad_glGetnMinmax;
#define glGetnMinmax glad_glGetnMinmax
typedef void (APIENTRYP PFNGLTEXTUREBARRIERPROC)(void);
GLAPI PFNGLTEXTUREBARRIERPROC glad_glTextureBarrier;
#define glTextureBarrier glad_glTextureBarrier
#endif
#ifndef GL_VERSION_4_6
#define GL_VERSION_4_6 1
GLAPI int GLAD_GL_VERSION_4_6;
typedef void (APIENTRYP PFNGLSPECIALIZESHADERPROC)(GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue);
GLAPI PFNGLSPECIALIZESHADERPROC glad_glSpecializeShader;
#define glSpecializeShader glad_glSpecializeShader
typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC)(GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
GLAPI PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glad_glMultiDrawArraysIndirectCount;
#define glMultiDrawArraysIndirectCount glad_glMultiDrawArraysIndirectCount
typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC)(GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
GLAPI PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glad_glMultiDrawElementsIndirectCount;
#define glMultiDrawElementsIndirectCount glad_glMultiDrawElementsIndirectCount
typedef void (APIENTRYP PFNGLPOLYGONOFFSETCLAMPPROC)(GLfloat factor, GLfloat units, GLfloat clamp);
GLAPI PFNGLPOLYGONOFFSETCLAMPPROC glad_glPolygonOffsetClamp;
#define glPolygonOffsetClamp glad_glPolygonOffsetClamp
#endif
#ifndef GL_ES_VERSION_2_0
#define GL_ES_VERSION_2_0 1
GLAPI int GLAD_GL_ES_VERSION_2_0;
#endif
#ifndef GL_ES_VERSION_3_0
#define GL_ES_VERSION_3_0 1
GLAPI int GLAD_GL_ES_VERSION_3_0;
#endif
#ifndef GL_ES_VERSION_3_1
#define GL_ES_VERSION_3_1 1
GLAPI int GLAD_GL_ES_VERSION_3_1;
#endif
#ifndef GL_ES_VERSION_3_2
#define GL_ES_VERSION_3_2 1
GLAPI int GLAD_GL_ES_VERSION_3_2;
typedef void (APIENTRYP PFNGLBLENDBARRIERPROC)(void);
GLAPI PFNGLBLENDBARRIERPROC glad_glBlendBarrier;
#define glBlendBarrier glad_glBlendBarrier
typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
GLAPI PFNGLPRIMITIVEBOUNDINGBOXPROC glad_glPrimitiveBoundingBox;
#define glPrimitiveBoundingBox glad_glPrimitiveBoundingBox
#endif
#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
#define GL_MAP_COHERENT_BIT_EXT 0x0080
#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
#define GL_CLIENT_STORAGE_BIT_EXT 0x0200
#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
#define GL_MAX_CLIP_DISTANCES_EXT 0x0D32
#define GL_MAX_CULL_DISTANCES_EXT 0x82F9
#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
#define GL_CLIP_DISTANCE0_EXT 0x3000
#define GL_CLIP_DISTANCE1_EXT 0x3001
#define GL_CLIP_DISTANCE2_EXT 0x3002
#define GL_CLIP_DISTANCE3_EXT 0x3003
#define GL_CLIP_DISTANCE4_EXT 0x3004
#define GL_CLIP_DISTANCE5_EXT 0x3005
#define GL_CLIP_DISTANCE6_EXT 0x3006
#define GL_CLIP_DISTANCE7_EXT 0x3007
#ifndef GL_ARB_buffer_storage
#define GL_ARB_buffer_storage 1
GLAPI int GLAD_GL_ARB_buffer_storage;
#endif
#ifndef GL_ARB_direct_state_access
#define GL_ARB_direct_state_access 1
GLAPI int GLAD_GL_ARB_direct_state_access;
#endif
#ifndef GL_ARB_texture_compression_bptc
#define GL_ARB_texture_compression_bptc 1
GLAPI int GLAD_GL_ARB_texture_compression_bptc;
#endif
#ifndef GL_EXT_texture_compression_s3tc
#define GL_EXT_texture_compression_s3tc 1
GLAPI int GLAD_GL_EXT_texture_compression_s3tc;
#endif
#ifndef GL_EXT_buffer_storage
#define GL_EXT_buffer_storage 1
@ -3694,6 +3835,10 @@ GLAPI PFNGLBUFFERSTORAGEEXTPROC glad_glBufferStorageEXT;
#define GL_EXT_clip_cull_distance 1
GLAPI int GLAD_GL_EXT_clip_cull_distance;
#endif
#ifndef GL_EXT_texture_compression_s3tc
#define GL_EXT_texture_compression_s3tc 1
GLAPI int GLAD_GL_EXT_texture_compression_s3tc;
#endif
#ifdef __cplusplus
}

View File

@ -1,25 +1,27 @@
/*
OpenGL, OpenGL ES loader generated by glad 0.1.36 on Fri Sep 9 09:22:43 2022.
OpenGL, OpenGL ES loader generated by glad 0.1.36 on Tue Feb 21 16:13:52 2023.
Language/Generator: C/C++
Specification: gl
APIs: gl=4.4, gles2=3.2
APIs: gl=4.6, gles2=3.2
Profile: core
Extensions:
GL_ARB_buffer_storage,
GL_ARB_direct_state_access,
GL_ARB_texture_compression_bptc,
GL_EXT_buffer_storage,
GL_EXT_clip_cull_distance
GL_EXT_clip_cull_distance,
GL_EXT_texture_compression_s3tc
Loader: True
Local files: False
Omit khrplatform: False
Reproducible: False
Commandline:
--profile="core" --api="gl=4.4,gles2=3.2" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_EXT_buffer_storage,GL_EXT_clip_cull_distance"
--profile="core" --api="gl=4.6,gles2=3.2" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_ARB_texture_compression_bptc,GL_EXT_buffer_storage,GL_EXT_clip_cull_distance,GL_EXT_texture_compression_s3tc"
Online:
https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D4.4&api=gles2%3D3.2&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_EXT_buffer_storage&extensions=GL_EXT_clip_cull_distance
https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D4.6&api=gles2%3D3.2&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_ARB_texture_compression_bptc&extensions=GL_EXT_buffer_storage&extensions=GL_EXT_clip_cull_distance&extensions=GL_EXT_texture_compression_s3tc
*/
#include <stdio.h>
@ -275,6 +277,8 @@ int GLAD_GL_VERSION_4_1 = 0;
int GLAD_GL_VERSION_4_2 = 0;
int GLAD_GL_VERSION_4_3 = 0;
int GLAD_GL_VERSION_4_4 = 0;
int GLAD_GL_VERSION_4_5 = 0;
int GLAD_GL_VERSION_4_6 = 0;
int GLAD_GL_ES_VERSION_2_0 = 0;
int GLAD_GL_ES_VERSION_3_0 = 0;
int GLAD_GL_ES_VERSION_3_1 = 0;
@ -302,6 +306,7 @@ PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
PFNGLBINDSAMPLERSPROC glad_glBindSamplers = NULL;
PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit = NULL;
PFNGLBINDTEXTURESPROC glad_glBindTextures = NULL;
PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback = NULL;
PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
@ -318,10 +323,12 @@ PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
PFNGLBLENDFUNCSEPARATEIPROC glad_glBlendFuncSeparatei = NULL;
PFNGLBLENDFUNCIPROC glad_glBlendFunci = NULL;
PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer = NULL;
PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
PFNGLBUFFERSTORAGEPROC glad_glBufferStorage = NULL;
PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus = NULL;
PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
PFNGLCLEARPROC glad_glClear = NULL;
PFNGLCLEARBUFFERDATAPROC glad_glClearBufferData = NULL;
@ -333,10 +340,17 @@ PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL;
PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData = NULL;
PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv = NULL;
PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
PFNGLCLEARTEXIMAGEPROC glad_glClearTexImage = NULL;
PFNGLCLEARTEXSUBIMAGEPROC glad_glClearTexSubImage = NULL;
PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
PFNGLCLIPCONTROLPROC glad_glClipControl = NULL;
PFNGLCOLORMASKPROC glad_glColorMask = NULL;
PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
@ -350,16 +364,32 @@ PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D = NULL;
PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData = NULL;
PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData = NULL;
PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D = NULL;
PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D = NULL;
PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D = NULL;
PFNGLCREATEBUFFERSPROC glad_glCreateBuffers = NULL;
PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers = NULL;
PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines = NULL;
PFNGLCREATEQUERIESPROC glad_glCreateQueries = NULL;
PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers = NULL;
PFNGLCREATESAMPLERSPROC glad_glCreateSamplers = NULL;
PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv = NULL;
PFNGLCREATETEXTURESPROC glad_glCreateTextures = NULL;
PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks = NULL;
PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays = NULL;
PFNGLCULLFACEPROC glad_glCullFace = NULL;
PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL;
PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL;
@ -384,6 +414,7 @@ PFNGLDEPTHRANGEINDEXEDPROC glad_glDepthRangeIndexed = NULL;
PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL;
PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
PFNGLDISABLEPROC glad_glDisable = NULL;
PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib = NULL;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
PFNGLDISABLEIPROC glad_glDisablei = NULL;
PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute = NULL;
@ -408,6 +439,7 @@ PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glad_glDrawTransformFeedbackInstanced =
PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glad_glDrawTransformFeedbackStream = NULL;
PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glad_glDrawTransformFeedbackStreamInstanced = NULL;
PFNGLENABLEPROC glad_glEnable = NULL;
PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib = NULL;
PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
PFNGLENABLEIPROC glad_glEnablei = NULL;
PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
@ -418,6 +450,7 @@ PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
PFNGLFINISHPROC glad_glFinish = NULL;
PFNGLFLUSHPROC glad_glFlush = NULL;
PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange = NULL;
PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri = NULL;
PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
@ -436,6 +469,7 @@ PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks = NULL;
PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap = NULL;
PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glad_glGetActiveAtomicCounterBufferiv = NULL;
PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
PFNGLGETACTIVESUBROUTINENAMEPROC glad_glGetActiveSubroutineName = NULL;
@ -455,6 +489,8 @@ PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage = NULL;
PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage = NULL;
PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL;
PFNGLGETDOUBLEI_VPROC glad_glGetDoublei_v = NULL;
PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
@ -473,6 +509,13 @@ PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
PFNGLGETINTERNALFORMATI64VPROC glad_glGetInternalformati64v = NULL;
PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ = NULL;
PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v = NULL;
PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv = NULL;
PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv = NULL;
PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData = NULL;
PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv = NULL;
PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv = NULL;
PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv = NULL;
PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL;
PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL;
PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
@ -488,6 +531,10 @@ PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName = NULL;
PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv = NULL;
PFNGLGETPROGRAMSTAGEIVPROC glad_glGetProgramStageiv = NULL;
PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v = NULL;
PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv = NULL;
PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v = NULL;
PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv = NULL;
PFNGLGETQUERYINDEXEDIVPROC glad_glGetQueryIndexediv = NULL;
PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
@ -515,7 +562,18 @@ PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage = NULL;
PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv = NULL;
PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv = NULL;
PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv = NULL;
PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv = NULL;
PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv = NULL;
PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv = NULL;
PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage = NULL;
PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v = NULL;
PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v = NULL;
PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv = NULL;
PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
@ -524,6 +582,9 @@ PFNGLGETUNIFORMDVPROC glad_glGetUniformdv = NULL;
PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv = NULL;
PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv = NULL;
PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv = NULL;
PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
PFNGLGETVERTEXATTRIBLDVPROC glad_glGetVertexAttribLdv = NULL;
@ -531,6 +592,21 @@ PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
PFNGLGETNCOLORTABLEPROC glad_glGetnColorTable = NULL;
PFNGLGETNCOMPRESSEDTEXIMAGEPROC glad_glGetnCompressedTexImage = NULL;
PFNGLGETNCONVOLUTIONFILTERPROC glad_glGetnConvolutionFilter = NULL;
PFNGLGETNHISTOGRAMPROC glad_glGetnHistogram = NULL;
PFNGLGETNMAPDVPROC glad_glGetnMapdv = NULL;
PFNGLGETNMAPFVPROC glad_glGetnMapfv = NULL;
PFNGLGETNMAPIVPROC glad_glGetnMapiv = NULL;
PFNGLGETNMINMAXPROC glad_glGetnMinmax = NULL;
PFNGLGETNPIXELMAPFVPROC glad_glGetnPixelMapfv = NULL;
PFNGLGETNPIXELMAPUIVPROC glad_glGetnPixelMapuiv = NULL;
PFNGLGETNPIXELMAPUSVPROC glad_glGetnPixelMapusv = NULL;
PFNGLGETNPOLYGONSTIPPLEPROC glad_glGetnPolygonStipple = NULL;
PFNGLGETNSEPARABLEFILTERPROC glad_glGetnSeparableFilter = NULL;
PFNGLGETNTEXIMAGEPROC glad_glGetnTexImage = NULL;
PFNGLGETNUNIFORMDVPROC glad_glGetnUniformdv = NULL;
PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv = NULL;
PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv = NULL;
PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv = NULL;
@ -538,6 +614,8 @@ PFNGLHINTPROC glad_glHint = NULL;
PFNGLINVALIDATEBUFFERDATAPROC glad_glInvalidateBufferData = NULL;
PFNGLINVALIDATEBUFFERSUBDATAPROC glad_glInvalidateBufferSubData = NULL;
PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer = NULL;
PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData = NULL;
PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData = NULL;
PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer = NULL;
PFNGLINVALIDATETEXIMAGEPROC glad_glInvalidateTexImage = NULL;
PFNGLINVALIDATETEXSUBIMAGEPROC glad_glInvalidateTexSubImage = NULL;
@ -560,14 +638,18 @@ PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
PFNGLLOGICOPPROC glad_glLogicOp = NULL;
PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer = NULL;
PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange = NULL;
PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier = NULL;
PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion = NULL;
PFNGLMINSAMPLESHADINGPROC glad_glMinSampleShading = NULL;
PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
PFNGLMULTIDRAWARRAYSINDIRECTPROC glad_glMultiDrawArraysIndirect = NULL;
PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glad_glMultiDrawArraysIndirectCount = NULL;
PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
PFNGLMULTIDRAWELEMENTSINDIRECTPROC glad_glMultiDrawElementsIndirect = NULL;
PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glad_glMultiDrawElementsIndirectCount = NULL;
PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
@ -576,6 +658,18 @@ PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData = NULL;
PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage = NULL;
PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData = NULL;
PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer = NULL;
PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers = NULL;
PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri = NULL;
PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer = NULL;
PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer = NULL;
PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture = NULL;
PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer = NULL;
PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage = NULL;
PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample = NULL;
PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL;
@ -592,6 +686,7 @@ PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
PFNGLPOLYGONOFFSETCLAMPPROC glad_glPolygonOffsetClamp = NULL;
PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL;
PFNGLPRIMITIVEBOUNDINGBOXPROC glad_glPrimitiveBoundingBox = NULL;
PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
@ -674,6 +769,7 @@ PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL;
PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
PFNGLSHADERSTORAGEBLOCKBINDINGPROC glad_glShaderStorageBlockBinding = NULL;
PFNGLSPECIALIZESHADERPROC glad_glSpecializeShader = NULL;
PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
@ -709,7 +805,26 @@ PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample = NULL;
PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
PFNGLTEXTUREBARRIERPROC glad_glTextureBarrier = NULL;
PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer = NULL;
PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange = NULL;
PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv = NULL;
PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv = NULL;
PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf = NULL;
PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv = NULL;
PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri = NULL;
PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv = NULL;
PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D = NULL;
PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D = NULL;
PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample = NULL;
PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D = NULL;
PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample = NULL;
PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D = NULL;
PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D = NULL;
PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D = NULL;
PFNGLTEXTUREVIEWPROC glad_glTextureView = NULL;
PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase = NULL;
PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange = NULL;
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
PFNGLUNIFORM1DPROC glad_glUniform1d = NULL;
PFNGLUNIFORM1DVPROC glad_glUniform1dv = NULL;
@ -764,10 +879,19 @@ PFNGLUNIFORMMATRIX4X3DVPROC glad_glUniformMatrix4x3dv = NULL;
PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
PFNGLUNIFORMSUBROUTINESUIVPROC glad_glUniformSubroutinesuiv = NULL;
PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer = NULL;
PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages = NULL;
PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline = NULL;
PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding = NULL;
PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat = NULL;
PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat = NULL;
PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat = NULL;
PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor = NULL;
PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer = NULL;
PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer = NULL;
PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers = NULL;
PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
@ -862,105 +986,10 @@ PFNGLVIEWPORTINDEXEDFVPROC glad_glViewportIndexedfv = NULL;
PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
int GLAD_GL_ARB_buffer_storage = 0;
int GLAD_GL_ARB_direct_state_access = 0;
int GLAD_GL_ARB_texture_compression_bptc = 0;
int GLAD_GL_EXT_buffer_storage = 0;
int GLAD_GL_EXT_clip_cull_distance = 0;
PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks = NULL;
PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase = NULL;
PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange = NULL;
PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv = NULL;
PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v = NULL;
PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v = NULL;
PFNGLCREATEBUFFERSPROC glad_glCreateBuffers = NULL;
PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage = NULL;
PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData = NULL;
PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData = NULL;
PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData = NULL;
PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData = NULL;
PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData = NULL;
PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer = NULL;
PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange = NULL;
PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer = NULL;
PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange = NULL;
PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv = NULL;
PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v = NULL;
PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv = NULL;
PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData = NULL;
PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers = NULL;
PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer = NULL;
PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri = NULL;
PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture = NULL;
PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer = NULL;
PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer = NULL;
PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers = NULL;
PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer = NULL;
PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData = NULL;
PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi = NULL;
PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer = NULL;
PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus = NULL;
PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv = NULL;
PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv = NULL;
PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers = NULL;
PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage = NULL;
PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample = NULL;
PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv = NULL;
PFNGLCREATETEXTURESPROC glad_glCreateTextures = NULL;
PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer = NULL;
PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange = NULL;
PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D = NULL;
PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D = NULL;
PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D = NULL;
PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample = NULL;
PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample = NULL;
PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D = NULL;
PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D = NULL;
PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D = NULL;
PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D = NULL;
PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D = NULL;
PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D = NULL;
PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf = NULL;
PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv = NULL;
PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri = NULL;
PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv = NULL;
PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv = NULL;
PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv = NULL;
PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap = NULL;
PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit = NULL;
PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage = NULL;
PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage = NULL;
PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv = NULL;
PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv = NULL;
PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv = NULL;
PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv = NULL;
PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv = NULL;
PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv = NULL;
PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays = NULL;
PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib = NULL;
PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib = NULL;
PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer = NULL;
PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer = NULL;
PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers = NULL;
PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding = NULL;
PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat = NULL;
PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat = NULL;
PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat = NULL;
PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor = NULL;
PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv = NULL;
PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv = NULL;
PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv = NULL;
PFNGLCREATESAMPLERSPROC glad_glCreateSamplers = NULL;
PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines = NULL;
PFNGLCREATEQUERIESPROC glad_glCreateQueries = NULL;
PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v = NULL;
PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv = NULL;
PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v = NULL;
PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv = NULL;
int GLAD_GL_EXT_texture_compression_s3tc = 0;
PFNGLBUFFERSTORAGEEXTPROC glad_glBufferStorageEXT = NULL;
static void load_GL_VERSION_1_0(GLADloadproc load) {
if(!GLAD_GL_VERSION_1_0) return;
@ -1590,6 +1619,138 @@ static void load_GL_VERSION_4_4(GLADloadproc load) {
glad_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)load("glBindImageTextures");
glad_glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC)load("glBindVertexBuffers");
}
static void load_GL_VERSION_4_5(GLADloadproc load) {
if(!GLAD_GL_VERSION_4_5) return;
glad_glClipControl = (PFNGLCLIPCONTROLPROC)load("glClipControl");
glad_glCreateTransformFeedbacks = (PFNGLCREATETRANSFORMFEEDBACKSPROC)load("glCreateTransformFeedbacks");
glad_glTransformFeedbackBufferBase = (PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)load("glTransformFeedbackBufferBase");
glad_glTransformFeedbackBufferRange = (PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)load("glTransformFeedbackBufferRange");
glad_glGetTransformFeedbackiv = (PFNGLGETTRANSFORMFEEDBACKIVPROC)load("glGetTransformFeedbackiv");
glad_glGetTransformFeedbacki_v = (PFNGLGETTRANSFORMFEEDBACKI_VPROC)load("glGetTransformFeedbacki_v");
glad_glGetTransformFeedbacki64_v = (PFNGLGETTRANSFORMFEEDBACKI64_VPROC)load("glGetTransformFeedbacki64_v");
glad_glCreateBuffers = (PFNGLCREATEBUFFERSPROC)load("glCreateBuffers");
glad_glNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGEPROC)load("glNamedBufferStorage");
glad_glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC)load("glNamedBufferData");
glad_glNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATAPROC)load("glNamedBufferSubData");
glad_glCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATAPROC)load("glCopyNamedBufferSubData");
glad_glClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATAPROC)load("glClearNamedBufferData");
glad_glClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATAPROC)load("glClearNamedBufferSubData");
glad_glMapNamedBuffer = (PFNGLMAPNAMEDBUFFERPROC)load("glMapNamedBuffer");
glad_glMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGEPROC)load("glMapNamedBufferRange");
glad_glUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFERPROC)load("glUnmapNamedBuffer");
glad_glFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)load("glFlushMappedNamedBufferRange");
glad_glGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIVPROC)load("glGetNamedBufferParameteriv");
glad_glGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)load("glGetNamedBufferParameteri64v");
glad_glGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERVPROC)load("glGetNamedBufferPointerv");
glad_glGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATAPROC)load("glGetNamedBufferSubData");
glad_glCreateFramebuffers = (PFNGLCREATEFRAMEBUFFERSPROC)load("glCreateFramebuffers");
glad_glNamedFramebufferRenderbuffer = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)load("glNamedFramebufferRenderbuffer");
glad_glNamedFramebufferParameteri = (PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)load("glNamedFramebufferParameteri");
glad_glNamedFramebufferTexture = (PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)load("glNamedFramebufferTexture");
glad_glNamedFramebufferTextureLayer = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)load("glNamedFramebufferTextureLayer");
glad_glNamedFramebufferDrawBuffer = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)load("glNamedFramebufferDrawBuffer");
glad_glNamedFramebufferDrawBuffers = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)load("glNamedFramebufferDrawBuffers");
glad_glNamedFramebufferReadBuffer = (PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)load("glNamedFramebufferReadBuffer");
glad_glInvalidateNamedFramebufferData = (PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)load("glInvalidateNamedFramebufferData");
glad_glInvalidateNamedFramebufferSubData = (PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)load("glInvalidateNamedFramebufferSubData");
glad_glClearNamedFramebufferiv = (PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)load("glClearNamedFramebufferiv");
glad_glClearNamedFramebufferuiv = (PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)load("glClearNamedFramebufferuiv");
glad_glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)load("glClearNamedFramebufferfv");
glad_glClearNamedFramebufferfi = (PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)load("glClearNamedFramebufferfi");
glad_glBlitNamedFramebuffer = (PFNGLBLITNAMEDFRAMEBUFFERPROC)load("glBlitNamedFramebuffer");
glad_glCheckNamedFramebufferStatus = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)load("glCheckNamedFramebufferStatus");
glad_glGetNamedFramebufferParameteriv = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)load("glGetNamedFramebufferParameteriv");
glad_glGetNamedFramebufferAttachmentParameteriv = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetNamedFramebufferAttachmentParameteriv");
glad_glCreateRenderbuffers = (PFNGLCREATERENDERBUFFERSPROC)load("glCreateRenderbuffers");
glad_glNamedRenderbufferStorage = (PFNGLNAMEDRENDERBUFFERSTORAGEPROC)load("glNamedRenderbufferStorage");
glad_glNamedRenderbufferStorageMultisample = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glNamedRenderbufferStorageMultisample");
glad_glGetNamedRenderbufferParameteriv = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)load("glGetNamedRenderbufferParameteriv");
glad_glCreateTextures = (PFNGLCREATETEXTURESPROC)load("glCreateTextures");
glad_glTextureBuffer = (PFNGLTEXTUREBUFFERPROC)load("glTextureBuffer");
glad_glTextureBufferRange = (PFNGLTEXTUREBUFFERRANGEPROC)load("glTextureBufferRange");
glad_glTextureStorage1D = (PFNGLTEXTURESTORAGE1DPROC)load("glTextureStorage1D");
glad_glTextureStorage2D = (PFNGLTEXTURESTORAGE2DPROC)load("glTextureStorage2D");
glad_glTextureStorage3D = (PFNGLTEXTURESTORAGE3DPROC)load("glTextureStorage3D");
glad_glTextureStorage2DMultisample = (PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)load("glTextureStorage2DMultisample");
glad_glTextureStorage3DMultisample = (PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)load("glTextureStorage3DMultisample");
glad_glTextureSubImage1D = (PFNGLTEXTURESUBIMAGE1DPROC)load("glTextureSubImage1D");
glad_glTextureSubImage2D = (PFNGLTEXTURESUBIMAGE2DPROC)load("glTextureSubImage2D");
glad_glTextureSubImage3D = (PFNGLTEXTURESUBIMAGE3DPROC)load("glTextureSubImage3D");
glad_glCompressedTextureSubImage1D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)load("glCompressedTextureSubImage1D");
glad_glCompressedTextureSubImage2D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)load("glCompressedTextureSubImage2D");
glad_glCompressedTextureSubImage3D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)load("glCompressedTextureSubImage3D");
glad_glCopyTextureSubImage1D = (PFNGLCOPYTEXTURESUBIMAGE1DPROC)load("glCopyTextureSubImage1D");
glad_glCopyTextureSubImage2D = (PFNGLCOPYTEXTURESUBIMAGE2DPROC)load("glCopyTextureSubImage2D");
glad_glCopyTextureSubImage3D = (PFNGLCOPYTEXTURESUBIMAGE3DPROC)load("glCopyTextureSubImage3D");
glad_glTextureParameterf = (PFNGLTEXTUREPARAMETERFPROC)load("glTextureParameterf");
glad_glTextureParameterfv = (PFNGLTEXTUREPARAMETERFVPROC)load("glTextureParameterfv");
glad_glTextureParameteri = (PFNGLTEXTUREPARAMETERIPROC)load("glTextureParameteri");
glad_glTextureParameterIiv = (PFNGLTEXTUREPARAMETERIIVPROC)load("glTextureParameterIiv");
glad_glTextureParameterIuiv = (PFNGLTEXTUREPARAMETERIUIVPROC)load("glTextureParameterIuiv");
glad_glTextureParameteriv = (PFNGLTEXTUREPARAMETERIVPROC)load("glTextureParameteriv");
glad_glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC)load("glGenerateTextureMipmap");
glad_glBindTextureUnit = (PFNGLBINDTEXTUREUNITPROC)load("glBindTextureUnit");
glad_glGetTextureImage = (PFNGLGETTEXTUREIMAGEPROC)load("glGetTextureImage");
glad_glGetCompressedTextureImage = (PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)load("glGetCompressedTextureImage");
glad_glGetTextureLevelParameterfv = (PFNGLGETTEXTURELEVELPARAMETERFVPROC)load("glGetTextureLevelParameterfv");
glad_glGetTextureLevelParameteriv = (PFNGLGETTEXTURELEVELPARAMETERIVPROC)load("glGetTextureLevelParameteriv");
glad_glGetTextureParameterfv = (PFNGLGETTEXTUREPARAMETERFVPROC)load("glGetTextureParameterfv");
glad_glGetTextureParameterIiv = (PFNGLGETTEXTUREPARAMETERIIVPROC)load("glGetTextureParameterIiv");
glad_glGetTextureParameterIuiv = (PFNGLGETTEXTUREPARAMETERIUIVPROC)load("glGetTextureParameterIuiv");
glad_glGetTextureParameteriv = (PFNGLGETTEXTUREPARAMETERIVPROC)load("glGetTextureParameteriv");
glad_glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC)load("glCreateVertexArrays");
glad_glDisableVertexArrayAttrib = (PFNGLDISABLEVERTEXARRAYATTRIBPROC)load("glDisableVertexArrayAttrib");
glad_glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC)load("glEnableVertexArrayAttrib");
glad_glVertexArrayElementBuffer = (PFNGLVERTEXARRAYELEMENTBUFFERPROC)load("glVertexArrayElementBuffer");
glad_glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC)load("glVertexArrayVertexBuffer");
glad_glVertexArrayVertexBuffers = (PFNGLVERTEXARRAYVERTEXBUFFERSPROC)load("glVertexArrayVertexBuffers");
glad_glVertexArrayAttribBinding = (PFNGLVERTEXARRAYATTRIBBINDINGPROC)load("glVertexArrayAttribBinding");
glad_glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC)load("glVertexArrayAttribFormat");
glad_glVertexArrayAttribIFormat = (PFNGLVERTEXARRAYATTRIBIFORMATPROC)load("glVertexArrayAttribIFormat");
glad_glVertexArrayAttribLFormat = (PFNGLVERTEXARRAYATTRIBLFORMATPROC)load("glVertexArrayAttribLFormat");
glad_glVertexArrayBindingDivisor = (PFNGLVERTEXARRAYBINDINGDIVISORPROC)load("glVertexArrayBindingDivisor");
glad_glGetVertexArrayiv = (PFNGLGETVERTEXARRAYIVPROC)load("glGetVertexArrayiv");
glad_glGetVertexArrayIndexediv = (PFNGLGETVERTEXARRAYINDEXEDIVPROC)load("glGetVertexArrayIndexediv");
glad_glGetVertexArrayIndexed64iv = (PFNGLGETVERTEXARRAYINDEXED64IVPROC)load("glGetVertexArrayIndexed64iv");
glad_glCreateSamplers = (PFNGLCREATESAMPLERSPROC)load("glCreateSamplers");
glad_glCreateProgramPipelines = (PFNGLCREATEPROGRAMPIPELINESPROC)load("glCreateProgramPipelines");
glad_glCreateQueries = (PFNGLCREATEQUERIESPROC)load("glCreateQueries");
glad_glGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECTI64VPROC)load("glGetQueryBufferObjecti64v");
glad_glGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECTIVPROC)load("glGetQueryBufferObjectiv");
glad_glGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECTUI64VPROC)load("glGetQueryBufferObjectui64v");
glad_glGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECTUIVPROC)load("glGetQueryBufferObjectuiv");
glad_glMemoryBarrierByRegion = (PFNGLMEMORYBARRIERBYREGIONPROC)load("glMemoryBarrierByRegion");
glad_glGetTextureSubImage = (PFNGLGETTEXTURESUBIMAGEPROC)load("glGetTextureSubImage");
glad_glGetCompressedTextureSubImage = (PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)load("glGetCompressedTextureSubImage");
glad_glGetGraphicsResetStatus = (PFNGLGETGRAPHICSRESETSTATUSPROC)load("glGetGraphicsResetStatus");
glad_glGetnCompressedTexImage = (PFNGLGETNCOMPRESSEDTEXIMAGEPROC)load("glGetnCompressedTexImage");
glad_glGetnTexImage = (PFNGLGETNTEXIMAGEPROC)load("glGetnTexImage");
glad_glGetnUniformdv = (PFNGLGETNUNIFORMDVPROC)load("glGetnUniformdv");
glad_glGetnUniformfv = (PFNGLGETNUNIFORMFVPROC)load("glGetnUniformfv");
glad_glGetnUniformiv = (PFNGLGETNUNIFORMIVPROC)load("glGetnUniformiv");
glad_glGetnUniformuiv = (PFNGLGETNUNIFORMUIVPROC)load("glGetnUniformuiv");
glad_glReadnPixels = (PFNGLREADNPIXELSPROC)load("glReadnPixels");
glad_glGetnMapdv = (PFNGLGETNMAPDVPROC)load("glGetnMapdv");
glad_glGetnMapfv = (PFNGLGETNMAPFVPROC)load("glGetnMapfv");
glad_glGetnMapiv = (PFNGLGETNMAPIVPROC)load("glGetnMapiv");
glad_glGetnPixelMapfv = (PFNGLGETNPIXELMAPFVPROC)load("glGetnPixelMapfv");
glad_glGetnPixelMapuiv = (PFNGLGETNPIXELMAPUIVPROC)load("glGetnPixelMapuiv");
glad_glGetnPixelMapusv = (PFNGLGETNPIXELMAPUSVPROC)load("glGetnPixelMapusv");
glad_glGetnPolygonStipple = (PFNGLGETNPOLYGONSTIPPLEPROC)load("glGetnPolygonStipple");
glad_glGetnColorTable = (PFNGLGETNCOLORTABLEPROC)load("glGetnColorTable");
glad_glGetnConvolutionFilter = (PFNGLGETNCONVOLUTIONFILTERPROC)load("glGetnConvolutionFilter");
glad_glGetnSeparableFilter = (PFNGLGETNSEPARABLEFILTERPROC)load("glGetnSeparableFilter");
glad_glGetnHistogram = (PFNGLGETNHISTOGRAMPROC)load("glGetnHistogram");
glad_glGetnMinmax = (PFNGLGETNMINMAXPROC)load("glGetnMinmax");
glad_glTextureBarrier = (PFNGLTEXTUREBARRIERPROC)load("glTextureBarrier");
}
static void load_GL_VERSION_4_6(GLADloadproc load) {
if(!GLAD_GL_VERSION_4_6) return;
glad_glSpecializeShader = (PFNGLSPECIALIZESHADERPROC)load("glSpecializeShader");
glad_glMultiDrawArraysIndirectCount = (PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC)load("glMultiDrawArraysIndirectCount");
glad_glMultiDrawElementsIndirectCount = (PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC)load("glMultiDrawElementsIndirectCount");
glad_glPolygonOffsetClamp = (PFNGLPOLYGONOFFSETCLAMPPROC)load("glPolygonOffsetClamp");
}
static void load_GL_ARB_buffer_storage(GLADloadproc load) {
if(!GLAD_GL_ARB_buffer_storage) return;
glad_glBufferStorage = (PFNGLBUFFERSTORAGEPROC)load("glBufferStorage");
@ -1698,6 +1859,8 @@ static int find_extensionsGL(void) {
if (!get_exts()) return 0;
GLAD_GL_ARB_buffer_storage = has_ext("GL_ARB_buffer_storage");
GLAD_GL_ARB_direct_state_access = has_ext("GL_ARB_direct_state_access");
GLAD_GL_ARB_texture_compression_bptc = has_ext("GL_ARB_texture_compression_bptc");
GLAD_GL_EXT_texture_compression_s3tc = has_ext("GL_EXT_texture_compression_s3tc");
free_exts();
return 1;
}
@ -1755,9 +1918,11 @@ static void find_coreGL(void) {
GLAD_GL_VERSION_4_2 = (major == 4 && minor >= 2) || major > 4;
GLAD_GL_VERSION_4_3 = (major == 4 && minor >= 3) || major > 4;
GLAD_GL_VERSION_4_4 = (major == 4 && minor >= 4) || major > 4;
if (GLVersion.major > 4 || (GLVersion.major >= 4 && GLVersion.minor >= 4)) {
GLAD_GL_VERSION_4_5 = (major == 4 && minor >= 5) || major > 4;
GLAD_GL_VERSION_4_6 = (major == 4 && minor >= 6) || major > 4;
if (GLVersion.major > 4 || (GLVersion.major >= 4 && GLVersion.minor >= 6)) {
max_loaded_major = 4;
max_loaded_minor = 4;
max_loaded_minor = 6;
}
}
@ -1784,6 +1949,8 @@ int gladLoadGLLoader(GLADloadproc load) {
load_GL_VERSION_4_2(load);
load_GL_VERSION_4_3(load);
load_GL_VERSION_4_4(load);
load_GL_VERSION_4_5(load);
load_GL_VERSION_4_6(load);
if (!find_extensionsGL()) return 0;
load_GL_ARB_buffer_storage(load);
@ -2169,6 +2336,7 @@ static int find_extensionsGLES2(void) {
if (!get_exts()) return 0;
GLAD_GL_EXT_buffer_storage = has_ext("GL_EXT_buffer_storage");
GLAD_GL_EXT_clip_cull_distance = has_ext("GL_EXT_clip_cull_distance");
GLAD_GL_EXT_texture_compression_s3tc = has_ext("GL_EXT_texture_compression_s3tc");
free_exts();
return 1;
}

1
externals/libspng vendored

Submodule externals/libspng deleted from 75c39ce094

25
externals/libspng/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,25 @@
add_library(spng STATIC spng.h spng.c)
target_compile_definitions(spng PUBLIC SPNG_STATIC)
target_include_directories(spng PUBLIC ${CMAKE_CURRENT_LIST_DIR})
# Try to find zlib, use miniz otherwise
find_package(ZLIB REQUIRED)
if (ZLIB_FOUND)
target_include_directories(spng PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(spng PRIVATE ${ZLIB_LIBRARIES})
else()
message(STATUS "Unable to find zlib for libspng, using miniz")
target_sources(spng PRIVATE miniz.c miniz.h)
target_compile_definitions(spng PRIVATE SPNG_USE_MINIZ)
endif()
# Enable SSE4.1 on x64
if ("x86_64" IN_LIST ARCHITECTURE)
target_compile_definitions(spng PRIVATE SPNG_SSE=4)
if (NOT MSVC)
target_compile_options(spng PRIVATE -msse4.1)
endif()
endif()
add_library(spng::spng ALIAS spng)

7833
externals/libspng/miniz.c vendored Normal file

File diff suppressed because it is too large Load Diff

1422
externals/libspng/miniz.h vendored Normal file

File diff suppressed because it is too large Load Diff

6979
externals/libspng/spng.c vendored Normal file

File diff suppressed because it is too large Load Diff

537
externals/libspng/spng.h vendored Normal file
View File

@ -0,0 +1,537 @@
/* SPDX-License-Identifier: BSD-2-Clause */
#ifndef SPNG_H
#define SPNG_H
#ifdef __cplusplus
extern "C" {
#endif
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(SPNG_STATIC)
#if defined(SPNG__BUILD)
#define SPNG_API __declspec(dllexport)
#else
#define SPNG_API __declspec(dllimport)
#endif
#else
#define SPNG_API
#endif
#if defined(_MSC_VER)
#define SPNG_CDECL __cdecl
#else
#define SPNG_CDECL
#endif
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#define SPNG_VERSION_MAJOR 0
#define SPNG_VERSION_MINOR 7
#define SPNG_VERSION_PATCH 3
enum spng_errno
{
SPNG_IO_ERROR = -2,
SPNG_IO_EOF = -1,
SPNG_OK = 0,
SPNG_EINVAL,
SPNG_EMEM,
SPNG_EOVERFLOW,
SPNG_ESIGNATURE,
SPNG_EWIDTH,
SPNG_EHEIGHT,
SPNG_EUSER_WIDTH,
SPNG_EUSER_HEIGHT,
SPNG_EBIT_DEPTH,
SPNG_ECOLOR_TYPE,
SPNG_ECOMPRESSION_METHOD,
SPNG_EFILTER_METHOD,
SPNG_EINTERLACE_METHOD,
SPNG_EIHDR_SIZE,
SPNG_ENOIHDR,
SPNG_ECHUNK_POS,
SPNG_ECHUNK_SIZE,
SPNG_ECHUNK_CRC,
SPNG_ECHUNK_TYPE,
SPNG_ECHUNK_UNKNOWN_CRITICAL,
SPNG_EDUP_PLTE,
SPNG_EDUP_CHRM,
SPNG_EDUP_GAMA,
SPNG_EDUP_ICCP,
SPNG_EDUP_SBIT,
SPNG_EDUP_SRGB,
SPNG_EDUP_BKGD,
SPNG_EDUP_HIST,
SPNG_EDUP_TRNS,
SPNG_EDUP_PHYS,
SPNG_EDUP_TIME,
SPNG_EDUP_OFFS,
SPNG_EDUP_EXIF,
SPNG_ECHRM,
SPNG_EPLTE_IDX,
SPNG_ETRNS_COLOR_TYPE,
SPNG_ETRNS_NO_PLTE,
SPNG_EGAMA,
SPNG_EICCP_NAME,
SPNG_EICCP_COMPRESSION_METHOD,
SPNG_ESBIT,
SPNG_ESRGB,
SPNG_ETEXT,
SPNG_ETEXT_KEYWORD,
SPNG_EZTXT,
SPNG_EZTXT_COMPRESSION_METHOD,
SPNG_EITXT,
SPNG_EITXT_COMPRESSION_FLAG,
SPNG_EITXT_COMPRESSION_METHOD,
SPNG_EITXT_LANG_TAG,
SPNG_EITXT_TRANSLATED_KEY,
SPNG_EBKGD_NO_PLTE,
SPNG_EBKGD_PLTE_IDX,
SPNG_EHIST_NO_PLTE,
SPNG_EPHYS,
SPNG_ESPLT_NAME,
SPNG_ESPLT_DUP_NAME,
SPNG_ESPLT_DEPTH,
SPNG_ETIME,
SPNG_EOFFS,
SPNG_EEXIF,
SPNG_EIDAT_TOO_SHORT,
SPNG_EIDAT_STREAM,
SPNG_EZLIB,
SPNG_EFILTER,
SPNG_EBUFSIZ,
SPNG_EIO,
SPNG_EOF,
SPNG_EBUF_SET,
SPNG_EBADSTATE,
SPNG_EFMT,
SPNG_EFLAGS,
SPNG_ECHUNKAVAIL,
SPNG_ENCODE_ONLY,
SPNG_EOI,
SPNG_ENOPLTE,
SPNG_ECHUNK_LIMITS,
SPNG_EZLIB_INIT,
SPNG_ECHUNK_STDLEN,
SPNG_EINTERNAL,
SPNG_ECTXTYPE,
SPNG_ENOSRC,
SPNG_ENODST,
SPNG_EOPSTATE,
SPNG_ENOTFINAL,
};
enum spng_text_type
{
SPNG_TEXT = 1,
SPNG_ZTXT = 2,
SPNG_ITXT = 3
};
enum spng_color_type
{
SPNG_COLOR_TYPE_GRAYSCALE = 0,
SPNG_COLOR_TYPE_TRUECOLOR = 2,
SPNG_COLOR_TYPE_INDEXED = 3,
SPNG_COLOR_TYPE_GRAYSCALE_ALPHA = 4,
SPNG_COLOR_TYPE_TRUECOLOR_ALPHA = 6
};
enum spng_filter
{
SPNG_FILTER_NONE = 0,
SPNG_FILTER_SUB = 1,
SPNG_FILTER_UP = 2,
SPNG_FILTER_AVERAGE = 3,
SPNG_FILTER_PAETH = 4
};
enum spng_filter_choice
{
SPNG_DISABLE_FILTERING = 0,
SPNG_FILTER_CHOICE_NONE = 8,
SPNG_FILTER_CHOICE_SUB = 16,
SPNG_FILTER_CHOICE_UP = 32,
SPNG_FILTER_CHOICE_AVG = 64,
SPNG_FILTER_CHOICE_PAETH = 128,
SPNG_FILTER_CHOICE_ALL = (8|16|32|64|128)
};
enum spng_interlace_method
{
SPNG_INTERLACE_NONE = 0,
SPNG_INTERLACE_ADAM7 = 1
};
/* Channels are always in byte-order */
enum spng_format
{
SPNG_FMT_RGBA8 = 1,
SPNG_FMT_RGBA16 = 2,
SPNG_FMT_RGB8 = 4,
/* Partially implemented, see documentation */
SPNG_FMT_GA8 = 16,
SPNG_FMT_GA16 = 32,
SPNG_FMT_G8 = 64,
/* No conversion or scaling */
SPNG_FMT_PNG = 256,
SPNG_FMT_RAW = 512 /* big-endian (everything else is host-endian) */
};
enum spng_ctx_flags
{
SPNG_CTX_IGNORE_ADLER32 = 1, /* Ignore checksum in DEFLATE streams */
SPNG_CTX_ENCODER = 2 /* Create an encoder context */
};
enum spng_decode_flags
{
SPNG_DECODE_USE_TRNS = 1, /* Deprecated */
SPNG_DECODE_USE_GAMA = 2, /* Deprecated */
SPNG_DECODE_USE_SBIT = 8, /* Undocumented */
SPNG_DECODE_TRNS = 1, /* Apply transparency */
SPNG_DECODE_GAMMA = 2, /* Apply gamma correction */
SPNG_DECODE_PROGRESSIVE = 256 /* Initialize for progressive reads */
};
enum spng_crc_action
{
/* Default for critical chunks */
SPNG_CRC_ERROR = 0,
/* Discard chunk, invalid for critical chunks.
Since v0.6.2: default for ancillary chunks */
SPNG_CRC_DISCARD = 1,
/* Ignore and don't calculate checksum.
Since v0.6.2: also ignores checksums in DEFLATE streams */
SPNG_CRC_USE = 2
};
enum spng_encode_flags
{
SPNG_ENCODE_PROGRESSIVE = 1, /* Initialize for progressive writes */
SPNG_ENCODE_FINALIZE = 2, /* Finalize PNG after encoding image */
};
struct spng_ihdr
{
uint32_t width;
uint32_t height;
uint8_t bit_depth;
uint8_t color_type;
uint8_t compression_method;
uint8_t filter_method;
uint8_t interlace_method;
};
struct spng_plte_entry
{
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha; /* Reserved for internal use */
};
struct spng_plte
{
uint32_t n_entries;
struct spng_plte_entry entries[256];
};
struct spng_trns
{
uint16_t gray;
uint16_t red;
uint16_t green;
uint16_t blue;
uint32_t n_type3_entries;
uint8_t type3_alpha[256];
};
struct spng_chrm_int
{
uint32_t white_point_x;
uint32_t white_point_y;
uint32_t red_x;
uint32_t red_y;
uint32_t green_x;
uint32_t green_y;
uint32_t blue_x;
uint32_t blue_y;
};
struct spng_chrm
{
double white_point_x;
double white_point_y;
double red_x;
double red_y;
double green_x;
double green_y;
double blue_x;
double blue_y;
};
struct spng_iccp
{
char profile_name[80];
size_t profile_len;
char *profile;
};
struct spng_sbit
{
uint8_t grayscale_bits;
uint8_t red_bits;
uint8_t green_bits;
uint8_t blue_bits;
uint8_t alpha_bits;
};
struct spng_text
{
char keyword[80];
int type;
size_t length;
char *text;
uint8_t compression_flag; /* iTXt only */
uint8_t compression_method; /* iTXt, ztXt only */
char *language_tag; /* iTXt only */
char *translated_keyword; /* iTXt only */
};
struct spng_bkgd
{
uint16_t gray; /* Only for gray/gray alpha */
uint16_t red;
uint16_t green;
uint16_t blue;
uint16_t plte_index; /* Only for indexed color */
};
struct spng_hist
{
uint16_t frequency[256];
};
struct spng_phys
{
uint32_t ppu_x, ppu_y;
uint8_t unit_specifier;
};
struct spng_splt_entry
{
uint16_t red;
uint16_t green;
uint16_t blue;
uint16_t alpha;
uint16_t frequency;
};
struct spng_splt
{
char name[80];
uint8_t sample_depth;
uint32_t n_entries;
struct spng_splt_entry *entries;
};
struct spng_time
{
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
};
struct spng_offs
{
int32_t x, y;
uint8_t unit_specifier;
};
struct spng_exif
{
size_t length;
char *data;
};
struct spng_chunk
{
size_t offset;
uint32_t length;
uint8_t type[4];
uint32_t crc;
};
enum spng_location
{
SPNG_AFTER_IHDR = 1,
SPNG_AFTER_PLTE = 2,
SPNG_AFTER_IDAT = 8,
};
struct spng_unknown_chunk
{
uint8_t type[4];
size_t length;
void *data;
enum spng_location location;
};
enum spng_option
{
SPNG_KEEP_UNKNOWN_CHUNKS = 1,
SPNG_IMG_COMPRESSION_LEVEL,
SPNG_IMG_WINDOW_BITS,
SPNG_IMG_MEM_LEVEL,
SPNG_IMG_COMPRESSION_STRATEGY,
SPNG_TEXT_COMPRESSION_LEVEL,
SPNG_TEXT_WINDOW_BITS,
SPNG_TEXT_MEM_LEVEL,
SPNG_TEXT_COMPRESSION_STRATEGY,
SPNG_FILTER_CHOICE,
SPNG_CHUNK_COUNT_LIMIT,
SPNG_ENCODE_TO_BUFFER,
};
typedef void* SPNG_CDECL spng_malloc_fn(size_t size);
typedef void* SPNG_CDECL spng_realloc_fn(void* ptr, size_t size);
typedef void* SPNG_CDECL spng_calloc_fn(size_t count, size_t size);
typedef void SPNG_CDECL spng_free_fn(void* ptr);
struct spng_alloc
{
spng_malloc_fn *malloc_fn;
spng_realloc_fn *realloc_fn;
spng_calloc_fn *calloc_fn;
spng_free_fn *free_fn;
};
struct spng_row_info
{
uint32_t scanline_idx;
uint32_t row_num; /* deinterlaced row index */
int pass;
uint8_t filter;
};
typedef struct spng_ctx spng_ctx;
typedef int spng_read_fn(spng_ctx *ctx, void *user, void *dest, size_t length);
typedef int spng_write_fn(spng_ctx *ctx, void *user, void *src, size_t length);
typedef int spng_rw_fn(spng_ctx *ctx, void *user, void *dst_src, size_t length);
SPNG_API spng_ctx *spng_ctx_new(int flags);
SPNG_API spng_ctx *spng_ctx_new2(struct spng_alloc *alloc, int flags);
SPNG_API void spng_ctx_free(spng_ctx *ctx);
SPNG_API int spng_set_png_buffer(spng_ctx *ctx, const void *buf, size_t size);
SPNG_API int spng_set_png_stream(spng_ctx *ctx, spng_rw_fn *rw_func, void *user);
SPNG_API int spng_set_png_file(spng_ctx *ctx, FILE *file);
SPNG_API void *spng_get_png_buffer(spng_ctx *ctx, size_t *len, int *error);
SPNG_API int spng_set_image_limits(spng_ctx *ctx, uint32_t width, uint32_t height);
SPNG_API int spng_get_image_limits(spng_ctx *ctx, uint32_t *width, uint32_t *height);
SPNG_API int spng_set_chunk_limits(spng_ctx *ctx, size_t chunk_size, size_t cache_size);
SPNG_API int spng_get_chunk_limits(spng_ctx *ctx, size_t *chunk_size, size_t *cache_size);
SPNG_API int spng_set_crc_action(spng_ctx *ctx, int critical, int ancillary);
SPNG_API int spng_set_option(spng_ctx *ctx, enum spng_option option, int value);
SPNG_API int spng_get_option(spng_ctx *ctx, enum spng_option option, int *value);
SPNG_API int spng_decoded_image_size(spng_ctx *ctx, int fmt, size_t *len);
/* Decode */
SPNG_API int spng_decode_image(spng_ctx *ctx, void *out, size_t len, int fmt, int flags);
/* Progressive decode */
SPNG_API int spng_decode_scanline(spng_ctx *ctx, void *out, size_t len);
SPNG_API int spng_decode_row(spng_ctx *ctx, void *out, size_t len);
SPNG_API int spng_decode_chunks(spng_ctx *ctx);
/* Encode/decode */
SPNG_API int spng_get_row_info(spng_ctx *ctx, struct spng_row_info *row_info);
/* Encode */
SPNG_API int spng_encode_image(spng_ctx *ctx, const void *img, size_t len, int fmt, int flags);
/* Progressive encode */
SPNG_API int spng_encode_scanline(spng_ctx *ctx, const void *scanline, size_t len);
SPNG_API int spng_encode_row(spng_ctx *ctx, const void *row, size_t len);
SPNG_API int spng_encode_chunks(spng_ctx *ctx);
SPNG_API int spng_get_ihdr(spng_ctx *ctx, struct spng_ihdr *ihdr);
SPNG_API int spng_get_plte(spng_ctx *ctx, struct spng_plte *plte);
SPNG_API int spng_get_trns(spng_ctx *ctx, struct spng_trns *trns);
SPNG_API int spng_get_chrm(spng_ctx *ctx, struct spng_chrm *chrm);
SPNG_API int spng_get_chrm_int(spng_ctx *ctx, struct spng_chrm_int *chrm_int);
SPNG_API int spng_get_gama(spng_ctx *ctx, double *gamma);
SPNG_API int spng_get_gama_int(spng_ctx *ctx, uint32_t *gama_int);
SPNG_API int spng_get_iccp(spng_ctx *ctx, struct spng_iccp *iccp);
SPNG_API int spng_get_sbit(spng_ctx *ctx, struct spng_sbit *sbit);
SPNG_API int spng_get_srgb(spng_ctx *ctx, uint8_t *rendering_intent);
SPNG_API int spng_get_text(spng_ctx *ctx, struct spng_text *text, uint32_t *n_text);
SPNG_API int spng_get_bkgd(spng_ctx *ctx, struct spng_bkgd *bkgd);
SPNG_API int spng_get_hist(spng_ctx *ctx, struct spng_hist *hist);
SPNG_API int spng_get_phys(spng_ctx *ctx, struct spng_phys *phys);
SPNG_API int spng_get_splt(spng_ctx *ctx, struct spng_splt *splt, uint32_t *n_splt);
SPNG_API int spng_get_time(spng_ctx *ctx, struct spng_time *time);
SPNG_API int spng_get_unknown_chunks(spng_ctx *ctx, struct spng_unknown_chunk *chunks, uint32_t *n_chunks);
/* Official extensions */
SPNG_API int spng_get_offs(spng_ctx *ctx, struct spng_offs *offs);
SPNG_API int spng_get_exif(spng_ctx *ctx, struct spng_exif *exif);
SPNG_API int spng_set_ihdr(spng_ctx *ctx, struct spng_ihdr *ihdr);
SPNG_API int spng_set_plte(spng_ctx *ctx, struct spng_plte *plte);
SPNG_API int spng_set_trns(spng_ctx *ctx, struct spng_trns *trns);
SPNG_API int spng_set_chrm(spng_ctx *ctx, struct spng_chrm *chrm);
SPNG_API int spng_set_chrm_int(spng_ctx *ctx, struct spng_chrm_int *chrm_int);
SPNG_API int spng_set_gama(spng_ctx *ctx, double gamma);
SPNG_API int spng_set_gama_int(spng_ctx *ctx, uint32_t gamma);
SPNG_API int spng_set_iccp(spng_ctx *ctx, struct spng_iccp *iccp);
SPNG_API int spng_set_sbit(spng_ctx *ctx, struct spng_sbit *sbit);
SPNG_API int spng_set_srgb(spng_ctx *ctx, uint8_t rendering_intent);
SPNG_API int spng_set_text(spng_ctx *ctx, struct spng_text *text, uint32_t n_text);
SPNG_API int spng_set_bkgd(spng_ctx *ctx, struct spng_bkgd *bkgd);
SPNG_API int spng_set_hist(spng_ctx *ctx, struct spng_hist *hist);
SPNG_API int spng_set_phys(spng_ctx *ctx, struct spng_phys *phys);
SPNG_API int spng_set_splt(spng_ctx *ctx, struct spng_splt *splt, uint32_t n_splt);
SPNG_API int spng_set_time(spng_ctx *ctx, struct spng_time *time);
SPNG_API int spng_set_unknown_chunks(spng_ctx *ctx, struct spng_unknown_chunk *chunks, uint32_t n_chunks);
/* Official extensions */
SPNG_API int spng_set_offs(spng_ctx *ctx, struct spng_offs *offs);
SPNG_API int spng_set_exif(spng_ctx *ctx, struct spng_exif *exif);
SPNG_API const char *spng_strerror(int err);
SPNG_API const char *spng_version_string(void);
#ifdef __cplusplus
}
#endif
#endif /* SPNG_H */

1
externals/lodepng/lodepng vendored Submodule

Submodule externals/lodepng/lodepng added at 18964554bc

View File

@ -560,6 +560,8 @@ void GMainWindow::InitializeHotkeys() {
});
connect_shortcut(QStringLiteral("Toggle Texture Dumping"),
[&] { Settings::values.dump_textures = !Settings::values.dump_textures; });
connect_shortcut(QStringLiteral("Toggle Custom Textures"),
[&] { Settings::values.custom_textures = !Settings::values.custom_textures; });
// We use "static" here in order to avoid capturing by lambda due to a MSVC bug, which makes
// the variable hold a garbage value after this function exits
static constexpr u16 SPEED_LIMIT_STEP = 5;

View File

@ -75,7 +75,7 @@ add_library(common STATIC
common_precompiled_headers.h
common_types.h
construct.h
dds.h
dds-ktx.h
error.cpp
error.h
file_util.cpp
@ -147,8 +147,8 @@ add_library(common STATIC
create_target_directory_groups(common)
target_link_libraries(common PUBLIC fmt::fmt microprofile Boost::boost Boost::serialization spng_static)
target_link_libraries(common PRIVATE libzstd_static)
target_link_libraries(common PUBLIC fmt::fmt microprofile Boost::boost Boost::serialization)
target_link_libraries(common PRIVATE libzstd_static spng::spng)
set_target_properties(common PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
if ("x86_64" IN_LIST ARCHITECTURE)

View File

@ -13,25 +13,27 @@ namespace Common {
struct AsyncHandle {
public:
[[nodiscard]] bool IsBuilt() noexcept {
return is_built.load(std::memory_order::relaxed);
AsyncHandle(bool is_done_ = false) : is_done{is_done_} {}
[[nodiscard]] bool IsDone() noexcept {
return is_done.load(std::memory_order::relaxed);
}
void WaitBuilt() noexcept {
void WaitDone() noexcept {
std::unique_lock lock{mutex};
condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); });
condvar.wait(lock, [this] { return is_done.load(std::memory_order::relaxed); });
}
void MarkBuilt() noexcept {
void MarkDone(bool done = true) noexcept {
std::scoped_lock lock{mutex};
is_built = true;
is_done = done;
condvar.notify_all();
}
private:
std::condition_variable condvar;
std::mutex mutex;
std::atomic_bool is_built{false};
std::atomic_bool is_done{false};
};
} // namespace Common

View File

@ -45,19 +45,19 @@ template <typename T>
}
template <typename T>
requires std::is_unsigned_v<T>
requires std::is_unsigned_v<T>
[[nodiscard]] constexpr bool IsPow2(T value) {
return std::has_single_bit(value);
}
template <typename T>
requires std::is_integral_v<T>
requires std::is_integral_v<T>
[[nodiscard]] T NextPow2(T value) {
return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U)));
}
template <size_t bit_index, typename T>
requires std::is_integral_v<T>
requires std::is_integral_v<T>
[[nodiscard]] constexpr bool Bit(const T value) {
static_assert(bit_index < BitSize<T>(), "bit_index must be smaller than size of T");
return ((value >> bit_index) & T(1)) == T(1);

1465
src/common/dds-ktx.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,111 +0,0 @@
//--------------------------------------------------------------------------------------
// DDS.h
//
// This header defines constants and structures that are useful when parsing
// DDS files. DDS files were originally designed to use several structures
// and constants that are native to DirectDraw and are defined in ddraw.h,
// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar
// (compatible) constants and structures so that one can use DDS files
// without needing to include ddraw.h.
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
// http://go.microsoft.com/fwlink/?LinkId=248929
// http://go.microsoft.com/fwlink/?LinkID=615561
//--------------------------------------------------------------------------------------
#pragma once
#include <cstdint>
namespace Common::DirectX {
#pragma pack(push, 1)
const uint32_t DDS_MAGIC = 0x20534444; // "DDS "
struct DDS_PIXELFORMAT {
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwFourCC;
uint32_t dwRGBBitCount;
uint32_t dwRBitMask;
uint32_t dwGBitMask;
uint32_t dwBBitMask;
uint32_t dwABitMask;
};
#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
#define DDS_RGB 0x00000040 // DDPF_RGB
#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS
#define DDS_ALPHA 0x00000002 // DDPF_ALPHA
#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8
#define DDS_PAL8A 0x00000021 // DDPF_PALETTEINDEXED8 | DDPF_ALPHAPIXELS
#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV
#ifndef MAKEFOURCC
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \
((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24))
#endif /* defined(MAKEFOURCC) */
#define DDS_HEADER_FLAGS_TEXTURE \
0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION
enum DDS_RESOURCE_DIMENSION {
DDS_DIMENSION_TEXTURE1D = 2,
DDS_DIMENSION_TEXTURE2D = 3,
DDS_DIMENSION_TEXTURE3D = 4,
};
struct DDS_HEADER {
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwHeight;
uint32_t dwWidth;
uint32_t dwPitchOrLinearSize;
uint32_t dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags
uint32_t dwMipMapCount;
uint32_t dwReserved1[11];
DDS_PIXELFORMAT ddspf;
uint32_t dwCaps;
uint32_t dwCaps2;
uint32_t dwCaps3;
uint32_t dwCaps4;
uint32_t dwReserved2;
};
struct DDS_HEADER_DXT10 {
uint32_t dxgiFormat;
uint32_t resourceDimension;
uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG
uint32_t arraySize;
uint32_t miscFlags2; // see DDS_MISC_FLAGS2
};
#pragma pack(pop)
static_assert(sizeof(DDS_HEADER) == 124, "DDS Header size mismatch");
static_assert(sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch");
constexpr DDS_PIXELFORMAT DDSPF_A8R8G8B8 = {
sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000};
constexpr DDS_PIXELFORMAT DDSPF_X8R8G8B8 = {
sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000};
constexpr DDS_PIXELFORMAT DDSPF_A8B8G8R8 = {
sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000};
constexpr DDS_PIXELFORMAT DDSPF_X8B8G8R8 = {
sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000};
constexpr DDS_PIXELFORMAT DDSPF_R8G8B8 = {
sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000};
} // namespace Common::DirectX

View File

@ -3,15 +3,13 @@
// Refer to the license.txt file included.
#include <spng.h>
#include "common/dds.h"
#define DDSKTX_IMPLEMENT
#include "common/file_util.h"
#include "common/image_util.h"
#include "common/logging/log.h"
namespace Common {
using namespace Common::DirectX;
namespace {
void spng_free(spng_ctx* ctx) {
@ -26,13 +24,13 @@ auto make_spng_ctx(int flags) {
} // Anonymous namespace
bool DecodePNG(std::span<const u8> in_data, std::vector<u8>& out_data, u32& width, u32& height) {
bool ParsePNG(std::span<const u8> png_data, size_t& decoded_size, u32& width, u32& height) {
auto ctx = make_spng_ctx(0);
if (!ctx) [[unlikely]] {
return false;
}
if (spng_set_png_buffer(ctx.get(), in_data.data(), in_data.size())) {
if (spng_set_png_buffer(ctx.get(), png_data.data(), png_data.size())) {
return false;
}
@ -40,36 +38,72 @@ bool DecodePNG(std::span<const u8> in_data, std::vector<u8>& out_data, u32& widt
if (spng_get_ihdr(ctx.get(), &ihdr)) {
return false;
}
width = ihdr.width;
height = ihdr.height;
const int format = SPNG_FMT_RGBA8;
if (spng_decoded_image_size(ctx.get(), format, &decoded_size)) {
return false;
}
return true;
}
bool DecodePNG(std::span<const u8> png_data, std::span<u8> out_data) {
auto ctx = make_spng_ctx(0);
if (!ctx) [[unlikely]] {
return false;
}
if (spng_set_png_buffer(ctx.get(), png_data.data(), png_data.size())) {
return false;
}
const int format = SPNG_FMT_RGBA8;
size_t decoded_len = 0;
if (spng_decoded_image_size(ctx.get(), format, &decoded_len)) {
return false;
}
ASSERT(out_data.size() == decoded_len);
out_data.resize(decoded_len);
if (spng_decode_image(ctx.get(), out_data.data(), decoded_len, format, SPNG_DECODE_TRNS)) {
if (spng_decode_image(ctx.get(), out_data.data(), decoded_len, format, 0)) {
return false;
}
width = ihdr.width;
height = ihdr.height;
return true;
}
bool EncodePNG(std::span<const u8> in_data, const std::string& out_path, u32 width, u32 height,
u32 stride, s32 level) {
bool ParseDDSKTX(std::span<const u8> in_data, std::vector<u8>& out_data, u32& width, u32& height,
ddsktx_format& format) {
ddsktx_texture_info tc{};
if (!ddsktx_parse(&tc, in_data.data(), in_data.size(), nullptr)) {
return false;
}
width = tc.width;
height = tc.height;
format = tc.format;
ddsktx_sub_data sub_data{};
ddsktx_get_sub(&tc, &sub_data, in_data.data(), in_data.size(), 0, 0, 0);
out_data.resize(sub_data.size_bytes);
std::memcpy(out_data.data(), sub_data.buff, sub_data.size_bytes);
return true;
}
bool EncodePNG(const std::string& out_path, std::span<u8> in_data, u32 width, u32 height,
s32 level) {
auto ctx = make_spng_ctx(SPNG_CTX_ENCODER);
if (!ctx) [[unlikely]] {
return false;
}
auto outfile = FileUtil::IOFile(out_path, "wb");
if (spng_set_png_file(ctx.get(), outfile.Handle())) {
if (spng_set_option(ctx.get(), SPNG_IMG_COMPRESSION_LEVEL, level)) {
return false;
}
if (spng_set_option(ctx.get(), SPNG_IMG_COMPRESSION_LEVEL, level)) {
if (spng_set_option(ctx.get(), SPNG_ENCODE_TO_BUFFER, 1)) {
return false;
}
@ -82,24 +116,22 @@ bool EncodePNG(std::span<const u8> in_data, const std::string& out_path, u32 wid
return false;
}
if (spng_encode_image(ctx.get(), nullptr, 0, SPNG_FMT_PNG,
SPNG_ENCODE_PROGRESSIVE | SPNG_ENCODE_FINALIZE)) {
if (spng_encode_image(ctx.get(), in_data.data(), in_data.size(), SPNG_FMT_PNG,
SPNG_ENCODE_FINALIZE)) {
return false;
}
for (u32 row = 0; row < height; row++) {
const int err = spng_encode_row(ctx.get(), &in_data[row * stride], stride);
if (err == SPNG_EOI) {
break;
}
int ret{};
size_t png_size{};
u8* png_buf = reinterpret_cast<u8*>(spng_get_png_buffer(ctx.get(), &png_size, &ret));
if (err) {
LOG_ERROR(Common, "Failed to save {} by {} image to {} at level {}: error {}", width,
height, out_path, level, err);
return false;
}
if (!png_buf) {
return false;
}
auto file = FileUtil::IOFile(out_path, "wb");
file.WriteBytes(png_buf, png_size);
size_t image_len = 0;
spng_decoded_image_size(ctx.get(), SPNG_FMT_PNG, &image_len);
LOG_ERROR(Common, "{} byte {} by {} image saved to {} at level {}", image_len, width, height,
@ -108,4 +140,14 @@ bool EncodePNG(std::span<const u8> in_data, const std::string& out_path, u32 wid
return true;
}
void FlipTexture(std::span<u8> in_data, u32 width, u32 height, u32 stride) {
for (u32 line = 0; line < height / 2; line++) {
const u32 offset_1 = line * stride;
const u32 offset_2 = (height - line - 1) * stride;
// Swap lines
std::swap_ranges(in_data.begin() + offset_1, in_data.begin() + offset_1 + stride,
in_data.begin() + offset_2);
}
}
} // namespace Common

View File

@ -5,21 +5,20 @@
#include <span>
#include <vector>
#include "common/common_types.h"
#include "common/dds-ktx.h"
namespace Common {
/**
* @brief DecodePNG Given a buffer of png input data decodes said data to RGBA8 format
* and writes the result to out_data, updating width and height to match the file dimentions
* @param in_data The input png data
* @param out_data The decoded RGBA8 pixel data
* @param width The output width of the png image
* @param height The output height of the png image
* @return true on decode success, false otherwise
*/
bool DecodePNG(std::span<const u8> in_data, std::vector<u8>& out_data, u32& width, u32& height);
bool ParsePNG(std::span<const u8> png_data, size_t& decoded_size, u32& width, u32& height);
bool EncodePNG(std::span<const u8> in_data, const std::string& out_path, u32 width, u32 height,
u32 stride, s32 level);
bool DecodePNG(std::span<const u8> png_data, std::span<u8> out_data);
bool ParseDDSKTX(std::span<const u8> in_data, std::vector<u8>& out_data, u32& width, u32& height,
ddsktx_format& format);
bool EncodePNG(const std::string& out_path, std::span<u8> in_data, u32 width, u32 height,
s32 level = 6);
void FlipTexture(std::span<u8> in_data, u32 width, u32 height, u32 stride);
} // namespace Common

View File

@ -4,14 +4,17 @@
#pragma once
#include <type_traits>
#include <span>
#include <memory>
#include "common/common_types.h"
#include <span>
#include <type_traits>
namespace Common {
template <typename T, u32 alignment = 0>
/**
* A ScratchBuffer is a simple heap allocated array without member initialization.
* Main usage is for temporary buffers passed to threads for example
*/
template <typename T>
class ScratchBuffer {
static_assert(std::is_trivial_v<T>, "Must use a POD type");
@ -28,8 +31,12 @@ public:
return buffer.get();
}
[[nodiscard]] std::span<const T> Span() const noexcept {
return std::span<const T>{buffer.get(), size};
[[nodiscard]] std::span<const T> Span(u32 index = 0) const noexcept {
return std::span<const T>{buffer.get() + index, size - index};
}
[[nodiscard]] std::span<T> Span(u32 index = 0) noexcept {
return std::span<T>{buffer.get() + index, size - index};
}
private:

View File

@ -36,8 +36,6 @@ add_library(core STATIC
core.h
core_timing.cpp
core_timing.h
custom_tex_cache.cpp
custom_tex_cache.h
dumping/backend.cpp
dumping/backend.h
file_sys/archive_backend.cpp

View File

@ -12,7 +12,6 @@
#include "audio_core/lle/lle.h"
#include "common/arch.h"
#include "common/logging/log.h"
#include "common/texture.h"
#include "core/arm/arm_interface.h"
#include "core/arm/exclusive_monitor.h"
#if CITRA_ARCH(x86_64) || CITRA_ARCH(arm64)
@ -27,7 +26,6 @@
#include "core/dumping/ffmpeg_backend.h"
#endif
#include "common/settings.h"
#include "core/custom_tex_cache.h"
#include "core/gdbstub/gdbstub.h"
#include "core/global.h"
#include "core/hle/kernel/client_port.h"
@ -48,6 +46,7 @@
#include "core/movie.h"
#include "core/rpc/rpc_server.h"
#include "network/network.h"
#include "video_core/rasterizer_cache/custom_tex_manager.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
@ -317,16 +316,9 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
static_cast<u32>(load_result));
}
perf_stats = std::make_unique<PerfStats>(title_id);
custom_tex_cache = std::make_unique<Core::CustomTexCache>();
if (Settings::values.custom_textures) {
const u64 program_id = Kernel().GetCurrentProcess()->codeset->program_id;
FileUtil::CreateFullPath(fmt::format(
"{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), program_id));
custom_tex_cache->FindCustomTextures(program_id);
}
if (Settings::values.preload_textures) {
custom_tex_cache->PreloadTextures(*GetImageInterface());
custom_tex_manager->FindCustomTextures();
}
status = ResultStatus::Success;
@ -431,7 +423,9 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
video_dumper = std::make_unique<VideoDumper::NullBackend>();
#endif
VideoCore::ResultStatus result = VideoCore::Init(emu_window, secondary_window, *memory);
custom_tex_manager = std::make_unique<VideoCore::CustomTexManager>(*this);
VideoCore::ResultStatus result = VideoCore::Init(emu_window, secondary_window, *this);
if (result != VideoCore::ResultStatus::Success) {
switch (result) {
case VideoCore::ResultStatus::ErrorGenericDrivers:
@ -512,12 +506,12 @@ const VideoDumper::Backend& System::VideoDumper() const {
return *video_dumper;
}
Core::CustomTexCache& System::CustomTexCache() {
return *custom_tex_cache;
VideoCore::CustomTexManager& System::CustomTexManager() {
return *custom_tex_manager;
}
const Core::CustomTexCache& System::CustomTexCache() const {
return *custom_tex_cache;
const VideoCore::CustomTexManager& System::CustomTexManager() const {
return *custom_tex_manager;
}
void System::RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector) {
@ -528,10 +522,6 @@ void System::RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard
registered_swkbd = std::move(swkbd);
}
void System::RegisterImageInterface(std::shared_ptr<Frontend::ImageInterface> image_interface) {
registered_image_interface = std::move(image_interface);
}
void System::Shutdown(bool is_deserializing) {
// Log last frame performance stats
const auto perf_results = GetAndResetPerfStats();

View File

@ -9,10 +9,8 @@
#include <string>
#include <boost/serialization/version.hpp>
#include "common/common_types.h"
#include "core/custom_tex_cache.h"
#include "core/frontend/applets/mii_selector.h"
#include "core/frontend/applets/swkbd.h"
#include "core/frontend/image_interface.h"
#include "core/loader/loader.h"
#include "core/memory.h"
#include "core/perf_stats.h"
@ -58,8 +56,9 @@ class Backend;
}
namespace VideoCore {
class CustomTexManager;
class RendererBase;
}
} // namespace VideoCore
namespace Core {
@ -257,11 +256,11 @@ public:
/// Gets a const reference to the cheat engine
[[nodiscard]] const Cheats::CheatEngine& CheatEngine() const;
/// Gets a reference to the custom texture cache system
[[nodiscard]] Core::CustomTexCache& CustomTexCache();
/// Gets a reference to the custom texture management system
[[nodiscard]] VideoCore::CustomTexManager& CustomTexManager();
/// Gets a const reference to the custom texture cache system
[[nodiscard]] const Core::CustomTexCache& CustomTexCache() const;
/// Gets a const reference to the custom texture management system
[[nodiscard]] const VideoCore::CustomTexManager& CustomTexManager() const;
/// Gets a reference to the video dumper backend
[[nodiscard]] VideoDumper::Backend& VideoDumper();
@ -301,14 +300,6 @@ public:
return registered_swkbd;
}
/// Image interface
void RegisterImageInterface(std::shared_ptr<Frontend::ImageInterface> image_interface);
[[nodiscard]] std::shared_ptr<Frontend::ImageInterface> GetImageInterface() const {
return registered_image_interface;
}
void SaveState(u32 slot) const;
void LoadState(u32 slot);
@ -367,10 +358,7 @@ private:
std::unique_ptr<VideoDumper::Backend> video_dumper;
/// Custom texture cache system
std::unique_ptr<Core::CustomTexCache> custom_tex_cache;
/// Image interface
std::shared_ptr<Frontend::ImageInterface> registered_image_interface;
std::unique_ptr<VideoCore::CustomTexManager> custom_tex_manager;
/// RPC Server for scripting support
std::unique_ptr<RPC::RPCServer> rpc_server;

View File

@ -1,109 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <fmt/format.h>
#include "common/file_util.h"
#include "common/texture.h"
#include "core.h"
#include "core/custom_tex_cache.h"
namespace Core {
CustomTexCache::CustomTexCache() = default;
CustomTexCache::~CustomTexCache() = default;
bool CustomTexCache::IsTextureDumped(u64 hash) const {
return dumped_textures.count(hash);
}
void CustomTexCache::SetTextureDumped(const u64 hash) {
dumped_textures.insert(hash);
}
bool CustomTexCache::IsTextureCached(u64 hash) const {
return custom_textures.count(hash);
}
const CustomTexInfo& CustomTexCache::LookupTexture(u64 hash) const {
return custom_textures.at(hash);
}
void CustomTexCache::CacheTexture(u64 hash, const std::vector<u8>& tex, u32 width, u32 height) {
custom_textures[hash] = {width, height, tex};
}
void CustomTexCache::AddTexturePath(u64 hash, const std::string& path) {
if (custom_texture_paths.count(hash))
LOG_ERROR(Core, "Textures {} and {} conflict!", custom_texture_paths[hash].path, path);
else
custom_texture_paths[hash] = {path, hash};
}
void CustomTexCache::FindCustomTextures(u64 program_id) {
// Custom textures are currently stored as
// [TitleID]/tex1_[width]x[height]_[64-bit hash]_[format].png
const std::string load_path = fmt::format(
"{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), program_id);
if (FileUtil::Exists(load_path)) {
FileUtil::FSTEntry texture_dir;
std::vector<FileUtil::FSTEntry> textures;
// 64 nested folders should be plenty for most cases
FileUtil::ScanDirectoryTree(load_path, texture_dir, 64);
FileUtil::GetAllFilesFromNestedEntries(texture_dir, textures);
for (const auto& file : textures) {
if (file.isDirectory)
continue;
if (file.virtualName.substr(0, 5) != "tex1_")
continue;
u32 width;
u32 height;
u64 hash;
u32 format; // unused
// TODO: more modern way of doing this
if (std::sscanf(file.virtualName.c_str(), "tex1_%ux%u_%llX_%u.png", &width, &height,
&hash, &format) == 4) {
AddTexturePath(hash, file.physicalName);
}
}
}
}
void CustomTexCache::PreloadTextures(Frontend::ImageInterface& image_interface) {
for (const auto& path : custom_texture_paths) {
const auto& path_info = path.second;
Core::CustomTexInfo tex_info;
if (image_interface.DecodePNG(tex_info.tex, tex_info.width, tex_info.height,
path_info.path)) {
// Make sure the texture size is a power of 2
std::bitset<32> width_bits(tex_info.width);
std::bitset<32> height_bits(tex_info.height);
if (width_bits.count() == 1 && height_bits.count() == 1) {
LOG_DEBUG(HW_GPU, "Loaded custom texture from {}", path_info.path);
Common::FlipRGBA8Texture(tex_info.tex, tex_info.width, tex_info.height);
CacheTexture(path_info.hash, tex_info.tex, tex_info.width, tex_info.height);
} else {
LOG_ERROR(HW_GPU, "Texture {} size is not a power of 2", path_info.path);
}
} else {
LOG_ERROR(HW_GPU, "Failed to load custom texture {}", path_info.path);
}
}
}
bool CustomTexCache::CustomTextureExists(u64 hash) const {
return custom_texture_paths.count(hash);
}
const CustomTexPathInfo& CustomTexCache::LookupTexturePathInfo(u64 hash) const {
return custom_texture_paths.at(hash);
}
bool CustomTexCache::IsTexturePathMapEmpty() const {
return custom_texture_paths.size() == 0;
}
} // namespace Core

View File

@ -1,55 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "common/common_types.h"
namespace Frontend {
class ImageInterface;
}
namespace Core {
struct CustomTexInfo {
u32 width;
u32 height;
std::vector<u8> tex;
};
// This is to avoid parsing the filename multiple times
struct CustomTexPathInfo {
std::string path;
u64 hash;
};
// TODO: think of a better name for this class...
class CustomTexCache {
public:
explicit CustomTexCache();
~CustomTexCache();
bool IsTextureDumped(u64 hash) const;
void SetTextureDumped(u64 hash);
bool IsTextureCached(u64 hash) const;
const CustomTexInfo& LookupTexture(u64 hash) const;
void CacheTexture(u64 hash, const std::vector<u8>& tex, u32 width, u32 height);
void AddTexturePath(u64 hash, const std::string& path);
void FindCustomTextures(u64 program_id);
void PreloadTextures(Frontend::ImageInterface& image_interface);
bool CustomTextureExists(u64 hash) const;
const CustomTexPathInfo& LookupTexturePathInfo(u64 hash) const;
bool IsTexturePathMapEmpty() const;
private:
std::unordered_set<u64> dumped_textures;
std::unordered_map<u64, CustomTexInfo> custom_textures;
std::unordered_map<u64, CustomTexPathInfo> custom_texture_paths;
};
} // namespace Core

View File

@ -28,10 +28,10 @@ add_library(video_core STATIC
regs_texturing.h
renderer_base.cpp
renderer_base.h
rasterizer_cache/custom_tex_manager.cpp
rasterizer_cache/custom_tex_manager.h
rasterizer_cache/framebuffer_base.cpp
rasterizer_cache/framebuffer_base.h
rasterizer_cache/hires_replacer.cpp
rasterizer_cache/hires_replacer.h
rasterizer_cache/pixel_format.cpp
rasterizer_cache/pixel_format.h
rasterizer_cache/rasterizer_cache.cpp

View File

@ -0,0 +1,251 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/bit_util.h"
#include "common/file_util.h"
#include "common/hash.h"
#include "common/image_util.h"
#include "common/scratch_buffer.h"
#include "core/core.h"
#include "video_core/rasterizer_cache/custom_tex_manager.h"
#include "video_core/rasterizer_cache/surface_params.h"
namespace VideoCore {
namespace {
using namespace Common;
CustomFileFormat MakeFileFormat(std::string_view ext) {
if (ext == "png") {
return CustomFileFormat::PNG;
} else if (ext == "dds") {
return CustomFileFormat::DDS;
} else if (ext == "ktx") {
return CustomFileFormat::KTX;
}
LOG_ERROR(Render, "Unknown file extension {}", ext);
return CustomFileFormat::PNG;
}
CustomPixelFormat ToCustomPixelFormat(ddsktx_format format) {
switch (format) {
case DDSKTX_FORMAT_RGBA8:
return CustomPixelFormat::RGBA8;
case DDSKTX_FORMAT_BC1:
return CustomPixelFormat::BC1;
case DDSKTX_FORMAT_BC3:
return CustomPixelFormat::BC3;
case DDSKTX_FORMAT_BC5:
return CustomPixelFormat::BC5;
case DDSKTX_FORMAT_BC7:
return CustomPixelFormat::BC7;
case DDSKTX_FORMAT_ASTC4x4:
return CustomPixelFormat::ASTC;
default:
LOG_ERROR(Common, "Unknown dds/ktx pixel format {}", format);
return CustomPixelFormat::RGBA8;
}
}
} // Anonymous namespace
CustomTexManager::CustomTexManager(Core::System& system_)
: system{system_}, workers{std::max(std::thread::hardware_concurrency(), 2U) - 1,
"Hires processing"} {}
CustomTexManager::~CustomTexManager() = default;
void CustomTexManager::FindCustomTextures() {
if (textures_loaded) {
return;
}
// Custom textures are currently stored as
// [TitleID]/tex1_[width]x[height]_[64-bit hash]_[format].png
using namespace FileUtil;
const u64 program_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
const std::string load_path =
fmt::format("{}textures/{:016X}/", GetUserPath(UserPath::LoadDir), program_id);
// Create the directory if it did not exist
if (!Exists(load_path)) {
CreateFullPath(load_path);
}
FSTEntry texture_dir;
std::vector<FSTEntry> textures;
// 64 nested folders should be plenty for most cases
ScanDirectoryTree(load_path, texture_dir, 64);
GetAllFilesFromNestedEntries(texture_dir, textures);
u32 width{};
u32 height{};
u64 hash{};
u32 format{};
std::string ext(3, ' ');
for (const FSTEntry& file : textures) {
const std::string& path = file.physicalName;
if (file.isDirectory || !file.virtualName.starts_with("tex1_")) {
continue;
}
// Parse the texture filename. We only really care about the hash,
// the rest should be queried from the file itself.
if (std::sscanf(file.virtualName.c_str(), "tex1_%ux%u_%lX_%u.%s", &width, &height, &hash,
&format, ext.data()) != 5) {
continue;
}
auto [it, new_texture] = custom_textures.try_emplace(hash);
if (!new_texture) {
LOG_ERROR(Render, "Textures {} and {} conflict, ignoring!", custom_textures[hash].path,
path);
continue;
}
auto& texture = it->second;
texture.file_format = MakeFileFormat(ext);
texture.path = path;
// Query the required information from the file and load it.
// Since this doesn't involve any decoding it shouldn't consume too much RAM.
LoadTexture(texture);
}
textures_loaded = true;
}
void CustomTexManager::DumpTexture(const SurfaceParams& params, std::span<const u8> data) {
const u64 data_hash = ComputeHash64(data.data(), data.size());
const u32 data_size = static_cast<u32>(data.size());
const u32 width = params.width;
const u32 height = params.height;
const PixelFormat format = params.pixel_format;
// Check if it's been dumped already
if (dumped_textures.contains(data_hash)) {
return;
}
// Make sure the texture size is a power of 2.
// If not, the surface is probably a framebuffer
if (!IsPow2(width) || !IsPow2(height)) {
LOG_WARNING(Render, "Not dumping {:016X} because size isn't a power of 2 ({}x{})",
data_hash, width, height);
return;
}
// Allocate a temporary buffer for the thread to use
const u32 decoded_size = width * height * 4;
ScratchBuffer<u8> pixels(data_size + decoded_size);
std::memcpy(pixels.Data(), data.data(), data_size);
// Proceed with the dump.
const u64 program_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
auto dump = [width, height, params, data_hash, format, data_size, program_id,
pixels = std::move(pixels)]() mutable {
// Decode and convert to RGBA8
const std::span encoded = pixels.Span().first(data_size);
const std::span decoded = pixels.Span(data_size);
DecodeTexture(params, params.addr, params.end, encoded, decoded,
params.type == SurfaceType::Color);
std::string dump_path = fmt::format(
"{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), program_id);
if (!FileUtil::CreateFullPath(dump_path)) {
LOG_ERROR(Render, "Unable to create {}", dump_path);
return;
}
dump_path += fmt::format("tex1_{}x{}_{:016X}_{}.png", width, height, data_hash, format);
EncodePNG(dump_path, decoded, width, height);
};
workers.QueueWork(std::move(dump));
dumped_textures.insert(data_hash);
}
const Texture& CustomTexManager::GetTexture(const SurfaceParams& params, std::span<u8> data) {
u64 data_hash;
if (compatibility_mode) {
const u32 decoded_size =
params.width * params.height * GetBytesPerPixel(params.pixel_format);
ScratchBuffer<u8> decoded(decoded_size);
DecodeTexture(params, params.addr, params.end, data, decoded.Span());
data_hash = ComputeHash64(decoded.Data(), decoded_size);
} else {
data_hash = ComputeHash64(data.data(), data.size());
}
auto it = custom_textures.find(data_hash);
if (it == custom_textures.end()) {
LOG_WARNING(
Render, "Unable to find replacement for {}x{} {} surface upload with hash {:016X}",
params.width, params.height, PixelFormatAsString(params.pixel_format), data_hash);
return dummy_texture;
}
LOG_DEBUG(Render, "Assigning {} to {}x{} {} surface with address {:#x} and hash {:016X}",
it->second.path, params.width, params.height,
PixelFormatAsString(params.pixel_format), params.addr, data_hash);
return it->second;
}
void CustomTexManager::DecodeToStaging(const Texture& texture, const StagingData& staging) {
switch (texture.file_format) {
case CustomFileFormat::PNG:
if (!DecodePNG(texture.data, staging.mapped)) {
LOG_ERROR(Render, "Failed to decode png {}", texture.path);
}
if (compatibility_mode) {
const u32 stride = texture.width * 4;
// FlipTexture(staging.mapped, texture.width, texture.height, stride);
}
break;
case CustomFileFormat::DDS:
case CustomFileFormat::KTX:
// Compressed formats don't need CPU decoding
std::memcpy(staging.mapped.data(), texture.data.data(), texture.data.size());
break;
}
}
void CustomTexManager::LoadTexture(Texture& texture) {
std::vector<u8>& data = texture.data;
// Read the file
auto file = FileUtil::IOFile(texture.path, "rb");
data.resize(file.GetSize());
file.ReadBytes(data.data(), file.GetSize());
// Parse it based on the file extension
switch (texture.file_format) {
case CustomFileFormat::PNG:
texture.format = CustomPixelFormat::RGBA8; // Check for other formats too?
if (!ParsePNG(data, texture.staging_size, texture.width, texture.height)) {
LOG_ERROR(Render, "Failed to parse png file {}", texture.path);
return;
}
break;
case CustomFileFormat::DDS:
case CustomFileFormat::KTX:
ddsktx_format format{};
if (!ParseDDSKTX(data, texture.data, texture.width, texture.height, format)) {
LOG_ERROR(Render, "Failed to parse dds/ktx file {}", texture.path);
return;
}
texture.staging_size = texture.data.size();
texture.format = ToCustomPixelFormat(format);
break;
}
ASSERT_MSG(texture.width != 0 && texture.height != 0 && texture.staging_size != 0,
"Invalid parameters read from {}", texture.path);
}
} // namespace VideoCore

View File

@ -0,0 +1,79 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <span>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include "common/thread_worker.h"
#include "video_core/rasterizer_cache/pixel_format.h"
namespace Core {
class System;
}
namespace VideoCore {
struct StagingData;
class SurfaceParams;
enum class PixelFormat : u32;
enum class CustomFileFormat : u32 {
PNG = 0,
DDS = 1,
KTX = 2,
};
struct Texture {
u32 width;
u32 height;
CustomPixelFormat format;
CustomFileFormat file_format;
std::string path;
std::size_t staging_size;
std::vector<u8> data;
operator bool() const noexcept {
return !data.empty();
}
};
class CustomTexManager {
public:
CustomTexManager(Core::System& system);
~CustomTexManager();
/// Searches the load directory assigned to program_id for any custom textures and loads them
void FindCustomTextures();
/// Saves the provided pixel data described by params to disk as png
void DumpTexture(const SurfaceParams& params, std::span<const u8> data);
/// Returns the custom texture handle assigned to the provided data hash
const Texture& GetTexture(const SurfaceParams& params, std::span<u8> data);
/// Decodes the data in texture to a consumable format
void DecodeToStaging(const Texture& texture, const StagingData& staging);
bool CompatibilityMode() const noexcept {
return compatibility_mode;
}
private:
/// Fills the texture structure with information from the file in path
void LoadTexture(Texture& texture);
private:
Core::System& system;
Common::ThreadWorker workers;
std::unordered_set<u64> dumped_textures;
std::unordered_map<u64, Texture> custom_textures;
Texture dummy_texture{};
bool textures_loaded{};
bool compatibility_mode{true};
};
} // namespace VideoCore

View File

@ -1,66 +0,0 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/bit_util.h"
#include "common/file_util.h"
#include "common/scratch_buffer.h"
#include "common/image_util.h"
#include "core/core.h"
#include "video_core/rasterizer_cache/hires_replacer.h"
#include "video_core/rasterizer_cache/surface_base.h"
namespace VideoCore {
HiresReplacer::HiresReplacer() :
workers{std::max(std::thread::hardware_concurrency(), 2U) - 1, "Hires processing"} {
}
void HiresReplacer::DumpSurface(const SurfaceBase& surface, std::span<const u8> data) {
const u32 data_hash = Common::ComputeHash64(data.data(), data.size());
const u32 width = surface.width;
const u32 height = surface.height;
const PixelFormat format = surface.pixel_format;
// Check if it's been dumped already
if (dumped_surfaces.contains(data_hash)) {
return;
}
// If this is a partial update do not dump it, it's probably not a texture
if (surface.BytesInPixels(width * height) != data.size()) {
LOG_WARNING(Render, "Not dumping {:016X} because it's a partial texture update");
return;
}
// Make sure the texture size is a power of 2.
// If not, the surface is probably a framebuffer
if (!Common::IsPow2(surface.width) || !Common::IsPow2(surface.height)) {
LOG_WARNING(Render, "Not dumping {:016X} because size isn't a power of 2 ({}x{})",
data_hash, width, height);
return;
}
// Allocate a temporary buffer for the thread to use
Common::ScratchBuffer<u8> pixels(data.size());
std::memcpy(pixels.Data(), data.data(), data.size());
// Proceed with the dump. The texture should be already decoded
const u64 program_id = Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id;
const auto dump = [width, height, data_hash, format, program_id, pixels = std::move(pixels)]() {
std::string dump_path =
fmt::format("{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), program_id);
if (!FileUtil::CreateFullPath(dump_path)) {
LOG_ERROR(Render, "Unable to create {}", dump_path);
return;
}
dump_path += fmt::format("tex1_{}x{}_{:016X}_{}.png", width, height, data_hash, format);
Common::EncodePNG(pixels.Span(), dump_path, width, height, width, 0);
};
dump();
}
} // namespace VideoCore

View File

@ -1,29 +0,0 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <span>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "common/thread_worker.h"
namespace VideoCore {
class SurfaceBase;
class HiresReplacer {
public:
HiresReplacer();
void DumpSurface(const SurfaceBase& surface, std::span<const u8> data);
private:
Common::ThreadWorker workers;
std::unordered_set<u64> dumped_surfaces;
};
} // namespace VideoCore

View File

@ -47,6 +47,23 @@ std::string_view PixelFormatAsString(PixelFormat format) {
}
}
std::string_view CustomPixelFormatAsString(CustomPixelFormat format) {
switch (format) {
case CustomPixelFormat::RGBA8:
return "RGBA8";
case CustomPixelFormat::BC1:
return "BC1";
case CustomPixelFormat::BC3:
return "BC3";
case CustomPixelFormat::BC5:
return "BC5";
case CustomPixelFormat::BC7:
return "BC7";
case CustomPixelFormat::ASTC:
return "ASTC";
}
}
bool CheckFormatsBlittable(PixelFormat source_format, PixelFormat dest_format) {
SurfaceType source_type = GetFormatType(source_format);
SurfaceType dest_type = GetFormatType(dest_format);

View File

@ -35,6 +35,15 @@ enum class PixelFormat : u32 {
Invalid = 255,
};
enum class CustomPixelFormat : u32 {
RGBA8 = 0,
BC1 = 1,
BC3 = 2,
BC5 = 3,
BC7 = 4,
ASTC = 5,
};
enum class SurfaceType : u32 {
Color = 0,
Texture = 1,
@ -112,6 +121,8 @@ constexpr u32 GetBytesPerPixel(PixelFormat format) {
std::string_view PixelFormatAsString(PixelFormat format);
std::string_view CustomPixelFormatAsString(CustomPixelFormat format);
bool CheckFormatsBlittable(PixelFormat source_format, PixelFormat dest_format);
PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format);

View File

@ -10,6 +10,7 @@
#include "common/microprofile.h"
#include "core/memory.h"
#include "video_core/pica_state.h"
#include "video_core/rasterizer_cache/custom_tex_manager.h"
#include "video_core/rasterizer_cache/rasterizer_cache_base.h"
#include "video_core/rasterizer_cache/surface_base.h"
#include "video_core/video_core.h"
@ -26,10 +27,13 @@ inline auto RangeFromInterval(auto& map, const auto& interval) {
}
template <class T>
RasterizerCache<T>::RasterizerCache(Memory::MemorySystem& memory_, Runtime& runtime_)
: memory{memory_}, runtime{runtime_}, resolution_scale_factor{
VideoCore::GetResolutionScaleFactor()},
dump_textures{Settings::values.dump_textures.GetValue()} {
RasterizerCache<T>::RasterizerCache(Memory::MemorySystem& memory_,
CustomTexManager& custom_tex_manager_, Runtime& runtime_)
: memory{memory_}, runtime{runtime_}, custom_tex_manager{custom_tex_manager_},
resolution_scale_factor{VideoCore::GetResolutionScaleFactor()},
dump_textures{Settings::values.dump_textures.GetValue()},
use_custom_textures{Settings::values.custom_textures.GetValue()} {
using TextureConfig = Pica::TexturingRegs::TextureConfig;
// Create null handles for all cached resources
@ -624,8 +628,15 @@ auto RasterizerCache<T>::GetFramebufferSurfaces(bool using_color_fb, bool using_
// Update resolution_scale_factor and reset cache if changed
const bool resolution_scale_changed =
resolution_scale_factor != VideoCore::GetResolutionScaleFactor();
if (resolution_scale_changed) [[unlikely]] {
const bool custom_textures_changed =
use_custom_textures != Settings::values.custom_textures.GetValue();
if (resolution_scale_changed || custom_textures_changed) [[unlikely]] {
resolution_scale_factor = VideoCore::GetResolutionScaleFactor();
use_custom_textures = Settings::values.custom_textures.GetValue();
if (use_custom_textures) {
custom_tex_manager.FindCustomTextures();
}
UnregisterAll();
}
@ -866,22 +877,29 @@ void RasterizerCache<T>::UploadSurface(const Surface& surface, SurfaceInterval i
MICROPROFILE_SCOPE(RasterizerCache_SurfaceLoad);
const auto staging = runtime.FindStaging(
load_info.width * load_info.height * surface->GetInternalBytesPerPixel(), true);
MemoryRef source_ptr = memory.GetPhysicalRef(load_info.addr);
if (!source_ptr) [[unlikely]] {
return;
}
const auto upload_data = source_ptr.GetWriteBytes(load_info.end - load_info.addr);
if (dump_textures) {
custom_tex_manager.DumpTexture(load_info, upload_data);
}
// Check if we need to replace the texture
if (use_custom_textures && UploadCustomSurface(surface, load_info, upload_data)) {
return;
}
// Upload the 3DS texture to the host GPU
const u32 upload_size =
load_info.width * load_info.height * surface->GetInternalBytesPerPixel();
const StagingData staging = runtime.FindStaging(upload_size, true);
DecodeTexture(load_info, load_info.addr, load_info.end, upload_data, staging.mapped,
runtime.NeedsConvertion(surface->pixel_format));
if (dump_textures) {
replacer.DumpSurface(*surface, staging.mapped);
}
const BufferTextureCopy upload = {
.buffer_offset = 0,
.buffer_size = staging.size,
@ -891,6 +909,60 @@ void RasterizerCache<T>::UploadSurface(const Surface& surface, SurfaceInterval i
surface->Upload(upload, staging);
}
template <class T>
bool RasterizerCache<T>::UploadCustomSurface(const Surface& surface, const SurfaceParams& load_info,
std::span<u8> upload_data) {
const u32 level = surface->LevelOf(load_info.addr);
const bool is_base_level = level == 0;
const Texture& texture = custom_tex_manager.GetTexture(load_info, upload_data);
// The old texture pack system did not support mipmaps so older packs might do
// wonky things. For example Henriko's pack has mipmaps larger than the base
// level. To avoid crashes just don't upload mipmaps
if (custom_tex_manager.CompatibilityMode() && !is_base_level) {
return true;
}
if (!texture) {
return false;
}
// Swap the internal surface allocation to the desired dimentions and format
if (is_base_level && !surface->Swap(texture.width, texture.height, texture.format)) {
// This means the backend doesn't support the custom compression format.
// We could implement a CPU/GPU decoder but it's always better for packs to
// have compatible compression formats.
LOG_ERROR(HW_GPU, "Custom compressed format {} unsupported by host GPU", texture.format);
return false;
}
// Ensure surface has a compatible allocation before proceeding
if (!surface->IsCustom() || surface->CustomPixelFormat() != texture.format) {
LOG_ERROR(HW_GPU, "Surface does not have a compatible allocation, ignoring");
return true;
}
// Copy and decode the custom texture to the staging buffer
const u32 custom_size = static_cast<u32>(texture.staging_size);
const StagingData staging = runtime.FindStaging(custom_size, true);
custom_tex_manager.DecodeToStaging(texture, staging);
// Upload surface
const BufferTextureCopy upload = {
.buffer_offset = 0,
.buffer_size = custom_size,
.texture_rect = {0, texture.height, texture.width, 0},
.texture_level = level,
};
surface->Upload(upload, staging);
// Manually generate mipmaps in compatibility mode
if (custom_tex_manager.CompatibilityMode()) {
runtime.GenerateMipmaps(*surface);
}
return true;
}
template <class T>
void RasterizerCache<T>::DownloadSurface(const Surface& surface, SurfaceInterval interval) {
const SurfaceParams flush_info = surface->FromInterval(interval);
@ -898,8 +970,9 @@ void RasterizerCache<T>::DownloadSurface(const Surface& surface, SurfaceInterval
const u32 flush_end = boost::icl::last_next(interval);
ASSERT(flush_start >= surface->addr && flush_end <= surface->end);
const auto staging = runtime.FindStaging(
flush_info.width * flush_info.height * surface->GetInternalBytesPerPixel(), false);
const u32 flush_size =
flush_info.width * flush_info.height * surface->GetInternalBytesPerPixel();
const StagingData staging = runtime.FindStaging(flush_size, false);
const BufferTextureCopy download = {
.buffer_offset = 0,

View File

@ -7,9 +7,10 @@
#include <algorithm>
#include <optional>
#include <unordered_map>
#include <unordered_set>
#include <boost/icl/interval_map.hpp>
#include <boost/range/iterator_range.hpp>
#include "video_core/rasterizer_cache/hires_replacer.h"
#include "common/thread_worker.h"
#include "video_core/rasterizer_cache/sampler_params.h"
#include "video_core/rasterizer_cache/surface_params.h"
#include "video_core/rasterizer_cache/utils.h"
@ -37,7 +38,7 @@ enum class MatchFlags {
DECLARE_ENUM_FLAG_OPERATORS(MatchFlags);
class RasterizerAccelerated;
class CustomTexManager;
template <class T>
class RasterizerCache : NonCopyable {
@ -57,8 +58,14 @@ class RasterizerCache : NonCopyable {
using SurfaceRect_Tuple = std::tuple<Surface, Common::Rectangle<u32>>;
using PageMap = boost::icl::interval_map<u32, int>;
struct RenderTargets {
Surface color_surface;
Surface depth_surface;
};
public:
RasterizerCache(Memory::MemorySystem& memory, Runtime& runtime);
RasterizerCache(Memory::MemorySystem& memory, CustomTexManager& custom_tex_manager,
Runtime& runtime);
~RasterizerCache();
/// Perform hardware accelerated texture copy according to the provided configuration
@ -150,6 +157,10 @@ private:
/// Copies pixel data in interval from the guest VRAM to the host GPU surface
void UploadSurface(const Surface& surface, SurfaceInterval interval);
/// Uploads a custom texture associated with upload_data to the target surface
bool UploadCustomSurface(const Surface& surface, const SurfaceParams& load_info,
std::span<u8> upload_data);
/// Copies pixel data in interval from the host GPU surface to the guest VRAM
void DownloadSurface(const Surface& surface, SurfaceInterval interval);
@ -185,7 +196,7 @@ private:
private:
Memory::MemorySystem& memory;
Runtime& runtime;
HiresReplacer replacer;
CustomTexManager& custom_tex_manager;
PageMap cached_pages;
SurfaceMap dirty_regions;
std::vector<Surface> remove_surfaces;
@ -199,14 +210,11 @@ private:
std::unordered_map<SamplerParams, SamplerId> samplers;
SlotVector<Sampler> slot_samplers;
struct RenderTargets {
Surface color_surface;
Surface depth_surface;
};
RenderTargets render_targets;
const bool& dump_textures;
// Custom textures
bool dump_textures;
bool use_custom_textures;
};
} // namespace VideoCore

View File

@ -12,16 +12,13 @@ namespace VideoCore {
using SurfaceRegions = boost::icl::interval_set<PAddr, std::less, SurfaceInterval>;
enum class CustomPixelFormat : u32;
class SurfaceBase : public SurfaceParams {
public:
SurfaceBase();
explicit SurfaceBase(const SurfaceParams& params);
[[nodiscard]] bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept {
const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size);
return addr < overlap_end && overlap_addr < end;
}
/// Returns true when this surface can be used to fill the fill_interval of dest_surface
bool CanFill(const SurfaceParams& dest_surface, SurfaceInterval fill_interval) const;
@ -35,12 +32,23 @@ public:
/// Returns the clear value used to validate another surface from this fill surface
ClearValue MakeClearValue(PAddr copy_addr, PixelFormat dst_format);
/// Returns true when the region denoted by interval is valid
bool IsCustom() const noexcept {
return is_custom;
}
CustomPixelFormat CustomPixelFormat() const noexcept {
return custom_format;
}
bool Overlaps(PAddr overlap_addr, size_t overlap_size) const noexcept {
const PAddr overlap_end = overlap_addr + static_cast<PAddr>(overlap_size);
return addr < overlap_end && overlap_addr < end;
}
bool IsRegionValid(SurfaceInterval interval) const {
return (invalid_regions.find(interval) == invalid_regions.end());
}
/// Returns true when the entire surface is invalid
bool IsFullyInvalid() const {
auto interval = GetInterval();
return *invalid_regions.equal_range(interval).first == interval;
@ -53,6 +61,8 @@ private:
public:
bool registered = false;
bool picked = false;
bool is_custom = false;
enum CustomPixelFormat custom_format {};
SurfaceRegions invalid_regions;
std::array<u8, 4> fill_data;
u32 fill_size = 0;

View File

@ -77,18 +77,10 @@ struct BufferTextureCopy {
u32 texture_level;
};
struct HostTextureTag {
PixelFormat format{};
TextureType type{};
u32 width = 0;
u32 height = 0;
u32 levels = 1;
auto operator<=>(const HostTextureTag&) const noexcept = default;
const u64 Hash() const {
return Common::ComputeHash64(this, sizeof(HostTextureTag));
}
struct StagingData {
u32 size = 0;
std::span<u8> mapped{};
u64 buffer_offset = 0;
};
struct TextureCubeConfig {
@ -144,13 +136,6 @@ void DecodeTexture(const SurfaceParams& surface_info, PAddr start_addr, PAddr en
} // namespace VideoCore
namespace std {
template <>
struct hash<VideoCore::HostTextureTag> {
std::size_t operator()(const VideoCore::HostTextureTag& tag) const noexcept {
return tag.Hash();
}
};
template <>
struct hash<VideoCore::TextureCubeConfig> {
std::size_t operator()(const VideoCore::TextureCubeConfig& config) const noexcept {

View File

@ -5,6 +5,7 @@
#include <glad/glad.h>
#include "common/assert.h"
#include "core/core.h"
#include "video_core/rasterizer_cache/pixel_format.h"
#include "video_core/renderer_opengl/gl_driver.h"
namespace OpenGL {
@ -96,6 +97,21 @@ bool Driver::HasBug(DriverBug bug) const {
return True(bugs & bug);
}
bool Driver::IsCustomFormatSupported(VideoCore::CustomPixelFormat format) const {
switch (format) {
case VideoCore::CustomPixelFormat::RGBA8:
return true;
case VideoCore::CustomPixelFormat::BC1:
case VideoCore::CustomPixelFormat::BC3:
case VideoCore::CustomPixelFormat::BC5:
return ext_texture_compression_s3tc;
case VideoCore::CustomPixelFormat::BC7:
return arb_texture_compression_bptc;
case VideoCore::CustomPixelFormat::ASTC:
return is_gles;
}
}
void Driver::ReportDriverInfo() {
// Report the context version and the vendor string
gl_version = std::string_view{reinterpret_cast<const char*>(glGetString(GL_VERSION))};
@ -135,6 +151,8 @@ void Driver::CheckExtensionSupport() {
arb_buffer_storage = GLAD_GL_ARB_buffer_storage;
ext_clip_cull_distance = GLAD_GL_EXT_clip_cull_distance;
arb_direct_state_access = GLAD_GL_ARB_direct_state_access;
ext_texture_compression_s3tc = GLAD_GL_EXT_texture_compression_s3tc;
arb_texture_compression_bptc = GLAD_GL_ARB_texture_compression_bptc;
}
void Driver::FindBugs() {

View File

@ -6,6 +6,10 @@
#include <string_view>
namespace VideoCore {
enum class CustomPixelFormat : u32;
}
namespace OpenGL {
enum class Vendor {
@ -40,6 +44,9 @@ public:
/// Returns true of the driver has a particular bug stated in the DriverBug enum
bool HasBug(DriverBug bug) const;
/// Returns true if the driver supports the provided custom format
bool IsCustomFormatSupported(VideoCore::CustomPixelFormat format) const;
/// Returns the vendor of the currently selected physical device
Vendor GetVendor() const {
return vendor;
@ -90,6 +97,8 @@ private:
bool arb_buffer_storage{};
bool ext_clip_cull_distance{};
bool arb_direct_state_access{};
bool ext_texture_compression_s3tc{};
bool arb_texture_compression_bptc{};
std::string_view gl_version{};
std::string_view gpu_vendor{};

View File

@ -36,9 +36,12 @@ constexpr std::size_t TEXTURE_BUFFER_SIZE = 1 * 1024 * 1024;
} // Anonymous namespace
RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory_, Frontend::EmuWindow& emu_window,
Driver& driver_)
: RasterizerAccelerated{memory_}, driver{driver_}, runtime{driver}, res_cache{memory, runtime},
RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory,
VideoCore::CustomTexManager& custom_tex_manager,
Frontend::EmuWindow& emu_window, Driver& driver_)
: RasterizerAccelerated{memory}, driver{driver_}, runtime{driver}, res_cache{memory,
custom_tex_manager,
runtime},
shader_program_manager{emu_window, driver, !driver.IsOpenGLES()},
vertex_buffer{GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE}, uniform_buffer{GL_UNIFORM_BUFFER,
UNIFORM_BUFFER_SIZE},

View File

@ -15,6 +15,10 @@ namespace Frontend {
class EmuWindow;
}
namespace VideoCore {
class CustomTexManager;
}
namespace OpenGL {
struct ScreenInfo;
@ -24,8 +28,9 @@ class ShaderProgramManager;
class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
public:
explicit RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window,
Driver& driver);
explicit RasterizerOpenGL(Memory::MemorySystem& memory,
VideoCore::CustomTexManager& custom_tex_manager,
Frontend::EmuWindow& emu_window, Driver& driver);
~RasterizerOpenGL() override;
void LoadDiskResources(const std::atomic_bool& stop_loading,

View File

@ -16,6 +16,7 @@
namespace OpenGL {
using VideoCore::StagingData;
using VideoCore::TextureType;
constexpr FormatTuple DEFAULT_TUPLE = {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE};
@ -42,6 +43,18 @@ static constexpr std::array COLOR_TUPLES_OES = {
FormatTuple{GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, // RGBA4
};
static constexpr std::array CUSTOM_TUPLES = {
DEFAULT_TUPLE,
FormatTuple{GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
GL_UNSIGNED_BYTE},
FormatTuple{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
GL_UNSIGNED_BYTE},
FormatTuple{GL_COMPRESSED_RG_RGTC2, GL_COMPRESSED_RG_RGTC2, GL_UNSIGNED_BYTE},
FormatTuple{GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB,
GL_UNSIGNED_BYTE},
FormatTuple{GL_COMPRESSED_RGBA_ASTC_4x4, GL_COMPRESSED_RGBA_ASTC_4x4, GL_UNSIGNED_BYTE},
};
[[nodiscard]] GLbitfield MakeBufferMask(VideoCore::SurfaceType type) {
switch (type) {
case VideoCore::SurfaceType::Color:
@ -97,7 +110,6 @@ StagingData TextureRuntime::FindStaging(u32 size, bool upload) {
auto [data, offset, invalidate] = upload_buffer.Map(size, 4);
return StagingData{
.buffer = upload_buffer.Handle(),
.size = size,
.mapped = std::span{data, size},
.buffer_offset = offset,
@ -121,14 +133,22 @@ const FormatTuple& TextureRuntime::GetFormatTuple(VideoCore::PixelFormat pixel_f
return DEFAULT_TUPLE;
}
OGLTexture TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat format, VideoCore::TextureType type) {
const FormatTuple& TextureRuntime::GetFormatTuple(VideoCore::CustomPixelFormat pixel_format) {
const std::size_t format_index = static_cast<std::size_t>(pixel_format);
return CUSTOM_TUPLES[format_index];
}
void TextureRuntime::Recycle(const HostTextureTag tag, Allocation&& alloc) {
texture_recycler.emplace(tag, std::move(alloc));
}
Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels, const FormatTuple& tuple,
VideoCore::TextureType type) {
const GLenum target =
type == VideoCore::TextureType::CubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
// Attempt to recycle an unused texture
const VideoCore::HostTextureTag key = {
.format = format,
const HostTextureTag key = {
.tuple = tuple,
.type = type,
.width = width,
.height = height,
@ -136,9 +156,9 @@ OGLTexture TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
};
if (auto it = texture_recycler.find(key); it != texture_recycler.end()) {
OGLTexture texture = std::move(it->second);
Allocation alloc = std::move(it->second);
texture_recycler.erase(it);
return texture;
return alloc;
}
// Allocate new texture
@ -148,7 +168,6 @@ OGLTexture TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
glActiveTexture(GL_TEXTURE0);
glBindTexture(target, texture.handle);
const auto& tuple = GetFormatTuple(format);
glTexStorage2D(target, levels, tuple.internal_format, width, height);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -156,7 +175,14 @@ OGLTexture TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(target, OpenGLState::GetCurState().texture_units[0].texture_2d);
return texture;
return Allocation{
.texture = std::move(texture),
.tuple = tuple,
.width = width,
.height = height,
.levels = levels,
};
}
bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClear& clear) {
@ -267,7 +293,7 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
return true;
}
void TextureRuntime::GenerateMipmaps(Surface& surface, u32 max_level) {
void TextureRuntime::GenerateMipmaps(Surface& surface) {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
@ -276,7 +302,7 @@ void TextureRuntime::GenerateMipmaps(Surface& surface, u32 max_level) {
state.Apply();
glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_level);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, surface.levels - 1);
glGenerateMipmap(GL_TEXTURE_2D);
}
@ -318,22 +344,24 @@ void TextureRuntime::BindFramebuffer(GLenum target, GLint level, GLenum textarge
Surface::Surface(VideoCore::SurfaceParams& params, TextureRuntime& runtime)
: VideoCore::SurfaceBase{params}, runtime{runtime}, driver{runtime.GetDriver()} {
if (pixel_format != VideoCore::PixelFormat::Invalid) {
texture = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, params.pixel_format,
texture_type);
const auto& tuple = runtime.GetFormatTuple(pixel_format);
alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, tuple, texture_type);
}
}
Surface::~Surface() {
if (pixel_format != VideoCore::PixelFormat::Invalid) {
const VideoCore::HostTextureTag tag = {
.format = pixel_format,
.type = texture_type,
.width = GetScaledWidth(),
.height = GetScaledHeight(),
.levels = levels,
};
runtime.texture_recycler.emplace(tag, std::move(texture));
if (pixel_format == VideoCore::PixelFormat::Invalid) {
return;
}
const HostTextureTag tag = {
.tuple = alloc.tuple,
.type = texture_type,
.width = alloc.width,
.height = alloc.height,
.levels = alloc.levels,
};
runtime.Recycle(tag, std::move(alloc));
}
void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging) {
@ -344,25 +372,31 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
if (is_scaled) {
ScaledUpload(upload, staging);
} else {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
const VideoCore::Rect2D rect = upload.texture_rect;
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(rect.GetWidth()));
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, staging.buffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, runtime.upload_buffer.Handle());
// Unmap the buffer FindStaging mapped beforehand
runtime.upload_buffer.Unmap(staging.size);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.handle);
glBindTexture(GL_TEXTURE_2D, Handle());
const auto& tuple = runtime.GetFormatTuple(pixel_format);
glTexSubImage2D(GL_TEXTURE_2D, upload.texture_level, rect.left, rect.bottom,
rect.GetWidth(), rect.GetHeight(), tuple.format, tuple.type,
reinterpret_cast<void*>(staging.buffer_offset));
const auto& tuple = alloc.tuple;
if (is_custom && custom_format != VideoCore::CustomPixelFormat::RGBA8) {
glCompressedTexSubImage2D(GL_TEXTURE_2D, upload.texture_level, rect.left, rect.bottom,
rect.GetWidth(), rect.GetHeight(), tuple.format, staging.size,
reinterpret_cast<void*>(staging.buffer_offset));
} else {
glTexSubImage2D(GL_TEXTURE_2D, upload.texture_level, rect.left, rect.bottom,
rect.GetWidth(), rect.GetHeight(), tuple.format, tuple.type,
reinterpret_cast<void*>(staging.buffer_offset));
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
// Restore old texture
glBindTexture(GL_TEXTURE_2D, OpenGLState::GetCurState().texture_units[0].texture_2d);
}
}
@ -374,23 +408,53 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
if (is_scaled) {
ScaledDownload(download, staging);
} else {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
const VideoCore::Rect2D rect = download.texture_rect;
glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(rect.GetWidth()));
runtime.BindFramebuffer(GL_READ_FRAMEBUFFER, download.texture_level, GL_TEXTURE_2D, type,
texture.handle);
Handle());
const auto& tuple = runtime.GetFormatTuple(pixel_format);
glReadPixels(rect.left, rect.bottom, rect.GetWidth(), rect.GetHeight(), tuple.format,
tuple.type, staging.mapped.data());
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
// Restore previous framebuffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, OpenGLState::GetCurState().draw.read_framebuffer);
}
}
bool Surface::Swap(u32 width, u32 height, VideoCore::CustomPixelFormat format) {
if (!driver.IsCustomFormatSupported(format)) {
return false;
}
const auto& tuple = runtime.GetFormatTuple(format);
if (alloc.Matches(width, height, levels, tuple)) {
return true;
}
const HostTextureTag tag = {
.tuple = alloc.tuple,
.type = texture_type,
.width = alloc.width,
.height = alloc.height,
.levels = alloc.levels,
};
runtime.Recycle(tag, std::move(alloc));
is_custom = true;
custom_format = format;
alloc = runtime.Allocate(width, height, levels, tuple, texture_type);
LOG_DEBUG(Render_OpenGL, "Swapped {}x{} {} surface at address {:#x} to {}x{} {}",
GetScaledWidth(), GetScaledHeight(), VideoCore::PixelFormatAsString(pixel_format),
addr, width, height, VideoCore::CustomPixelFormatAsString(format));
return true;
}
void Surface::ScaledUpload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging) {
const u32 rect_width = upload.texture_rect.GetWidth();
const u32 rect_height = upload.texture_rect.GetHeight();
@ -412,7 +476,8 @@ void Surface::ScaledUpload(const VideoCore::BufferTextureCopy& upload, const Sta
unscaled_surface.Upload(unscaled_upload, staging);
const auto& filterer = runtime.GetFilterer();
if (!filterer.Filter(unscaled_surface.texture, unscaled_rect, texture, scaled_rect, type)) {
if (!filterer.Filter(unscaled_surface.alloc.texture, unscaled_rect, alloc.texture, scaled_rect,
type)) {
const VideoCore::TextureBlit blit = {
.src_level = 0,
.dst_level = upload.texture_level,
@ -450,7 +515,7 @@ void Surface::ScaledDownload(const VideoCore::BufferTextureCopy& download,
runtime.BlitTextures(*this, unscaled_surface, blit);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, unscaled_surface.texture.handle);
glBindTexture(GL_TEXTURE_2D, unscaled_surface.Handle());
const auto& tuple = runtime.GetFormatTuple(pixel_format);
if (driver.IsOpenGLES()) {

View File

@ -13,21 +13,65 @@
#include "video_core/renderer_opengl/gl_stream_buffer.h"
#include "video_core/renderer_opengl/texture_filters/texture_filterer.h"
namespace VideoCore {
enum class CustomPixelFormat : u32;
}
namespace OpenGL {
struct FormatTuple {
GLint internal_format;
GLenum format;
GLenum type;
bool operator==(const FormatTuple& other) const noexcept {
return std::tie(internal_format, format, type) ==
std::tie(other.internal_format, other.format, other.type);
}
};
struct StagingData {
GLuint buffer;
u32 size = 0;
std::span<u8> mapped{};
u64 buffer_offset = 0;
struct Allocation {
OGLTexture texture;
FormatTuple tuple;
u32 width;
u32 height;
u32 levels;
bool Matches(u32 width_, u32 height_, u32 levels_, const FormatTuple& tuple_) const {
return std::tie(width, height, levels, tuple) == std::tie(width_, height_, levels_, tuple_);
}
};
struct HostTextureTag {
FormatTuple tuple{};
VideoCore::TextureType type{};
u32 width = 0;
u32 height = 0;
u32 levels = 1;
bool operator==(const HostTextureTag& other) const noexcept {
return std::tie(tuple, type, width, height, levels) ==
std::tie(other.tuple, other.type, other.width, other.height, other.levels);
}
const u64 Hash() const {
return Common::ComputeHash64(this, sizeof(HostTextureTag));
}
};
} // namespace OpenGL
namespace std {
template <>
struct hash<OpenGL::HostTextureTag> {
std::size_t operator()(const OpenGL::HostTextureTag& tag) const noexcept {
return tag.Hash();
}
};
} // namespace std
namespace OpenGL {
class Driver;
class Surface;
@ -44,16 +88,20 @@ public:
~TextureRuntime();
/// Maps an internal staging buffer of the provided size of pixel uploads/downloads
StagingData FindStaging(u32 size, bool upload);
VideoCore::StagingData FindStaging(u32 size, bool upload);
/// Returns the OpenGL format tuple associated with the provided pixel format
const FormatTuple& GetFormatTuple(VideoCore::PixelFormat pixel_format);
const FormatTuple& GetFormatTuple(VideoCore::CustomPixelFormat pixel_format);
/// Causes a GPU command flush
void Finish() const {}
/// Takes back ownership of the allocation for recycling
void Recycle(const HostTextureTag tag, Allocation&& alloc);
/// Allocates an OpenGL texture with the specified dimentions and format
OGLTexture Allocate(u32 width, u32 height, u32 levels, VideoCore::PixelFormat format,
Allocation Allocate(u32 width, u32 height, u32 levels, const FormatTuple& tuple,
VideoCore::TextureType type);
/// Fills the rectangle of the texture with the clear value provided
@ -66,7 +114,7 @@ public:
bool BlitTextures(Surface& surface, Surface& dest, const VideoCore::TextureBlit& blit);
/// Generates mipmaps for all the available levels of the texture
void GenerateMipmaps(Surface& surface, u32 max_level);
void GenerateMipmaps(Surface& surface);
/// Returns all source formats that support reinterpretation to the dest format
[[nodiscard]] const ReinterpreterList& GetPossibleReinterpretations(
@ -94,7 +142,7 @@ private:
Driver& driver;
TextureFilterer filterer;
std::array<ReinterpreterList, VideoCore::PIXEL_FORMAT_COUNT> reinterpreters;
std::unordered_multimap<VideoCore::HostTextureTag, OGLTexture> texture_recycler;
std::unordered_multimap<HostTextureTag, Allocation> texture_recycler;
std::unordered_map<u64, OGLFramebuffer, Common::IdentityHash<u64>> framebuffer_cache;
StreamBuffer upload_buffer;
std::vector<u8> download_buffer;
@ -108,14 +156,18 @@ public:
/// Returns the surface image handle
GLuint Handle() const noexcept {
return texture.handle;
return alloc.texture.handle;
}
/// Uploads pixel data in staging to a rectangle region of the surface texture
void Upload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging);
void Upload(const VideoCore::BufferTextureCopy& upload, const VideoCore::StagingData& staging);
/// Downloads pixel data to staging from a rectangle region of the surface texture
void Download(const VideoCore::BufferTextureCopy& download, const StagingData& staging);
void Download(const VideoCore::BufferTextureCopy& download,
const VideoCore::StagingData& staging);
/// Swaps the internal allocation to match the provided dimentions and format
bool Swap(u32 width, u32 height, VideoCore::CustomPixelFormat format);
/// Returns the bpp of the internal surface format
u32 GetInternalBytesPerPixel() const {
@ -124,15 +176,17 @@ public:
private:
/// Uploads pixel data to scaled texture
void ScaledUpload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging);
void ScaledUpload(const VideoCore::BufferTextureCopy& upload,
const VideoCore::StagingData& staging);
/// Downloads scaled image by downscaling the requested rectangle
void ScaledDownload(const VideoCore::BufferTextureCopy& download, const StagingData& staging);
void ScaledDownload(const VideoCore::BufferTextureCopy& download,
const VideoCore::StagingData& staging);
private:
TextureRuntime& runtime;
const Driver& driver;
OGLTexture texture{};
Allocation alloc;
};
class Framebuffer : public VideoCore::FramebufferBase {

View File

@ -273,14 +273,13 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
return matrix;
}
RendererOpenGL::RendererOpenGL(Memory::MemorySystem& memory_, Frontend::EmuWindow& window,
RendererOpenGL::RendererOpenGL(Core::System& system_, Frontend::EmuWindow& window,
Frontend::EmuWindow* secondary_window)
: RendererBase{window, secondary_window}, memory{memory_},
: RendererBase{window, secondary_window}, system{system_}, memory{system.Memory()},
driver{Settings::values.graphics_api.GetValue() == Settings::GraphicsAPI::OpenGLES,
Settings::values.renderer_debug.GetValue()},
rasterizer{memory, render_window, driver}, frame_dumper{
Core::System::GetInstance().VideoDumper(),
window} {
rasterizer{memory, system.CustomTexManager(), render_window, driver},
frame_dumper{system.VideoDumper(), window} {
const Vendor vendor = driver.GetVendor();
if (vendor == Vendor::Generic || vendor == Vendor::Unknown) {
@ -326,8 +325,6 @@ void RendererOpenGL::SwapBuffers() {
}
m_current_frame++;
Core::System& system = Core::System::GetInstance();
system.perf_stats->EndSystemFrame();
render_window.PollEvents();

View File

@ -11,6 +11,10 @@
#include "video_core/renderer_opengl/gl_driver.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
namespace Core {
class System;
}
namespace Layout {
struct FramebufferLayout;
}
@ -60,7 +64,7 @@ class RasterizerOpenGL;
class RendererOpenGL : public VideoCore::RendererBase {
public:
explicit RendererOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& window,
explicit RendererOpenGL(Core::System& system, Frontend::EmuWindow& window,
Frontend::EmuWindow* secondary_window);
~RendererOpenGL() override;
@ -122,6 +126,7 @@ private:
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
private:
Core::System& system;
Memory::MemorySystem& memory;
Driver driver;
OpenGLState state;

View File

@ -100,10 +100,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
} // Anonymous namespace
RendererVulkan::RendererVulkan(Memory::MemorySystem& memory_, Frontend::EmuWindow& window,
RendererVulkan::RendererVulkan(Core::System& system_, Frontend::EmuWindow& window,
Frontend::EmuWindow* secondary_window)
: RendererBase{window, secondary_window}, memory{memory_},
telemetry_session{Core::System::GetInstance().TelemetrySession()},
: RendererBase{window, secondary_window}, system{system_}, memory{system.Memory()},
telemetry_session{system.TelemetrySession()},
instance{window, Settings::values.physical_device.GetValue()}, scheduler{instance,
renderpass_cache},
renderpass_cache{instance, scheduler}, desc_manager{instance, scheduler},
@ -111,8 +111,9 @@ RendererVulkan::RendererVulkan(Memory::MemorySystem& memory_, Frontend::EmuWindo
renderpass_cache},
vertex_buffer{instance, scheduler, vk::BufferUsageFlagBits::eVertexBuffer,
VERTEX_BUFFER_SIZE},
rasterizer{memory, render_window, instance, scheduler,
desc_manager, runtime, renderpass_cache} {
rasterizer{
memory, system.CustomTexManager(), render_window, instance, scheduler, desc_manager,
runtime, renderpass_cache} {
Report();
CompileShaders();
BuildLayouts();
@ -986,9 +987,7 @@ void RendererVulkan::SwapBuffers() {
m_current_frame++;
Core::System& system = Core::System::GetInstance();
system.perf_stats->EndSystemFrame();
render_window.PollEvents();
system.frame_limiter.DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs());

View File

@ -20,8 +20,9 @@
#include "video_core/renderer_vulkan/vk_swapchain.h"
namespace Core {
class System;
class TelemetrySession;
}
} // namespace Core
namespace Memory {
class MemorySystem;
@ -61,7 +62,7 @@ class RendererVulkan : public VideoCore::RendererBase {
static constexpr std::size_t PRESENT_PIPELINES = 3;
public:
explicit RendererVulkan(Memory::MemorySystem& memory, Frontend::EmuWindow& window,
explicit RendererVulkan(Core::System& system, Frontend::EmuWindow& window,
Frontend::EmuWindow* secondary_window);
~RendererVulkan() override;
@ -125,6 +126,7 @@ private:
void LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
private:
Core::System& system;
Memory::MemorySystem& memory;
Core::TelemetrySession& telemetry_session;

View File

@ -6,6 +6,7 @@
#include "common/assert.h"
#include "common/settings.h"
#include "core/frontend/emu_window.h"
#include "video_core/rasterizer_cache/custom_tex_manager.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_platform.h"
@ -108,6 +109,25 @@ vk::Format MakeFormat(VideoCore::PixelFormat format) {
}
}
vk::Format MakeCustomFormat(VideoCore::CustomPixelFormat format) {
switch (format) {
case VideoCore::CustomPixelFormat::RGBA8:
return vk::Format::eR8G8B8A8Unorm;
case VideoCore::CustomPixelFormat::BC1:
return vk::Format::eBc1RgbaUnormBlock;
case VideoCore::CustomPixelFormat::BC3:
return vk::Format::eBc3UnormBlock;
case VideoCore::CustomPixelFormat::BC5:
return vk::Format::eBc5UnormBlock;
case VideoCore::CustomPixelFormat::BC7:
return vk::Format::eBc7UnormBlock;
case VideoCore::CustomPixelFormat::ASTC:
return vk::Format::eAstc4x4UnormBlock;
}
LOG_ERROR(Render_Vulkan, "Unknown custom format {}", format);
return vk::Format::eR8G8B8A8Unorm;
}
vk::Format MakeAttributeFormat(Pica::PipelineRegs::VertexAttributeFormat format, u32 count,
bool scaled = true) {
static constexpr std::array attrib_formats_scaled = {
@ -350,6 +370,7 @@ Instance::Instance(Frontend::EmuWindow& window, u32 physical_device_index)
CreateDevice();
CreateFormatTable();
CreateCustomFormatTable();
CreateAttribTable();
CollectTelemetryParameters();
}
@ -380,6 +401,11 @@ const FormatTraits& Instance::GetTraits(VideoCore::PixelFormat pixel_format) con
return format_table[index];
}
const FormatTraits& Instance::GetTraits(VideoCore::CustomPixelFormat pixel_format) const {
const u32 index = static_cast<u32>(pixel_format);
return custom_format_table[index];
}
const FormatTraits& Instance::GetTraits(Pica::PipelineRegs::VertexAttributeFormat format,
u32 count) const {
if (count == 0) [[unlikely]] {
@ -419,7 +445,7 @@ FormatTraits Instance::DetermineTraits(VideoCore::PixelFormat pixel_format, vk::
pixel_format == VideoCore::PixelFormat::D24S8;
// Find the most inclusive usage flags for this format
vk::ImageUsageFlags best_usage;
vk::ImageUsageFlags best_usage{};
if (supports_blit || supports_transfer) {
best_usage |= vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst |
vk::ImageUsageFlagBits::eTransferSrc;
@ -459,7 +485,7 @@ void Instance::CreateFormatTable() {
};
for (const auto& pixel_format : pixel_formats) {
const auto format = MakeFormat(pixel_format);
const vk::Format format = MakeFormat(pixel_format);
FormatTraits traits = DetermineTraits(pixel_format, format);
const bool is_suitable =
@ -487,6 +513,41 @@ void Instance::CreateFormatTable() {
}
}
void Instance::CreateCustomFormatTable() {
// The traits are the same for RGBA8
custom_format_table[0] = format_table[static_cast<u32>(VideoCore::PixelFormat::RGBA8)];
constexpr std::array custom_formats = {
VideoCore::CustomPixelFormat::BC1, VideoCore::CustomPixelFormat::BC3,
VideoCore::CustomPixelFormat::BC5, VideoCore::CustomPixelFormat::BC7,
VideoCore::CustomPixelFormat::ASTC,
};
for (const auto& custom_format : custom_formats) {
const vk::Format format = MakeCustomFormat(custom_format);
const vk::FormatProperties format_properties = physical_device.getFormatProperties(format);
// Compressed formats don't support blit_dst in general so just check for transfer
const vk::FormatFeatureFlags transfer_usage = vk::FormatFeatureFlagBits::eSampledImage;
const bool supports_transfer =
(format_properties.optimalTilingFeatures & transfer_usage) == transfer_usage;
vk::ImageUsageFlags best_usage{};
if (supports_transfer) {
best_usage |= vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst |
vk::ImageUsageFlagBits::eTransferSrc;
}
const u32 index = static_cast<u32>(custom_format);
custom_format_table[index] = FormatTraits{
.transfer_support = supports_transfer,
.usage = best_usage,
.aspect = vk::ImageAspectFlagBits::eColor,
.native = format,
};
}
}
void Instance::CreateAttribTable() {
constexpr std::array attrib_formats = {
Pica::PipelineRegs::VertexAttributeFormat::BYTE,

View File

@ -14,6 +14,10 @@ namespace Frontend {
class EmuWindow;
}
namespace VideoCore {
enum class CustomPixelFormat : u32;
}
VK_DEFINE_HANDLE(VmaAllocator)
namespace Vulkan {
@ -39,6 +43,7 @@ public:
/// Returns the FormatTraits struct for the provided pixel format
const FormatTraits& GetTraits(VideoCore::PixelFormat pixel_format) const;
const FormatTraits& GetTraits(VideoCore::CustomPixelFormat pixel_format) const;
/// Returns the FormatTraits struct for the provided attribute format and count
const FormatTraits& GetTraits(Pica::PipelineRegs::VertexAttributeFormat format,
@ -271,6 +276,7 @@ private:
/// Creates the format compatibility table for the current device
void CreateFormatTable();
void CreateCustomFormatTable();
/// Creates the attribute format table for the current device
void CreateAttribTable();
@ -302,6 +308,7 @@ private:
vk::Queue graphics_queue;
std::vector<vk::PhysicalDevice> physical_devices;
std::array<FormatTraits, VideoCore::PIXEL_FORMAT_COUNT> format_table;
std::array<FormatTraits, 10> custom_format_table;
std::array<FormatTraits, 16> attrib_table;
std::vector<std::string> available_extensions;
u32 present_queue_family_index{0};

View File

@ -4,8 +4,8 @@
#pragma once
#include <atomic>
#include <deque>
#include <limits>
#include <mutex>
#include <thread>
#include <vector>
#include "common/common_types.h"

View File

@ -100,7 +100,7 @@ PipelineCache::Shader::Shader(const Instance& instance, vk::ShaderStageFlagBits
std::string code)
: Shader{instance} {
module = Compile(code, stage, instance.GetDevice(), ShaderOptimization::High);
MarkBuilt();
MarkDone();
}
PipelineCache::Shader::~Shader() {
@ -139,7 +139,7 @@ bool PipelineCache::GraphicsPipeline::Build(bool fail_on_compile_required) {
if (fail_on_compile_required) {
// Check if all shader modules are ready
for (auto& shader : stages) {
if (shader && !shader->IsBuilt()) {
if (shader && !shader->IsDone()) {
return false;
}
}
@ -309,7 +309,7 @@ bool PipelineCache::GraphicsPipeline::Build(bool fail_on_compile_required) {
continue;
}
shader->WaitBuilt();
shader->WaitDone();
shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{
.stage = MakeShaderStage(i),
.module = shader->Handle(),
@ -392,7 +392,7 @@ bool PipelineCache::GraphicsPipeline::Build(bool fail_on_compile_required) {
UNREACHABLE();
}
MarkBuilt();
MarkDone();
return true;
}
@ -489,7 +489,7 @@ bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) {
}
GraphicsPipeline* const pipeline{it->second.get()};
if (!wait_built && !pipeline->IsBuilt()) {
if (!wait_built && !pipeline->IsDone()) {
return false;
}
@ -497,8 +497,8 @@ bool PipelineCache::BindPipeline(const PipelineInfo& info, bool wait_built) {
ApplyDynamic(info, is_dirty);
if (current_pipeline != pipeline || is_dirty) {
if (!pipeline->IsBuilt()) {
scheduler.Record([pipeline](vk::CommandBuffer) { pipeline->WaitBuilt(); });
if (!pipeline->IsDone()) {
scheduler.Record([pipeline](vk::CommandBuffer) { pipeline->WaitDone(); });
}
scheduler.Record([pipeline](vk::CommandBuffer cmdbuf) {
@ -549,7 +549,7 @@ bool PipelineCache::UseProgrammableVertexShader(const Pica::Regs& regs,
workers.QueueWork([device, &shader] {
shader.module = Compile(shader.program, vk::ShaderStageFlagBits::eVertex, device,
ShaderOptimization::High);
shader.MarkBuilt();
shader.MarkDone();
});
}
@ -589,7 +589,7 @@ bool PipelineCache::UseFixedGeometryShader(const Pica::Regs& regs) {
const std::string code = GenerateFixedGeometryShader(gs_config);
shader.module =
Compile(code, vk::ShaderStageFlagBits::eGeometry, device, ShaderOptimization::High);
shader.MarkBuilt();
shader.MarkDone();
});
}
@ -620,13 +620,13 @@ void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
if (emit_spirv) {
const std::vector code = GenerateFragmentShaderSPV(config);
shader.module = CompileSPV(code, device);
shader.MarkBuilt();
shader.MarkDone();
} else {
workers.QueueWork([config, device, &shader]() {
const std::string code = GenerateFragmentShader(config);
shader.module = Compile(code, vk::ShaderStageFlagBits::eFragment, device,
ShaderOptimization::High);
shader.MarkBuilt();
ShaderOptimization::Debug);
shader.MarkDone();
});
}
}

View File

@ -10,7 +10,6 @@
#include "video_core/regs_framebuffer.h"
#include "video_core/regs_pipeline.h"
#include "video_core/regs_rasterizer.h"
#include "video_core/renderer_vulkan/pica_to_vk.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_rasterizer.h"
@ -69,12 +68,15 @@ struct DrawParams {
} // Anonymous namespace
RasterizerVulkan::RasterizerVulkan(Memory::MemorySystem& memory_, Frontend::EmuWindow& emu_window,
const Instance& instance, Scheduler& scheduler,
DescriptorManager& desc_manager, TextureRuntime& runtime,
RenderpassCache& renderpass_cache)
: RasterizerAccelerated{memory_}, instance{instance}, scheduler{scheduler}, runtime{runtime},
renderpass_cache{renderpass_cache}, desc_manager{desc_manager}, res_cache{memory, runtime},
RasterizerVulkan::RasterizerVulkan(Memory::MemorySystem& memory,
VideoCore::CustomTexManager& custom_tex_manager,
Frontend::EmuWindow& emu_window, const Instance& instance,
Scheduler& scheduler, DescriptorManager& desc_manager,
TextureRuntime& runtime, RenderpassCache& renderpass_cache)
: RasterizerAccelerated{memory}, instance{instance}, scheduler{scheduler}, runtime{runtime},
renderpass_cache{renderpass_cache}, desc_manager{desc_manager}, res_cache{memory,
custom_tex_manager,
runtime},
pipeline_cache{instance, scheduler, renderpass_cache, desc_manager},
null_surface{NULL_PARAMS, vk::Format::eR8G8B8A8Unorm, NULL_USAGE,
vk::ImageAspectFlagBits::eColor, runtime},

View File

@ -15,6 +15,10 @@ namespace Frontend {
class EmuWindow;
}
namespace VideoCore {
class CustomTexManager;
}
namespace Vulkan {
struct ScreenInfo;
@ -28,10 +32,11 @@ class RasterizerVulkan : public VideoCore::RasterizerAccelerated {
friend class RendererVulkan;
public:
explicit RasterizerVulkan(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window,
const Instance& instance, Scheduler& scheduler,
DescriptorManager& desc_manager, TextureRuntime& runtime,
RenderpassCache& renderpass_cache);
explicit RasterizerVulkan(Memory::MemorySystem& memory,
VideoCore::CustomTexManager& custom_tex_manager,
Frontend::EmuWindow& emu_window, const Instance& instance,
Scheduler& scheduler, DescriptorManager& desc_manager,
TextureRuntime& runtime, RenderpassCache& renderpass_cache);
~RasterizerVulkan() override;
void LoadDiskResources(const std::atomic_bool& stop_loading,

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "common/microprofile.h"
#include "video_core/rasterizer_cache/custom_tex_manager.h"
#include "video_core/rasterizer_cache/texture_codec.h"
#include "video_core/rasterizer_cache/utils.h"
#include "video_core/renderer_vulkan/pica_to_vk.h"
@ -18,9 +19,11 @@ MICROPROFILE_DEFINE(Vulkan_ImageAlloc, "Vulkan", "Texture Allocation", MP_RGB(19
namespace Vulkan {
namespace {
using VideoCore::GetFormatType;
using VideoCore::MipLevels;
using VideoCore::PixelFormatAsString;
using VideoCore::StagingData;
using VideoCore::TextureType;
struct RecordParams {
@ -33,7 +36,7 @@ struct RecordParams {
vk::Image dst_image;
};
[[nodiscard]] vk::Filter MakeFilter(VideoCore::PixelFormat pixel_format) {
vk::Filter MakeFilter(VideoCore::PixelFormat pixel_format) {
switch (pixel_format) {
case VideoCore::PixelFormat::D16:
case VideoCore::PixelFormat::D24:
@ -94,7 +97,7 @@ u32 UnpackDepthStencil(const StagingData& data, vk::Format dest) {
break;
}
default:
LOG_ERROR(Render_Vulkan, "Unimplemtend convertion for depth format {}",
LOG_ERROR(Render_Vulkan, "Unimplemented convertion for depth format {}",
vk::to_string(dest));
UNREACHABLE();
}
@ -103,8 +106,10 @@ u32 UnpackDepthStencil(const StagingData& data, vk::Format dest) {
return depth_offset;
}
constexpr u64 UPLOAD_BUFFER_SIZE = 32 * 1024 * 1024;
constexpr u64 DOWNLOAD_BUFFER_SIZE = 32 * 1024 * 1024;
constexpr u64 UPLOAD_BUFFER_SIZE = 64 * 1024 * 1024;
constexpr u64 DOWNLOAD_BUFFER_SIZE = 16 * 1024 * 1024;
} // Anonymous namespace
TextureRuntime::TextureRuntime(const Instance& instance, Scheduler& scheduler,
RenderpassCache& renderpass_cache, DescriptorManager& desc_manager)
@ -146,10 +151,9 @@ TextureRuntime::~TextureRuntime() {
StagingData TextureRuntime::FindStaging(u32 size, bool upload) {
auto& buffer = upload ? upload_buffer : download_buffer;
auto [data, offset, invalidate] = buffer.Map(size, 4);
auto [data, offset, invalidate] = buffer.Map(size, 16);
return StagingData{
.buffer = buffer.Handle(),
.size = size,
.mapped = std::span<u8>{data, size},
.buffer_offset = offset,
@ -163,24 +167,24 @@ void TextureRuntime::Finish() {
Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat format, VideoCore::TextureType type) {
const FormatTraits traits = instance.GetTraits(format);
return Allocate(width, height, levels, format, type, traits.native, traits.usage,
const bool is_mutable = format == VideoCore::PixelFormat::RGBA8;
return Allocate(width, height, levels, is_mutable, type, traits.native, traits.usage,
traits.aspect);
}
Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat pixel_format,
Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels, bool is_mutable,
VideoCore::TextureType type, vk::Format format,
vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect) {
MICROPROFILE_SCOPE(Vulkan_ImageAlloc);
ASSERT(pixel_format != VideoCore::PixelFormat::Invalid && levels >= 1);
ASSERT(format != vk::Format::eUndefined && levels >= 1);
const HostTextureTag key = {
.format = format,
.pixel_format = pixel_format,
.type = type,
.width = width,
.height = height,
.levels = levels,
.is_mutable = is_mutable,
};
if (auto it = texture_recycler.find(key); it != texture_recycler.end()) {
@ -189,18 +193,17 @@ Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
return alloc;
}
const bool create_storage_view = pixel_format == VideoCore::PixelFormat::RGBA8;
const u32 layers = type == VideoCore::TextureType::CubeMap ? 6 : 1;
vk::ImageCreateFlags flags;
if (type == VideoCore::TextureType::CubeMap) {
flags |= vk::ImageCreateFlagBits::eCubeCompatible;
}
if (create_storage_view) {
if (is_mutable) {
flags |= vk::ImageCreateFlagBits::eMutableFormat;
}
const bool need_format_list = create_storage_view && instance.IsImageFormatListSupported();
const bool need_format_list = is_mutable && instance.IsImageFormatListSupported();
const std::array format_list = {
vk::Format::eR8G8B8A8Unorm,
vk::Format::eR32Uint,
@ -290,6 +293,10 @@ Allocation TextureRuntime::Allocate(u32 width, u32 height, u32 levels,
.allocation = allocation,
.aspect = aspect,
.format = format,
.is_mutable = is_mutable,
.width = width,
.height = height,
.levels = levels,
};
}
@ -722,7 +729,34 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
return true;
}
void TextureRuntime::GenerateMipmaps(Surface& surface, u32 max_level) {}
void TextureRuntime::GenerateMipmaps(Surface& surface) {
if (surface.custom_format != VideoCore::CustomPixelFormat::RGBA8) {
LOG_ERROR(Render_Vulkan, "Generating mipmaps for compressed formats unsupported!");
return;
}
renderpass_cache.ExitRenderpass();
// Always use the allocation width on custom textures
u32 current_width = surface.alloc.width;
u32 current_height = surface.alloc.height;
const u32 levels = surface.levels;
for (u32 i = 1; i < levels; i++) {
const VideoCore::Rect2D src_rect{0, current_height, current_width, 0};
current_width = current_width > 1 ? current_width >> 1 : 1;
current_height = current_height > 1 ? current_height >> 1 : 1;
const VideoCore::Rect2D dst_rect{0, current_height, current_width, 0};
const VideoCore::TextureBlit blit = {
.src_level = i - 1,
.dst_level = i,
.src_rect = src_rect,
.dst_rect = dst_rect,
};
BlitTextures(surface, surface, blit);
}
}
const ReinterpreterList& TextureRuntime::GetPossibleReinterpretations(
VideoCore::PixelFormat dest_format) const {
@ -751,23 +785,25 @@ Surface::Surface(const VideoCore::SurfaceParams& params, vk::Format format,
: VideoCore::SurfaceBase{params}, runtime{runtime}, instance{runtime.GetInstance()},
scheduler{runtime.GetScheduler()} {
if (format != vk::Format::eUndefined) {
alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, pixel_format,
texture_type, format, usage, aspect);
alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), levels, false, texture_type,
format, usage, aspect);
}
}
Surface::~Surface() {
if (pixel_format != VideoCore::PixelFormat::Invalid) {
const HostTextureTag tag = {
.format = alloc.format,
.pixel_format = pixel_format,
.type = texture_type,
.width = GetScaledWidth(),
.height = GetScaledHeight(),
};
runtime.Recycle(tag, std::move(alloc));
if (pixel_format == VideoCore::PixelFormat::Invalid) {
return;
}
const HostTextureTag tag = {
.format = alloc.format,
.type = texture_type,
.width = alloc.width,
.height = alloc.height,
.levels = alloc.levels,
.is_mutable = alloc.is_mutable,
};
runtime.Recycle(tag, std::move(alloc));
}
void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging) {
@ -784,79 +820,78 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
.src_image = alloc.image,
};
scheduler.Record(
[format = alloc.format, params, staging, upload](vk::CommandBuffer cmdbuf) {
u32 num_copies = 1;
std::array<vk::BufferImageCopy, 2> buffer_image_copies;
scheduler.Record([buffer = runtime.upload_buffer.Handle(), format = alloc.format, params,
staging, upload](vk::CommandBuffer cmdbuf) {
u32 num_copies = 1;
std::array<vk::BufferImageCopy, 2> buffer_image_copies;
const VideoCore::Rect2D rect = upload.texture_rect;
buffer_image_copies[0] = vk::BufferImageCopy{
.bufferOffset = staging.buffer_offset + upload.buffer_offset,
.bufferRowLength = rect.GetWidth(),
.bufferImageHeight = rect.GetHeight(),
.imageSubresource{
.aspectMask = params.aspect,
.mipLevel = upload.texture_level,
.baseArrayLayer = 0,
.layerCount = 1,
},
.imageOffset = {static_cast<s32>(rect.left), static_cast<s32>(rect.bottom), 0},
.imageExtent = {rect.GetWidth(), rect.GetHeight(), 1},
};
const VideoCore::Rect2D rect = upload.texture_rect;
buffer_image_copies[0] = vk::BufferImageCopy{
.bufferOffset = staging.buffer_offset + upload.buffer_offset,
.bufferRowLength = rect.GetWidth(),
.bufferImageHeight = rect.GetHeight(),
.imageSubresource{
.aspectMask = params.aspect,
.mipLevel = upload.texture_level,
.baseArrayLayer = 0,
.layerCount = 1,
},
.imageOffset = {static_cast<s32>(rect.left), static_cast<s32>(rect.bottom), 0},
.imageExtent = {rect.GetWidth(), rect.GetHeight(), 1},
};
if (params.aspect & vk::ImageAspectFlagBits::eStencil) {
buffer_image_copies[0].imageSubresource.aspectMask =
vk::ImageAspectFlagBits::eDepth;
vk::BufferImageCopy& stencil_copy = buffer_image_copies[1];
stencil_copy = buffer_image_copies[0];
stencil_copy.bufferOffset += UnpackDepthStencil(staging, format);
stencil_copy.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eStencil;
num_copies++;
}
if (params.aspect & vk::ImageAspectFlagBits::eStencil) {
buffer_image_copies[0].imageSubresource.aspectMask =
vk::ImageAspectFlagBits::eDepth;
vk::BufferImageCopy& stencil_copy = buffer_image_copies[1];
stencil_copy = buffer_image_copies[0];
stencil_copy.bufferOffset += UnpackDepthStencil(staging, format);
stencil_copy.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eStencil;
num_copies++;
}
const vk::ImageMemoryBarrier read_barrier = {
.srcAccessMask = params.src_access,
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eTransferDstOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = params.src_image,
.subresourceRange{
.aspectMask = params.aspect,
.baseMipLevel = upload.texture_level,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
const vk::ImageMemoryBarrier write_barrier = {
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = params.src_access,
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = params.src_image,
.subresourceRange{
.aspectMask = params.aspect,
.baseMipLevel = upload.texture_level,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
const vk::ImageMemoryBarrier read_barrier = {
.srcAccessMask = params.src_access,
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eTransferDstOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = params.src_image,
.subresourceRange{
.aspectMask = params.aspect,
.baseMipLevel = upload.texture_level,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
const vk::ImageMemoryBarrier write_barrier = {
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = params.src_access,
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = params.src_image,
.subresourceRange{
.aspectMask = params.aspect,
.baseMipLevel = upload.texture_level,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
cmdbuf.pipelineBarrier(params.pipeline_flags, vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlagBits::eByRegion, {}, {}, read_barrier);
cmdbuf.pipelineBarrier(params.pipeline_flags, vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlagBits::eByRegion, {}, {}, read_barrier);
cmdbuf.copyBufferToImage(staging.buffer, params.src_image,
vk::ImageLayout::eTransferDstOptimal, num_copies,
buffer_image_copies.data());
cmdbuf.copyBufferToImage(buffer, params.src_image, vk::ImageLayout::eTransferDstOptimal,
num_copies, buffer_image_copies.data());
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, params.pipeline_flags,
vk::DependencyFlagBits::eByRegion, {}, {}, write_barrier);
});
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, params.pipeline_flags,
vk::DependencyFlagBits::eByRegion, {}, {}, write_barrier);
});
runtime.upload_buffer.Commit(staging.size);
}
@ -883,7 +918,8 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
.src_image = alloc.image,
};
scheduler.Record([params, staging, download](vk::CommandBuffer cmdbuf) {
scheduler.Record([buffer = runtime.download_buffer.Handle(), params, staging,
download](vk::CommandBuffer cmdbuf) {
const VideoCore::Rect2D rect = download.texture_rect;
const vk::BufferImageCopy buffer_image_copy = {
.bufferOffset = staging.buffer_offset + download.buffer_offset,
@ -939,8 +975,8 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
cmdbuf.pipelineBarrier(params.pipeline_flags, vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlagBits::eByRegion, {}, {}, read_barrier);
cmdbuf.copyImageToBuffer(params.src_image, vk::ImageLayout::eTransferSrcOptimal,
staging.buffer, buffer_image_copy);
cmdbuf.copyImageToBuffer(params.src_image, vk::ImageLayout::eTransferSrcOptimal, buffer,
buffer_image_copy);
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, params.pipeline_flags,
vk::DependencyFlagBits::eByRegion, memory_write_barrier, {},
@ -950,6 +986,39 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
}
}
bool Surface::Swap(u32 width, u32 height, VideoCore::CustomPixelFormat format) {
const FormatTraits& traits = instance.GetTraits(format);
if (!traits.transfer_support) {
return false;
}
const vk::Format custom_vk_format = traits.native;
if (alloc.Matches(width, height, levels, custom_vk_format)) {
return true;
}
const HostTextureTag tag = {
.format = alloc.format,
.type = texture_type,
.width = GetScaledWidth(),
.height = GetScaledHeight(),
.levels = levels,
.is_mutable = alloc.is_mutable,
};
runtime.Recycle(tag, std::move(alloc));
is_custom = true;
custom_format = format;
alloc = runtime.Allocate(width, height, levels, false, texture_type, custom_vk_format,
traits.usage, traits.aspect);
LOG_DEBUG(Render_Vulkan, "Swapped {}x{} {} surface at address {:#x} to {}x{} {}",
GetScaledWidth(), GetScaledHeight(), VideoCore::PixelFormatAsString(pixel_format),
addr, width, height, VideoCore::CustomPixelFormatAsString(format));
return true;
}
u32 Surface::GetInternalBytesPerPixel() const {
// Request 5 bytes for D24S8 as well because we can use the
// extra space when deinterleaving the data during upload
@ -1041,7 +1110,7 @@ vk::ImageView Surface::StorageView() noexcept {
ASSERT_MSG(pixel_format == VideoCore::PixelFormat::RGBA8,
"Attempted to retrieve storage view from unsupported surface with format {}",
PixelFormatAsString(pixel_format));
VideoCore::PixelFormatAsString(pixel_format));
const vk::ImageViewCreateInfo storage_view_info = {
.image = alloc.image,

View File

@ -17,14 +17,11 @@
VK_DEFINE_HANDLE(VmaAllocation)
namespace Vulkan {
namespace VideoCore {
enum class CustomPixelFormat : u32;
}
struct StagingData {
vk::Buffer buffer;
u32 size = 0;
std::span<u8> mapped{};
u64 buffer_offset = 0;
};
namespace Vulkan {
struct Allocation {
vk::Image image;
@ -35,15 +32,24 @@ struct Allocation {
VmaAllocation allocation;
vk::ImageAspectFlags aspect;
vk::Format format;
bool is_mutable;
u32 width;
u32 height;
u32 levels;
bool Matches(u32 width_, u32 height_, u32 levels_, vk::Format format_) const noexcept {
return std::tie(width, height, levels, format) ==
std::tie(width_, height_, levels_, format_);
}
};
struct HostTextureTag {
vk::Format format = vk::Format::eUndefined;
VideoCore::PixelFormat pixel_format = VideoCore::PixelFormat::Invalid;
VideoCore::TextureType type = VideoCore::TextureType::Texture2D;
u32 width = 1;
u32 height = 1;
u32 levels = 1;
u32 is_mutable = 0; // This is a u32 to ensure alignment for hashing
auto operator<=>(const HostTextureTag&) const noexcept = default;
@ -90,15 +96,14 @@ public:
void Recycle(const HostTextureTag tag, Allocation&& alloc);
/// Maps an internal staging buffer of the provided size of pixel uploads/downloads
[[nodiscard]] StagingData FindStaging(u32 size, bool upload);
[[nodiscard]] VideoCore::StagingData FindStaging(u32 size, bool upload);
/// Allocates a vulkan image possibly resusing an existing one
[[nodiscard]] Allocation Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat format, VideoCore::TextureType type);
/// Allocates a vulkan image
[[nodiscard]] Allocation Allocate(u32 width, u32 height, u32 levels,
VideoCore::PixelFormat pixel_format,
[[nodiscard]] Allocation Allocate(u32 width, u32 height, u32 levels, bool is_mutable,
VideoCore::TextureType type, vk::Format format,
vk::ImageUsageFlags usage, vk::ImageAspectFlags aspect);
@ -112,7 +117,7 @@ public:
bool BlitTextures(Surface& surface, Surface& dest, const VideoCore::TextureBlit& blit);
/// Generates mipmaps for all the available levels of the texture
void GenerateMipmaps(Surface& surface, u32 max_level);
void GenerateMipmaps(Surface& surface);
/// Returns all source formats that support reinterpretation to the dest format
[[nodiscard]] const ReinterpreterList& GetPossibleReinterpretations(
@ -176,10 +181,14 @@ public:
}
/// Uploads pixel data in staging to a rectangle region of the surface texture
void Upload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging);
void Upload(const VideoCore::BufferTextureCopy& upload, const VideoCore::StagingData& staging);
/// Downloads pixel data to staging from a rectangle region of the surface texture
void Download(const VideoCore::BufferTextureCopy& download, const StagingData& staging);
void Download(const VideoCore::BufferTextureCopy& download,
const VideoCore::StagingData& staging);
/// Swaps the internal allocation to match the provided dimentions and format
bool Swap(u32 width, u32 height, VideoCore::CustomPixelFormat format);
/// Returns the bpp of the internal surface format
u32 GetInternalBytesPerPixel() const;
@ -201,14 +210,16 @@ public:
private:
/// Uploads pixel data to scaled texture
void ScaledUpload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging);
void ScaledUpload(const VideoCore::BufferTextureCopy& upload,
const VideoCore::StagingData& staging);
/// Downloads scaled image by downscaling the requested rectangle
void ScaledDownload(const VideoCore::BufferTextureCopy& download, const StagingData& stagings);
void ScaledDownload(const VideoCore::BufferTextureCopy& download,
const VideoCore::StagingData& stagings);
/// Downloads scaled depth stencil data
void DepthStencilDownload(const VideoCore::BufferTextureCopy& download,
const StagingData& staging);
const VideoCore::StagingData& staging);
private:
TextureRuntime& runtime;

View File

@ -6,6 +6,7 @@
#include "common/archives.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "core/core.h"
#include "video_core/pica.h"
#include "video_core/pica_state.h"
#include "video_core/renderer_base.h"
@ -31,8 +32,8 @@ Memory::MemorySystem* g_memory;
/// Initialize the video core
ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window,
Memory::MemorySystem& memory) {
g_memory = &memory;
Core::System& system) {
g_memory = &system.Memory();
Pica::Init();
const Settings::GraphicsAPI graphics_api = Settings::values.graphics_api.GetValue();
@ -40,10 +41,10 @@ ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondar
case Settings::GraphicsAPI::OpenGL:
case Settings::GraphicsAPI::OpenGLES:
OpenGL::GLES = graphics_api == Settings::GraphicsAPI::OpenGLES;
g_renderer = std::make_unique<OpenGL::RendererOpenGL>(memory, emu_window, secondary_window);
g_renderer = std::make_unique<OpenGL::RendererOpenGL>(system, emu_window, secondary_window);
break;
case Settings::GraphicsAPI::Vulkan:
g_renderer = std::make_unique<Vulkan::RendererVulkan>(memory, emu_window, secondary_window);
g_renderer = std::make_unique<Vulkan::RendererVulkan>(system, emu_window, secondary_window);
break;
default:
LOG_CRITICAL(Render, "Invalid graphics API enum value {}", graphics_api);

View File

@ -10,6 +10,10 @@
#include <memory>
#include "core/frontend/emu_window.h"
namespace Core {
class System;
}
namespace Frontend {
class EmuWindow;
}
@ -44,7 +48,7 @@ enum class ResultStatus {
/// Initialize the video core
ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window,
Memory::MemorySystem& memory);
Core::System& system);
/// Shutdown the video core
void Shutdown();