video_core: Rewrite custom textures
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
305
externals/glad/include/glad/glad.h
vendored
305
externals/glad/include/glad/glad.h
vendored
@ -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
|
||||
}
|
||||
|
376
externals/glad/src/glad.c
vendored
376
externals/glad/src/glad.c
vendored
@ -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
1
externals/libspng
vendored
Submodule externals/libspng deleted from 75c39ce094
25
externals/libspng/CMakeLists.txt
vendored
Normal file
25
externals/libspng/CMakeLists.txt
vendored
Normal 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
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
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
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
537
externals/libspng/spng.h
vendored
Normal 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
1
externals/lodepng/lodepng
vendored
Submodule
Submodule externals/lodepng/lodepng added at 18964554bc
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
1465
src/common/dds-ktx.h
Normal file
File diff suppressed because it is too large
Load Diff
111
src/common/dds.h
111
src/common/dds.h
@ -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
|
@ -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,23 +116,21 @@ 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);
|
||||
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);
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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
|
@ -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
|
||||
|
251
src/video_core/rasterizer_cache/custom_tex_manager.cpp
Normal file
251
src/video_core/rasterizer_cache/custom_tex_manager.cpp
Normal 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
|
79
src/video_core/rasterizer_cache/custom_tex_manager.h
Normal file
79
src/video_core/rasterizer_cache/custom_tex_manager.h
Normal 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
|
@ -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
|
@ -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
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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() {
|
||||
|
@ -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{};
|
||||
|
@ -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},
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
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()) {
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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};
|
||||
|
@ -4,8 +4,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
if (pixel_format == VideoCore::PixelFormat::Invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const HostTextureTag tag = {
|
||||
.format = alloc.format,
|
||||
.pixel_format = pixel_format,
|
||||
.type = texture_type,
|
||||
.width = GetScaledWidth(),
|
||||
.height = GetScaledHeight(),
|
||||
.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,8 +820,8 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
|
||||
.src_image = alloc.image,
|
||||
};
|
||||
|
||||
scheduler.Record(
|
||||
[format = alloc.format, params, staging, upload](vk::CommandBuffer cmdbuf) {
|
||||
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;
|
||||
|
||||
@ -850,9 +886,8 @@ void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingDa
|
||||
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);
|
||||
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user