mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Restructured some Shader code. Added runtime temporary caching and sharing of shader stages. Resolves issue #1235.
--HG-- branch : minor
This commit is contained in:
@@ -529,6 +529,8 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT
|
||||
src/modules/graphics/Quad.h
|
||||
src/modules/graphics/Shader.cpp
|
||||
src/modules/graphics/Shader.h
|
||||
src/modules/graphics/ShaderStage.cpp
|
||||
src/modules/graphics/ShaderStage.h
|
||||
src/modules/graphics/SpriteBatch.cpp
|
||||
src/modules/graphics/SpriteBatch.h
|
||||
src/modules/graphics/StreamBuffer.cpp
|
||||
@@ -588,6 +590,8 @@ set(LOVE_SRC_MODULE_GRAPHICS_OPENGL
|
||||
src/modules/graphics/opengl/ParticleSystem.h
|
||||
src/modules/graphics/opengl/Shader.cpp
|
||||
src/modules/graphics/opengl/Shader.h
|
||||
src/modules/graphics/opengl/ShaderStage.cpp
|
||||
src/modules/graphics/opengl/ShaderStage.h
|
||||
src/modules/graphics/opengl/SpriteBatch.cpp
|
||||
src/modules/graphics/opengl/SpriteBatch.h
|
||||
src/modules/graphics/opengl/StreamBuffer.cpp
|
||||
|
||||
@@ -821,9 +821,6 @@
|
||||
FA27B39D1B498151008A9DCE /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B38A1B498151008A9DCE /* Video.cpp */; };
|
||||
FA27B39E1B498151008A9DCE /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B38A1B498151008A9DCE /* Video.cpp */; };
|
||||
FA27B39F1B498151008A9DCE /* Video.h in Headers */ = {isa = PBXBuildFile; fileRef = FA27B38B1B498151008A9DCE /* Video.h */; };
|
||||
FA27B3A01B498151008A9DCE /* VideoStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B38C1B498151008A9DCE /* VideoStream.cpp */; };
|
||||
FA27B3A11B498151008A9DCE /* VideoStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B38C1B498151008A9DCE /* VideoStream.cpp */; };
|
||||
FA27B3A21B498151008A9DCE /* VideoStream.h in Headers */ = {isa = PBXBuildFile; fileRef = FA27B38D1B498151008A9DCE /* VideoStream.h */; };
|
||||
FA27B3A91B498151008A9DCE /* Video.h in Headers */ = {isa = PBXBuildFile; fileRef = FA27B3931B498151008A9DCE /* Video.h */; };
|
||||
FA27B3AA1B498151008A9DCE /* VideoStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B3941B498151008A9DCE /* VideoStream.cpp */; };
|
||||
FA27B3AB1B498151008A9DCE /* VideoStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA27B3941B498151008A9DCE /* VideoStream.cpp */; };
|
||||
@@ -843,6 +840,12 @@
|
||||
FA2AF6741DAD64970032B62C /* vertex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA2AF6731DAD64970032B62C /* vertex.cpp */; };
|
||||
FA2AF6751DAD64970032B62C /* vertex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA2AF6731DAD64970032B62C /* vertex.cpp */; };
|
||||
FA317EBA18F28B6D00B0BCD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FA317EB918F28B6D00B0BCD7 /* libz.dylib */; };
|
||||
FA3C5E421F8C368C0003C579 /* ShaderStage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA3C5E401F8C368C0003C579 /* ShaderStage.cpp */; };
|
||||
FA3C5E431F8C368C0003C579 /* ShaderStage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA3C5E401F8C368C0003C579 /* ShaderStage.cpp */; };
|
||||
FA3C5E441F8C368C0003C579 /* ShaderStage.h in Headers */ = {isa = PBXBuildFile; fileRef = FA3C5E411F8C368C0003C579 /* ShaderStage.h */; };
|
||||
FA3C5E471F8D80CA0003C579 /* ShaderStage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA3C5E451F8D80CA0003C579 /* ShaderStage.cpp */; };
|
||||
FA3C5E481F8D80CA0003C579 /* ShaderStage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA3C5E451F8D80CA0003C579 /* ShaderStage.cpp */; };
|
||||
FA3C5E491F8D80CA0003C579 /* ShaderStage.h in Headers */ = {isa = PBXBuildFile; fileRef = FA3C5E461F8D80CA0003C579 /* ShaderStage.h */; };
|
||||
FA41A3C81C0A1F950084430C /* ASTCHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA41A3C61C0A1F950084430C /* ASTCHandler.cpp */; };
|
||||
FA41A3C91C0A1F950084430C /* ASTCHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA41A3C61C0A1F950084430C /* ASTCHandler.cpp */; };
|
||||
FA41A3CA1C0A1F950084430C /* ASTCHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA41A3C71C0A1F950084430C /* ASTCHandler.h */; };
|
||||
@@ -963,6 +966,10 @@
|
||||
FAA3A9AE1B7D465A00CED060 /* android.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAA3A9AC1B7D465A00CED060 /* android.cpp */; };
|
||||
FAA3A9AF1B7D465A00CED060 /* android.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAA3A9AC1B7D465A00CED060 /* android.cpp */; };
|
||||
FAA3A9B01B7D465A00CED060 /* android.h in Headers */ = {isa = PBXBuildFile; fileRef = FAA3A9AD1B7D465A00CED060 /* android.h */; };
|
||||
FAA54ACA1F91660400A8FA7B /* OggDemuxer.h in Headers */ = {isa = PBXBuildFile; fileRef = FAA54AC61F91660400A8FA7B /* OggDemuxer.h */; };
|
||||
FAA54ACB1F91660400A8FA7B /* TheoraVideoStream.h in Headers */ = {isa = PBXBuildFile; fileRef = FAA54AC71F91660400A8FA7B /* TheoraVideoStream.h */; };
|
||||
FAA54ACC1F91660400A8FA7B /* TheoraVideoStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAA54AC81F91660400A8FA7B /* TheoraVideoStream.cpp */; };
|
||||
FAA54ACD1F91660400A8FA7B /* OggDemuxer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAA54AC91F91660400A8FA7B /* OggDemuxer.cpp */; };
|
||||
FAA627CE18E7E1560080752D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAA627CD18E7E1560080752D /* CoreServices.framework */; };
|
||||
FAAA3FD81F64B3AD00F89E99 /* lprefix.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAA3FD31F64B3AD00F89E99 /* lprefix.h */; };
|
||||
FAAA3FD91F64B3AD00F89E99 /* lstrlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FAAA3FD41F64B3AD00F89E99 /* lstrlib.c */; };
|
||||
@@ -1737,8 +1744,6 @@
|
||||
FA1E88821DF363DB00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
|
||||
FA27B38A1B498151008A9DCE /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Video.cpp; sourceTree = "<group>"; };
|
||||
FA27B38B1B498151008A9DCE /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = "<group>"; };
|
||||
FA27B38C1B498151008A9DCE /* VideoStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoStream.cpp; sourceTree = "<group>"; };
|
||||
FA27B38D1B498151008A9DCE /* VideoStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoStream.h; sourceTree = "<group>"; };
|
||||
FA27B3931B498151008A9DCE /* Video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = "<group>"; };
|
||||
FA27B3941B498151008A9DCE /* VideoStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoStream.cpp; sourceTree = "<group>"; };
|
||||
FA27B3951B498151008A9DCE /* VideoStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoStream.h; sourceTree = "<group>"; };
|
||||
@@ -1757,6 +1762,10 @@
|
||||
FA2AF6731DAD64970032B62C /* vertex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vertex.cpp; sourceTree = "<group>"; };
|
||||
FA2E9BFE1C19E00C0004A1EE /* wrap_RandomGenerator.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wrap_RandomGenerator.lua; sourceTree = "<group>"; };
|
||||
FA317EB918F28B6D00B0BCD7 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
|
||||
FA3C5E401F8C368C0003C579 /* ShaderStage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ShaderStage.cpp; sourceTree = "<group>"; };
|
||||
FA3C5E411F8C368C0003C579 /* ShaderStage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShaderStage.h; sourceTree = "<group>"; };
|
||||
FA3C5E451F8D80CA0003C579 /* ShaderStage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ShaderStage.cpp; sourceTree = "<group>"; };
|
||||
FA3C5E461F8D80CA0003C579 /* ShaderStage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShaderStage.h; sourceTree = "<group>"; };
|
||||
FA41A3C61C0A1F950084430C /* ASTCHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ASTCHandler.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
FA41A3C71C0A1F950084430C /* ASTCHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ASTCHandler.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
FA4B66C81ABBCF1900558F15 /* Timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Timer.cpp; sourceTree = "<group>"; };
|
||||
@@ -1835,6 +1844,10 @@
|
||||
FA9D8DDF1DEF843D002CD881 /* Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Image.cpp; sourceTree = "<group>"; };
|
||||
FAA3A9AC1B7D465A00CED060 /* android.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = android.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
FAA3A9AD1B7D465A00CED060 /* android.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = android.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
FAA54AC61F91660400A8FA7B /* OggDemuxer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OggDemuxer.h; sourceTree = "<group>"; };
|
||||
FAA54AC71F91660400A8FA7B /* TheoraVideoStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TheoraVideoStream.h; sourceTree = "<group>"; };
|
||||
FAA54AC81F91660400A8FA7B /* TheoraVideoStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TheoraVideoStream.cpp; sourceTree = "<group>"; };
|
||||
FAA54AC91F91660400A8FA7B /* OggDemuxer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OggDemuxer.cpp; sourceTree = "<group>"; };
|
||||
FAA627CD18E7E1560080752D /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
||||
FAAA3FD31F64B3AD00F89E99 /* lprefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lprefix.h; sourceTree = "<group>"; };
|
||||
FAAA3FD41F64B3AD00F89E99 /* lstrlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lstrlib.c; sourceTree = "<group>"; };
|
||||
@@ -2705,6 +2718,8 @@
|
||||
FA0B7BBD1A95902C000E1D17 /* Quad.h */,
|
||||
FA1BA0AF1E16FD0800AA2803 /* Shader.cpp */,
|
||||
FA1BA0B01E16FD0800AA2803 /* Shader.h */,
|
||||
FA3C5E401F8C368C0003C579 /* ShaderStage.cpp */,
|
||||
FA3C5E411F8C368C0003C579 /* ShaderStage.h */,
|
||||
FADF542D1E3DABF600012CC0 /* SpriteBatch.cpp */,
|
||||
FADF542E1E3DABF600012CC0 /* SpriteBatch.h */,
|
||||
FA29C0041E12355B00268CD8 /* StreamBuffer.cpp */,
|
||||
@@ -2770,6 +2785,8 @@
|
||||
FA0B7B9A1A95902C000E1D17 /* ParticleSystem.h */,
|
||||
FA0B7B9D1A95902C000E1D17 /* Shader.cpp */,
|
||||
FA0B7B9E1A95902C000E1D17 /* Shader.h */,
|
||||
FA3C5E451F8D80CA0003C579 /* ShaderStage.cpp */,
|
||||
FA3C5E461F8D80CA0003C579 /* ShaderStage.h */,
|
||||
FA0B7B9F1A95902C000E1D17 /* SpriteBatch.cpp */,
|
||||
FA0B7BA01A95902C000E1D17 /* SpriteBatch.h */,
|
||||
FA7634481E28722A0066EF9E /* StreamBuffer.cpp */,
|
||||
@@ -3244,10 +3261,12 @@
|
||||
FA27B3891B498151008A9DCE /* theora */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FAA54AC91F91660400A8FA7B /* OggDemuxer.cpp */,
|
||||
FAA54AC61F91660400A8FA7B /* OggDemuxer.h */,
|
||||
FAA54AC81F91660400A8FA7B /* TheoraVideoStream.cpp */,
|
||||
FAA54AC71F91660400A8FA7B /* TheoraVideoStream.h */,
|
||||
FA27B38A1B498151008A9DCE /* Video.cpp */,
|
||||
FA27B38B1B498151008A9DCE /* Video.h */,
|
||||
FA27B38C1B498151008A9DCE /* VideoStream.cpp */,
|
||||
FA27B38D1B498151008A9DCE /* VideoStream.h */,
|
||||
);
|
||||
path = theora;
|
||||
sourceTree = "<group>";
|
||||
@@ -3622,6 +3641,7 @@
|
||||
FADF54361E3DAE6E00012CC0 /* wrap_SpriteBatch.h in Headers */,
|
||||
FA0B7DB01A95902C000E1D17 /* wrap_CompressedImageData.h in Headers */,
|
||||
FA0B7AC11A958EA3000E1D17 /* callbacks.h in Headers */,
|
||||
FA3C5E491F8D80CA0003C579 /* ShaderStage.h in Headers */,
|
||||
FA0B7D8F1A95902C000E1D17 /* ddsHandler.h in Headers */,
|
||||
FAB2D5AC1AABDD8A008224A4 /* TrueTypeRasterizer.h in Headers */,
|
||||
FAF140C41E20934C00F898D2 /* ShaderLang.h in Headers */,
|
||||
@@ -3658,6 +3678,7 @@
|
||||
FA0B7CE41A95902C000E1D17 /* wrap_Audio.h in Headers */,
|
||||
FA0B7A7F1A958EA3000E1D17 /* b2ContactSolver.h in Headers */,
|
||||
FADF540F1E3D7CDD00012CC0 /* wrap_Video.h in Headers */,
|
||||
FAA54ACA1F91660400A8FA7B /* OggDemuxer.h in Headers */,
|
||||
FA0B79491A958E3B000E1D17 /* version.h in Headers */,
|
||||
FAF140581E20934C00F898D2 /* BaseTypes.h in Headers */,
|
||||
FA0B7B2B1A958EA3000E1D17 /* stb_image.h in Headers */,
|
||||
@@ -3783,9 +3804,9 @@
|
||||
FA0B7E961A95902C000E1D17 /* Mpg123Decoder.h in Headers */,
|
||||
FADF54091E3D78F700012CC0 /* Video.h in Headers */,
|
||||
FA0B7D501A95902C000E1D17 /* SpriteBatch.h in Headers */,
|
||||
FAA54ACB1F91660400A8FA7B /* TheoraVideoStream.h in Headers */,
|
||||
FA0B7DD51A95902C000E1D17 /* BezierCurve.h in Headers */,
|
||||
FA0B79271A958E3B000E1D17 /* int.h in Headers */,
|
||||
FA27B3A21B498151008A9DCE /* VideoStream.h in Headers */,
|
||||
FA0B7E531A95902C000E1D17 /* wrap_FrictionJoint.h in Headers */,
|
||||
FA0B7EB71A95902C000E1D17 /* wrap_System.h in Headers */,
|
||||
FA27B3A91B498151008A9DCE /* Video.h in Headers */,
|
||||
@@ -3878,6 +3899,7 @@
|
||||
217DFBF81D9F6D490055D849 /* pierror.h in Headers */,
|
||||
217DFC021D9F6D490055D849 /* tcp.h in Headers */,
|
||||
FA0B7A3D1A958EA3000E1D17 /* b2TimeOfImpact.h in Headers */,
|
||||
FA3C5E441F8C368C0003C579 /* ShaderStage.h in Headers */,
|
||||
FA0B79261A958E3B000E1D17 /* Exception.h in Headers */,
|
||||
FA0B7D4D1A95902C000E1D17 /* Shader.h in Headers */,
|
||||
FA0B793D1A958E3B000E1D17 /* runtime.h in Headers */,
|
||||
@@ -4093,6 +4115,7 @@
|
||||
FA4F2C031DE936C200CA37D7 /* auxiliar.c in Sources */,
|
||||
FA0B7E731A95902C000E1D17 /* wrap_Shape.cpp in Sources */,
|
||||
FA0B7CFE1A95902C000E1D17 /* File.cpp in Sources */,
|
||||
FA3C5E481F8D80CA0003C579 /* ShaderStage.cpp in Sources */,
|
||||
FA27B39E1B498151008A9DCE /* Video.cpp in Sources */,
|
||||
FA0B7A751A958EA3000E1D17 /* b2ChainAndPolygonContact.cpp in Sources */,
|
||||
FA0B7E6A1A95902C000E1D17 /* wrap_PulleyJoint.cpp in Sources */,
|
||||
@@ -4128,6 +4151,7 @@
|
||||
FAF140AA1E20934C00F898D2 /* SymbolTable.cpp in Sources */,
|
||||
FA0B7A8D1A958EA3000E1D17 /* b2DistanceJoint.cpp in Sources */,
|
||||
FA0B7A841A958EA3000E1D17 /* b2EdgeAndPolygonContact.cpp in Sources */,
|
||||
FA3C5E431F8C368C0003C579 /* ShaderStage.cpp in Sources */,
|
||||
FA0B7E191A95902C000E1D17 /* MotorJoint.cpp in Sources */,
|
||||
FAF1406F1E20934C00F898D2 /* Initialize.cpp in Sources */,
|
||||
FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */,
|
||||
@@ -4252,7 +4276,6 @@
|
||||
FA0B791C1A958E3B000E1D17 /* b64.cpp in Sources */,
|
||||
FA1E88851DF363E100E808AA /* Filter.cpp in Sources */,
|
||||
FA0B7DA01A95902C000E1D17 /* KTXHandler.cpp in Sources */,
|
||||
FA27B3A11B498151008A9DCE /* VideoStream.cpp in Sources */,
|
||||
FA0B7A5C1A958EA3000E1D17 /* b2Timer.cpp in Sources */,
|
||||
FA0B7CEC1A95902C000E1D17 /* Event.cpp in Sources */,
|
||||
FA27B3AB1B498151008A9DCE /* VideoStream.cpp in Sources */,
|
||||
@@ -4428,6 +4451,7 @@
|
||||
FA0B7D2B1A95902C000E1D17 /* wrap_Rasterizer.cpp in Sources */,
|
||||
FA0B7E8E1A95902C000E1D17 /* GmeDecoder.cpp in Sources */,
|
||||
FA0B7CD61A95902C000E1D17 /* Audio.cpp in Sources */,
|
||||
FA3C5E421F8C368C0003C579 /* ShaderStage.cpp in Sources */,
|
||||
FA0B7A9E1A958EA3000E1D17 /* b2PrismaticJoint.cpp in Sources */,
|
||||
FA0B7EAF1A95902C000E1D17 /* System.cpp in Sources */,
|
||||
FA0B7EE21A95902D000E1D17 /* Window.cpp in Sources */,
|
||||
@@ -4617,7 +4641,6 @@
|
||||
FA0B7D9F1A95902C000E1D17 /* KTXHandler.cpp in Sources */,
|
||||
FA1E88831DF363DB00E808AA /* Filter.cpp in Sources */,
|
||||
FA0B7A2C1A958EA3000E1D17 /* b2CollideCircle.cpp in Sources */,
|
||||
FA27B3A01B498151008A9DCE /* VideoStream.cpp in Sources */,
|
||||
FA0B7CEB1A95902C000E1D17 /* Event.cpp in Sources */,
|
||||
FA1557C31CE90BD200AFF582 /* EXRHandler.cpp in Sources */,
|
||||
FA27B3AA1B498151008A9DCE /* VideoStream.cpp in Sources */,
|
||||
@@ -4700,6 +4723,7 @@
|
||||
FA0B7DCD1A95902C000E1D17 /* wrap_Keyboard.cpp in Sources */,
|
||||
FA0B7EE51A95902D000E1D17 /* Window.cpp in Sources */,
|
||||
FA6A2B6A1F5F7F560074C308 /* DataView.cpp in Sources */,
|
||||
FA3C5E471F8D80CA0003C579 /* ShaderStage.cpp in Sources */,
|
||||
FA0B7E391A95902C000E1D17 /* World.cpp in Sources */,
|
||||
FA0B7ABD1A958EA3000E1D17 /* compress.c in Sources */,
|
||||
FA0B7ACB1A958EA3000E1D17 /* list.c in Sources */,
|
||||
@@ -4764,6 +4788,7 @@
|
||||
FAF140881E20934C00F898D2 /* PoolAlloc.cpp in Sources */,
|
||||
FA0B7AAD1A958EA3000E1D17 /* b2WheelJoint.cpp in Sources */,
|
||||
FA0B7DEE1A95902C000E1D17 /* Mouse.cpp in Sources */,
|
||||
FAA54ACC1F91660400A8FA7B /* TheoraVideoStream.cpp in Sources */,
|
||||
FA1E887E1DF363CD00E808AA /* Filter.cpp in Sources */,
|
||||
FA0B7D281A95902C000E1D17 /* wrap_GlyphData.cpp in Sources */,
|
||||
FA0B7DE21A95902C000E1D17 /* wrap_RandomGenerator.cpp in Sources */,
|
||||
@@ -4773,6 +4798,7 @@
|
||||
FA0B7D0C1A95902C000E1D17 /* wrap_Filesystem.cpp in Sources */,
|
||||
FA0B7AD91A958EA3000E1D17 /* glad.cpp in Sources */,
|
||||
217DFBF61D9F6D490055D849 /* options.c in Sources */,
|
||||
FAA54ACD1F91660400A8FA7B /* OggDemuxer.cpp in Sources */,
|
||||
217DFBD91D9F6D490055D849 /* auxiliar.c in Sources */,
|
||||
217DFBDB1D9F6D490055D849 /* buffer.c in Sources */,
|
||||
FA0B7DB41A95902C000E1D17 /* wrap_ImageData.cpp in Sources */,
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "Graphics.h"
|
||||
#include "Buffer.h"
|
||||
#include "math/MathModule.h"
|
||||
#include "data/DataModule.h"
|
||||
#include "Polyline.h"
|
||||
#include "font/Font.h"
|
||||
#include "window/Window.h"
|
||||
@@ -100,7 +101,7 @@ bool isDebugEnabled()
|
||||
|
||||
love::Type Graphics::type("graphics", &Module::type);
|
||||
|
||||
Shader::ShaderSource Graphics::defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
|
||||
Graphics::DefaultShaderCode Graphics::defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
|
||||
|
||||
Graphics::Graphics()
|
||||
: width(0)
|
||||
@@ -115,6 +116,7 @@ Graphics::Graphics()
|
||||
, canvasSwitchCount(0)
|
||||
, drawCallsBatched(0)
|
||||
, capabilities()
|
||||
, cachedShaderStages()
|
||||
{
|
||||
transformStack.reserve(16);
|
||||
transformStack.push_back(Matrix4());
|
||||
@@ -149,6 +151,9 @@ Graphics::~Graphics()
|
||||
delete streamBufferState.vb[1];
|
||||
delete streamBufferState.indexBuffer;
|
||||
|
||||
for (int i = 0; i < (int) ShaderStage::STAGE_MAX_ENUM; i++)
|
||||
cachedShaderStages[i].clear();
|
||||
|
||||
Shader::deinitialize();
|
||||
}
|
||||
|
||||
@@ -177,9 +182,77 @@ Video *Graphics::newVideo(love::video::VideoStream *stream, float dpiscale)
|
||||
return new Video(this, stream, dpiscale);
|
||||
}
|
||||
|
||||
bool Graphics::validateShader(bool gles, const Shader::ShaderSource &source, std::string &err)
|
||||
ShaderStage *Graphics::newShaderStage(ShaderStage::StageType stage, const std::string &optsource)
|
||||
{
|
||||
return Shader::validate(this, gles, source, true, err);
|
||||
if (stage == ShaderStage::STAGE_MAX_ENUM)
|
||||
throw love::Exception("Invalid shader stage.");
|
||||
|
||||
const std::string &source = optsource.empty() ? getCurrentDefaultShaderCode().source[stage] : optsource;
|
||||
|
||||
ShaderStage *s = nullptr;
|
||||
std::string cachekey;
|
||||
|
||||
if (!source.empty())
|
||||
{
|
||||
data::HashFunction::Value hashvalue;
|
||||
data::hash(data::HashFunction::FUNCTION_SHA1, source.c_str(), source.size(), hashvalue);
|
||||
|
||||
cachekey = std::string(hashvalue.data, hashvalue.size);
|
||||
|
||||
auto it = cachedShaderStages[stage].find(cachekey);
|
||||
if (it != cachedShaderStages[stage].end())
|
||||
{
|
||||
s = it->second;
|
||||
s->retain();
|
||||
}
|
||||
}
|
||||
|
||||
if (s == nullptr)
|
||||
{
|
||||
s = newShaderStageInternal(stage, cachekey, source, getRenderer() == RENDERER_OPENGLES);
|
||||
if (!cachekey.empty())
|
||||
cachedShaderStages[stage][cachekey] = s;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void Graphics::cleanupCachedShaderStage(ShaderStage::StageType type, const std::string &hashkey)
|
||||
{
|
||||
cachedShaderStages[type].erase(hashkey);
|
||||
}
|
||||
|
||||
Shader *Graphics::newShader(const std::string &vertex, const std::string &pixel)
|
||||
{
|
||||
if (vertex.empty() && pixel.empty())
|
||||
throw love::Exception("Error creating shader: no source code!");
|
||||
|
||||
StrongRef<ShaderStage> vertexstage(newShaderStage(ShaderStage::STAGE_VERTEX, vertex), Acquire::NORETAIN);
|
||||
StrongRef<ShaderStage> pixelstage(newShaderStage(ShaderStage::STAGE_PIXEL, pixel), Acquire::NORETAIN);
|
||||
|
||||
return newShaderInternal(vertexstage.get(), pixelstage.get());
|
||||
}
|
||||
|
||||
bool Graphics::validateShader(bool gles, const std::string &vertex, const std::string &pixel, std::string &err)
|
||||
{
|
||||
if (vertex.empty() && pixel.empty())
|
||||
{
|
||||
err = "Error validating shader: no source code!";
|
||||
return false;
|
||||
}
|
||||
|
||||
StrongRef<ShaderStage> vertexstage;
|
||||
StrongRef<ShaderStage> pixelstage;
|
||||
|
||||
// Don't use cached shader stages, since the gles flag may not match the
|
||||
// current renderer.
|
||||
if (!vertex.empty())
|
||||
vertexstage.set(new ShaderStageForValidation(this, ShaderStage::STAGE_VERTEX, vertex, gles), Acquire::NORETAIN);
|
||||
|
||||
if (!pixel.empty())
|
||||
pixelstage.set(new ShaderStageForValidation(this, ShaderStage::STAGE_PIXEL, pixel, gles), Acquire::NORETAIN);
|
||||
|
||||
return Shader::validate(vertexstage.get(), pixelstage.get(), err);
|
||||
}
|
||||
|
||||
int Graphics::getWidth() const
|
||||
@@ -1425,9 +1498,12 @@ Vector2 Graphics::inverseTransformPoint(Vector2 point)
|
||||
return p;
|
||||
}
|
||||
|
||||
const Shader::ShaderSource &Graphics::getCurrentDefaultShaderCode() const
|
||||
const Graphics::DefaultShaderCode &Graphics::getCurrentDefaultShaderCode() const
|
||||
{
|
||||
return defaultShaderCode[Shader::STANDARD_DEFAULT][getShaderLanguageTarget()][isGammaCorrect() ? 1 : 0];
|
||||
int languageindex = (int) getShaderLanguageTarget();
|
||||
int gammaindex = isGammaCorrect() ? 1 : 0;
|
||||
|
||||
return defaultShaderCode[Shader::STANDARD_DEFAULT][languageindex][gammaindex];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "Texture.h"
|
||||
#include "Canvas.h"
|
||||
#include "Font.h"
|
||||
#include "ShaderStage.h"
|
||||
#include "Shader.h"
|
||||
#include "Quad.h"
|
||||
#include "Mesh.h"
|
||||
@@ -44,6 +45,7 @@
|
||||
#include "font/Rasterizer.h"
|
||||
#include "font/Font.h"
|
||||
#include "video/VideoStream.h"
|
||||
#include "data/HashFunction.h"
|
||||
|
||||
// C++
|
||||
#include <string>
|
||||
@@ -359,6 +361,11 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
struct DefaultShaderCode
|
||||
{
|
||||
std::string source[ShaderStage::STAGE_MAX_ENUM];
|
||||
};
|
||||
|
||||
Graphics();
|
||||
virtual ~Graphics();
|
||||
|
||||
@@ -378,7 +385,9 @@ public:
|
||||
virtual ParticleSystem *newParticleSystem(Texture *texture, int size) = 0;
|
||||
|
||||
virtual Canvas *newCanvas(const Canvas::Settings &settings) = 0;
|
||||
virtual Shader *newShader(const Shader::ShaderSource &source) = 0;
|
||||
|
||||
ShaderStage *newShaderStage(ShaderStage::StageType stage, const std::string &source);
|
||||
Shader *newShader(const std::string &vertex, const std::string &pixel);
|
||||
|
||||
virtual Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) = 0;
|
||||
|
||||
@@ -390,7 +399,7 @@ public:
|
||||
|
||||
virtual Text *newText(Font *font, const std::vector<Font::ColoredString> &text = {}) = 0;
|
||||
|
||||
bool validateShader(bool gles, const Shader::ShaderSource &source, std::string &err);
|
||||
bool validateShader(bool gles, const std::string &vertex, const std::string &pixel, std::string &err);
|
||||
|
||||
/**
|
||||
* Resets the current color, background color, line style, and so forth.
|
||||
@@ -758,7 +767,9 @@ public:
|
||||
static void flushStreamDrawsGlobal();
|
||||
|
||||
virtual Shader::Language getShaderLanguageTarget() const = 0;
|
||||
const Shader::ShaderSource &getCurrentDefaultShaderCode() const;
|
||||
const DefaultShaderCode &getCurrentDefaultShaderCode() const;
|
||||
|
||||
void cleanupCachedShaderStage(ShaderStage::StageType type, const std::string &cachekey);
|
||||
|
||||
template <typename T>
|
||||
T *getScratchBuffer(size_t count)
|
||||
@@ -806,7 +817,7 @@ public:
|
||||
static std::vector<std::string> getConstants(StackType);
|
||||
|
||||
// Default shader code (a shader is always required internally.)
|
||||
static Shader::ShaderSource defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
|
||||
static DefaultShaderCode defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
|
||||
|
||||
protected:
|
||||
|
||||
@@ -868,6 +879,8 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
virtual ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) = 0;
|
||||
virtual Shader *newShaderInternal(ShaderStage *vertex, ShaderStage *pixel) = 0;
|
||||
virtual StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0;
|
||||
|
||||
virtual void setCanvasInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas) = 0;
|
||||
@@ -926,6 +939,8 @@ private:
|
||||
|
||||
std::vector<uint8> scratchBuffer;
|
||||
|
||||
std::unordered_map<std::string, ShaderStage *> cachedShaderStages[ShaderStage::STAGE_MAX_ENUM];
|
||||
|
||||
static StringMap<DrawMode, DRAW_MAX_ENUM>::Entry drawModeEntries[];
|
||||
static StringMap<DrawMode, DRAW_MAX_ENUM> drawModes;
|
||||
|
||||
|
||||
+11
-175
@@ -29,103 +29,6 @@
|
||||
// C++
|
||||
#include <string>
|
||||
|
||||
// TODO: Use love.graphics to determine actual limits?
|
||||
static const TBuiltInResource defaultTBuiltInResource = {
|
||||
/* .MaxLights = */ 32,
|
||||
/* .MaxClipPlanes = */ 6,
|
||||
/* .MaxTextureUnits = */ 32,
|
||||
/* .MaxTextureCoords = */ 32,
|
||||
/* .MaxVertexAttribs = */ 64,
|
||||
/* .MaxVertexUniformComponents = */ 16384,
|
||||
/* .MaxVaryingFloats = */ 128,
|
||||
/* .MaxVertexTextureImageUnits = */ 32,
|
||||
/* .MaxCombinedTextureImageUnits = */ 80,
|
||||
/* .MaxTextureImageUnits = */ 32,
|
||||
/* .MaxFragmentUniformComponents = */ 16384,
|
||||
/* .MaxDrawBuffers = */ 8,
|
||||
/* .MaxVertexUniformVectors = */ 4096,
|
||||
/* .MaxVaryingVectors = */ 32,
|
||||
/* .MaxFragmentUniformVectors = */ 4096,
|
||||
/* .MaxVertexOutputVectors = */ 32,
|
||||
/* .MaxFragmentInputVectors = */ 31,
|
||||
/* .MinProgramTexelOffset = */ -8,
|
||||
/* .MaxProgramTexelOffset = */ 7,
|
||||
/* .MaxClipDistances = */ 8,
|
||||
/* .MaxComputeWorkGroupCountX = */ 65535,
|
||||
/* .MaxComputeWorkGroupCountY = */ 65535,
|
||||
/* .MaxComputeWorkGroupCountZ = */ 65535,
|
||||
/* .MaxComputeWorkGroupSizeX = */ 1024,
|
||||
/* .MaxComputeWorkGroupSizeY = */ 1024,
|
||||
/* .MaxComputeWorkGroupSizeZ = */ 64,
|
||||
/* .MaxComputeUniformComponents = */ 1024,
|
||||
/* .MaxComputeTextureImageUnits = */ 32,
|
||||
/* .MaxComputeImageUniforms = */ 16,
|
||||
/* .MaxComputeAtomicCounters = */ 4096,
|
||||
/* .MaxComputeAtomicCounterBuffers = */ 8,
|
||||
/* .MaxVaryingComponents = */ 128,
|
||||
/* .MaxVertexOutputComponents = */ 128,
|
||||
/* .MaxGeometryInputComponents = */ 128,
|
||||
/* .MaxGeometryOutputComponents = */ 128,
|
||||
/* .MaxFragmentInputComponents = */ 128,
|
||||
/* .MaxImageUnits = */ 192,
|
||||
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 144,
|
||||
/* .MaxCombinedShaderOutputResources = */ 144,
|
||||
/* .MaxImageSamples = */ 32,
|
||||
/* .MaxVertexImageUniforms = */ 16,
|
||||
/* .MaxTessControlImageUniforms = */ 16,
|
||||
/* .MaxTessEvaluationImageUniforms = */ 16,
|
||||
/* .MaxGeometryImageUniforms = */ 16,
|
||||
/* .MaxFragmentImageUniforms = */ 16,
|
||||
/* .MaxCombinedImageUniforms = */ 80,
|
||||
/* .MaxGeometryTextureImageUnits = */ 16,
|
||||
/* .MaxGeometryOutputVertices = */ 256,
|
||||
/* .MaxGeometryTotalOutputComponents = */ 1024,
|
||||
/* .MaxGeometryUniformComponents = */ 1024,
|
||||
/* .MaxGeometryVaryingComponents = */ 64,
|
||||
/* .MaxTessControlInputComponents = */ 128,
|
||||
/* .MaxTessControlOutputComponents = */ 128,
|
||||
/* .MaxTessControlTextureImageUnits = */ 16,
|
||||
/* .MaxTessControlUniformComponents = */ 1024,
|
||||
/* .MaxTessControlTotalOutputComponents = */ 4096,
|
||||
/* .MaxTessEvaluationInputComponents = */ 128,
|
||||
/* .MaxTessEvaluationOutputComponents = */ 128,
|
||||
/* .MaxTessEvaluationTextureImageUnits = */ 16,
|
||||
/* .MaxTessEvaluationUniformComponents = */ 1024,
|
||||
/* .MaxTessPatchComponents = */ 120,
|
||||
/* .MaxPatchVertices = */ 32,
|
||||
/* .MaxTessGenLevel = */ 64,
|
||||
/* .MaxViewports = */ 16,
|
||||
/* .MaxVertexAtomicCounters = */ 4096,
|
||||
/* .MaxTessControlAtomicCounters = */ 4096,
|
||||
/* .MaxTessEvaluationAtomicCounters = */ 4096,
|
||||
/* .MaxGeometryAtomicCounters = */ 4096,
|
||||
/* .MaxFragmentAtomicCounters = */ 4096,
|
||||
/* .MaxCombinedAtomicCounters = */ 4096,
|
||||
/* .MaxAtomicCounterBindings = */ 8,
|
||||
/* .MaxVertexAtomicCounterBuffers = */ 8,
|
||||
/* .MaxTessControlAtomicCounterBuffers = */ 8,
|
||||
/* .MaxTessEvaluationAtomicCounterBuffers = */ 8,
|
||||
/* .MaxGeometryAtomicCounterBuffers = */ 8,
|
||||
/* .MaxFragmentAtomicCounterBuffers = */ 8,
|
||||
/* .MaxCombinedAtomicCounterBuffers = */ 8,
|
||||
/* .MaxAtomicCounterBufferSize = */ 16384,
|
||||
/* .MaxTransformFeedbackBuffers = */ 4,
|
||||
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
|
||||
/* .MaxCullDistances = */ 8,
|
||||
/* .MaxCombinedClipAndCullDistances = */ 8,
|
||||
/* .MaxSamples = */ 32,
|
||||
/* .limits = */ {
|
||||
/* .nonInductiveForLoops = */ 1,
|
||||
/* .whileLoops = */ 1,
|
||||
/* .doWhileLoops = */ 1,
|
||||
/* .generalUniformIndexing = */ 1,
|
||||
/* .generalAttributeMatrixVectorIndexing = */ 1,
|
||||
/* .generalVaryingIndexing = */ 1,
|
||||
/* .generalSamplerIndexing = */ 1,
|
||||
/* .generalVariableIndexing = */ 1,
|
||||
/* .generalConstantMatrixVectorIndexing = */ 1,
|
||||
}};
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
@@ -136,17 +39,15 @@ love::Type Shader::type("Shader", &Object::type);
|
||||
Shader *Shader::current = nullptr;
|
||||
Shader *Shader::standardShaders[Shader::STANDARD_MAX_ENUM] = {nullptr};
|
||||
|
||||
Shader::Shader(const ShaderSource &source)
|
||||
: shaderSource(source)
|
||||
Shader::Shader(ShaderStage *vertex, ShaderStage *pixel)
|
||||
: stages()
|
||||
{
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx == nullptr)
|
||||
throw love::Exception("love.graphics must be initialized to create a Shader.");
|
||||
|
||||
bool gles = gfx->getRenderer() == Graphics::RENDERER_OPENGLES;
|
||||
std::string err;
|
||||
if (!validate(gfx, gles, source, false, err))
|
||||
if (!validate(vertex, pixel, err))
|
||||
throw love::Exception("%s", err.c_str());
|
||||
|
||||
stages[ShaderStage::STAGE_VERTEX] = vertex;
|
||||
stages[ShaderStage::STAGE_PIXEL] = pixel;
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
@@ -225,62 +126,15 @@ void Shader::checkMainTexture(Texture *tex) const
|
||||
checkMainTextureType(tex->getTextureType(), tex->getDepthSampleMode().hasValue);
|
||||
}
|
||||
|
||||
bool Shader::validate(Graphics *gfx, bool gles, const ShaderSource &source, bool checkWithDefaults, std::string &err)
|
||||
bool Shader::validate(ShaderStage *vertex, ShaderStage *pixel, std::string &err)
|
||||
{
|
||||
if (source.vertex.empty() && source.pixel.empty())
|
||||
{
|
||||
err = "Error validating shader: no source code!";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3];
|
||||
|
||||
int defaultversion = gles ? 100 : 120;
|
||||
EProfile defaultprofile = ENoProfile;
|
||||
|
||||
glslang::TShader vshader(EShLangVertex);
|
||||
glslang::TShader pshader(EShLangFragment);
|
||||
|
||||
// TProgram must be destroyed before TShader.
|
||||
glslang::TProgram program;
|
||||
|
||||
auto addshader = [&](glslang::TShader &s, const std::string &src, ShaderStage stage) -> bool
|
||||
{
|
||||
if (src.empty())
|
||||
return true;
|
||||
if (vertex != nullptr)
|
||||
program.addShader(vertex->getGLSLangShader());
|
||||
|
||||
const char *csrc = src.c_str();
|
||||
int srclen = (int) src.length();
|
||||
s.setStringsWithLengths(&csrc, &srclen, 1);
|
||||
|
||||
bool forcedefault = false;
|
||||
if (src.find("#define LOVE_GLSL1_ON_GLSL3") != std::string::npos)
|
||||
forcedefault = true;
|
||||
|
||||
bool forwardcompat = supportsGLSL3 && !forcedefault;
|
||||
|
||||
if (!s.parse(&defaultTBuiltInResource, defaultversion, defaultprofile, forcedefault, forwardcompat, EShMsgSuppressWarnings))
|
||||
{
|
||||
const char *stagename = "unknown";
|
||||
getConstant(stage, stagename);
|
||||
err = "Error validating " + std::string(stagename) + " shader:\n\n"
|
||||
+ std::string(s.getInfoLog()) + "\n" + std::string(s.getInfoDebugLog());
|
||||
return false;
|
||||
}
|
||||
|
||||
program.addShader(&s);
|
||||
return true;
|
||||
};
|
||||
|
||||
const ShaderSource &defaults = gfx->getCurrentDefaultShaderCode();
|
||||
const std::string &vertcode = (checkWithDefaults && source.vertex.empty()) ? defaults.vertex : source.vertex;
|
||||
const std::string &pixcode = (checkWithDefaults && source.pixel.empty()) ? defaults.pixel : source.pixel;
|
||||
|
||||
if (!addshader(vshader, vertcode, STAGE_VERTEX))
|
||||
return false;
|
||||
|
||||
if (!addshader(pshader, pixcode, STAGE_PIXEL))
|
||||
return false;
|
||||
if (pixel != nullptr)
|
||||
program.addShader(pixel->getGLSLangShader());
|
||||
|
||||
if (!program.link(EShMsgDefault))
|
||||
{
|
||||
@@ -311,16 +165,6 @@ bool Shader::getConstant(Language in, const char *&out)
|
||||
return languages.find(in, out);
|
||||
}
|
||||
|
||||
bool Shader::getConstant(const char *in, ShaderStage &out)
|
||||
{
|
||||
return stageNames.find(in, out);
|
||||
}
|
||||
|
||||
bool Shader::getConstant(ShaderStage in, const char *&out)
|
||||
{
|
||||
return stageNames.find(in, out);
|
||||
}
|
||||
|
||||
bool Shader::getConstant(const char *in, BuiltinUniform &out)
|
||||
{
|
||||
return builtinNames.find(in, out);
|
||||
@@ -341,14 +185,6 @@ StringMap<Shader::Language, Shader::LANGUAGE_MAX_ENUM>::Entry Shader::languageEn
|
||||
|
||||
StringMap<Shader::Language, Shader::LANGUAGE_MAX_ENUM> Shader::languages(Shader::languageEntries, sizeof(Shader::languageEntries));
|
||||
|
||||
StringMap<Shader::ShaderStage, Shader::STAGE_MAX_ENUM>::Entry Shader::stageNameEntries[] =
|
||||
{
|
||||
{ "vertex", STAGE_VERTEX },
|
||||
{ "pixel", STAGE_PIXEL },
|
||||
};
|
||||
|
||||
StringMap<Shader::ShaderStage, Shader::STAGE_MAX_ENUM> Shader::stageNames(Shader::stageNameEntries, sizeof(Shader::stageNameEntries));
|
||||
|
||||
StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builtinNameEntries[] =
|
||||
{
|
||||
{ "MainTex", BUILTIN_TEXTURE_MAIN },
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "common/Object.h"
|
||||
#include "common/StringMap.h"
|
||||
#include "Texture.h"
|
||||
#include "ShaderStage.h"
|
||||
|
||||
// STL
|
||||
#include <string>
|
||||
@@ -59,13 +60,6 @@ public:
|
||||
LANGUAGE_MAX_ENUM
|
||||
};
|
||||
|
||||
enum ShaderStage
|
||||
{
|
||||
STAGE_VERTEX,
|
||||
STAGE_PIXEL,
|
||||
STAGE_MAX_ENUM
|
||||
};
|
||||
|
||||
// Built-in uniform variables.
|
||||
enum BuiltinUniform
|
||||
{
|
||||
@@ -103,12 +97,6 @@ public:
|
||||
STANDARD_MAX_ENUM
|
||||
};
|
||||
|
||||
struct ShaderSource
|
||||
{
|
||||
std::string vertex;
|
||||
std::string pixel;
|
||||
};
|
||||
|
||||
struct MatrixSize
|
||||
{
|
||||
short columns;
|
||||
@@ -150,7 +138,7 @@ public:
|
||||
// Pointer to the default Shader.
|
||||
static Shader *standardShaders[STANDARD_MAX_ENUM];
|
||||
|
||||
Shader(const ShaderSource &source);
|
||||
Shader(ShaderStage *vertex, ShaderStage *pixel);
|
||||
virtual ~Shader();
|
||||
|
||||
/**
|
||||
@@ -197,7 +185,7 @@ public:
|
||||
|
||||
virtual ptrdiff_t getHandle() const = 0;
|
||||
|
||||
static bool validate(Graphics *gfx, bool gles, const ShaderSource &source, bool checkWithDefaults, std::string &err);
|
||||
static bool validate(ShaderStage *vertex, ShaderStage *pixel, std::string &err);
|
||||
|
||||
static bool initialize();
|
||||
static void deinitialize();
|
||||
@@ -205,34 +193,17 @@ public:
|
||||
static bool getConstant(const char *in, Language &out);
|
||||
static bool getConstant(Language in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, ShaderStage &out);
|
||||
static bool getConstant(ShaderStage in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, BuiltinUniform &out);
|
||||
static bool getConstant(BuiltinUniform in, const char *&out);
|
||||
|
||||
protected:
|
||||
|
||||
struct CachedShaderStage
|
||||
{
|
||||
int referenceCount;
|
||||
ShaderStage stage;
|
||||
glslang::TShader *glslangShader;
|
||||
ptrdiff_t handle;
|
||||
};
|
||||
|
||||
// Source code used for this Shader.
|
||||
ShaderSource shaderSource;
|
||||
|
||||
static std::map<std::string, CachedShaderStage> cachedShaders;
|
||||
StrongRef<ShaderStage> stages[ShaderStage::STAGE_MAX_ENUM];
|
||||
|
||||
private:
|
||||
|
||||
static StringMap<Language, LANGUAGE_MAX_ENUM>::Entry languageEntries[];
|
||||
static StringMap<Language, LANGUAGE_MAX_ENUM> languages;
|
||||
|
||||
static StringMap<ShaderStage, STAGE_MAX_ENUM>::Entry stageNameEntries[];
|
||||
static StringMap<ShaderStage, STAGE_MAX_ENUM> stageNames;
|
||||
|
||||
// Names for the built-in uniform variables.
|
||||
static StringMap<BuiltinUniform, BUILTIN_MAX_ENUM>::Entry builtinNameEntries[];
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2017 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "ShaderStage.h"
|
||||
#include "common/Exception.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
#include "libraries/glslang/glslang/Public/ShaderLang.h"
|
||||
|
||||
// TODO: Use love.graphics to determine actual limits?
|
||||
static const TBuiltInResource defaultTBuiltInResource = {
|
||||
/* .MaxLights = */ 32,
|
||||
/* .MaxClipPlanes = */ 6,
|
||||
/* .MaxTextureUnits = */ 32,
|
||||
/* .MaxTextureCoords = */ 32,
|
||||
/* .MaxVertexAttribs = */ 64,
|
||||
/* .MaxVertexUniformComponents = */ 16384,
|
||||
/* .MaxVaryingFloats = */ 128,
|
||||
/* .MaxVertexTextureImageUnits = */ 32,
|
||||
/* .MaxCombinedTextureImageUnits = */ 80,
|
||||
/* .MaxTextureImageUnits = */ 32,
|
||||
/* .MaxFragmentUniformComponents = */ 16384,
|
||||
/* .MaxDrawBuffers = */ 8,
|
||||
/* .MaxVertexUniformVectors = */ 4096,
|
||||
/* .MaxVaryingVectors = */ 32,
|
||||
/* .MaxFragmentUniformVectors = */ 4096,
|
||||
/* .MaxVertexOutputVectors = */ 32,
|
||||
/* .MaxFragmentInputVectors = */ 31,
|
||||
/* .MinProgramTexelOffset = */ -8,
|
||||
/* .MaxProgramTexelOffset = */ 7,
|
||||
/* .MaxClipDistances = */ 8,
|
||||
/* .MaxComputeWorkGroupCountX = */ 65535,
|
||||
/* .MaxComputeWorkGroupCountY = */ 65535,
|
||||
/* .MaxComputeWorkGroupCountZ = */ 65535,
|
||||
/* .MaxComputeWorkGroupSizeX = */ 1024,
|
||||
/* .MaxComputeWorkGroupSizeY = */ 1024,
|
||||
/* .MaxComputeWorkGroupSizeZ = */ 64,
|
||||
/* .MaxComputeUniformComponents = */ 1024,
|
||||
/* .MaxComputeTextureImageUnits = */ 32,
|
||||
/* .MaxComputeImageUniforms = */ 16,
|
||||
/* .MaxComputeAtomicCounters = */ 4096,
|
||||
/* .MaxComputeAtomicCounterBuffers = */ 8,
|
||||
/* .MaxVaryingComponents = */ 128,
|
||||
/* .MaxVertexOutputComponents = */ 128,
|
||||
/* .MaxGeometryInputComponents = */ 128,
|
||||
/* .MaxGeometryOutputComponents = */ 128,
|
||||
/* .MaxFragmentInputComponents = */ 128,
|
||||
/* .MaxImageUnits = */ 192,
|
||||
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 144,
|
||||
/* .MaxCombinedShaderOutputResources = */ 144,
|
||||
/* .MaxImageSamples = */ 32,
|
||||
/* .MaxVertexImageUniforms = */ 16,
|
||||
/* .MaxTessControlImageUniforms = */ 16,
|
||||
/* .MaxTessEvaluationImageUniforms = */ 16,
|
||||
/* .MaxGeometryImageUniforms = */ 16,
|
||||
/* .MaxFragmentImageUniforms = */ 16,
|
||||
/* .MaxCombinedImageUniforms = */ 80,
|
||||
/* .MaxGeometryTextureImageUnits = */ 16,
|
||||
/* .MaxGeometryOutputVertices = */ 256,
|
||||
/* .MaxGeometryTotalOutputComponents = */ 1024,
|
||||
/* .MaxGeometryUniformComponents = */ 1024,
|
||||
/* .MaxGeometryVaryingComponents = */ 64,
|
||||
/* .MaxTessControlInputComponents = */ 128,
|
||||
/* .MaxTessControlOutputComponents = */ 128,
|
||||
/* .MaxTessControlTextureImageUnits = */ 16,
|
||||
/* .MaxTessControlUniformComponents = */ 1024,
|
||||
/* .MaxTessControlTotalOutputComponents = */ 4096,
|
||||
/* .MaxTessEvaluationInputComponents = */ 128,
|
||||
/* .MaxTessEvaluationOutputComponents = */ 128,
|
||||
/* .MaxTessEvaluationTextureImageUnits = */ 16,
|
||||
/* .MaxTessEvaluationUniformComponents = */ 1024,
|
||||
/* .MaxTessPatchComponents = */ 120,
|
||||
/* .MaxPatchVertices = */ 32,
|
||||
/* .MaxTessGenLevel = */ 64,
|
||||
/* .MaxViewports = */ 16,
|
||||
/* .MaxVertexAtomicCounters = */ 4096,
|
||||
/* .MaxTessControlAtomicCounters = */ 4096,
|
||||
/* .MaxTessEvaluationAtomicCounters = */ 4096,
|
||||
/* .MaxGeometryAtomicCounters = */ 4096,
|
||||
/* .MaxFragmentAtomicCounters = */ 4096,
|
||||
/* .MaxCombinedAtomicCounters = */ 4096,
|
||||
/* .MaxAtomicCounterBindings = */ 8,
|
||||
/* .MaxVertexAtomicCounterBuffers = */ 8,
|
||||
/* .MaxTessControlAtomicCounterBuffers = */ 8,
|
||||
/* .MaxTessEvaluationAtomicCounterBuffers = */ 8,
|
||||
/* .MaxGeometryAtomicCounterBuffers = */ 8,
|
||||
/* .MaxFragmentAtomicCounterBuffers = */ 8,
|
||||
/* .MaxCombinedAtomicCounterBuffers = */ 8,
|
||||
/* .MaxAtomicCounterBufferSize = */ 16384,
|
||||
/* .MaxTransformFeedbackBuffers = */ 4,
|
||||
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
|
||||
/* .MaxCullDistances = */ 8,
|
||||
/* .MaxCombinedClipAndCullDistances = */ 8,
|
||||
/* .MaxSamples = */ 32,
|
||||
/* .limits = */ {
|
||||
/* .nonInductiveForLoops = */ 1,
|
||||
/* .whileLoops = */ 1,
|
||||
/* .doWhileLoops = */ 1,
|
||||
/* .generalUniformIndexing = */ 1,
|
||||
/* .generalAttributeMatrixVectorIndexing = */ 1,
|
||||
/* .generalVaryingIndexing = */ 1,
|
||||
/* .generalSamplerIndexing = */ 1,
|
||||
/* .generalVariableIndexing = */ 1,
|
||||
/* .generalConstantMatrixVectorIndexing = */ 1,
|
||||
}
|
||||
};
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
ShaderStage::ShaderStage(Graphics *gfx, StageType stage, const std::string &glsl, bool gles, const std::string &cachekey)
|
||||
: stageType(stage)
|
||||
, source(glsl)
|
||||
, cacheKey(cachekey)
|
||||
, glslangShader(nullptr)
|
||||
{
|
||||
EShLanguage glslangStage = EShLangCount;
|
||||
if (stage == STAGE_VERTEX)
|
||||
glslangStage = EShLangVertex;
|
||||
else if (stage == STAGE_PIXEL)
|
||||
glslangStage = EShLangFragment;
|
||||
else
|
||||
throw love::Exception("Cannot compile shader stage: unknown stage type.");
|
||||
|
||||
glslangShader = new glslang::TShader(glslangStage);
|
||||
|
||||
bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3];
|
||||
int defaultversion = gles ? 100 : 120;
|
||||
EProfile defaultprofile = ENoProfile;
|
||||
|
||||
const char *csrc = glsl.c_str();
|
||||
int srclen = (int) glsl.length();
|
||||
glslangShader->setStringsWithLengths(&csrc, &srclen, 1);
|
||||
|
||||
bool forcedefault = false;
|
||||
if (source.find("#define LOVE_GLSL1_ON_GLSL3") != std::string::npos)
|
||||
forcedefault = true;
|
||||
|
||||
bool forwardcompat = supportsGLSL3 && !forcedefault;
|
||||
|
||||
if (!glslangShader->parse(&defaultTBuiltInResource, defaultversion, defaultprofile, forcedefault, forwardcompat, EShMsgSuppressWarnings))
|
||||
{
|
||||
const char *stagename = "unknown";
|
||||
getConstant(stage, stagename);
|
||||
|
||||
std::string err = "Error validating " + std::string(stagename) + " shader:\n\n"
|
||||
+ std::string(glslangShader->getInfoLog()) + "\n"
|
||||
+ std::string(glslangShader->getInfoDebugLog());
|
||||
|
||||
delete glslangShader;
|
||||
throw love::Exception("%s", err.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ShaderStage::~ShaderStage()
|
||||
{
|
||||
if (!cacheKey.empty())
|
||||
{
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
gfx->cleanupCachedShaderStage(stageType, cacheKey);
|
||||
}
|
||||
|
||||
delete glslangShader;
|
||||
}
|
||||
|
||||
bool ShaderStage::getConstant(const char *in, StageType &out)
|
||||
{
|
||||
return stageNames.find(in, out);
|
||||
}
|
||||
|
||||
bool ShaderStage::getConstant(StageType in, const char *&out)
|
||||
{
|
||||
return stageNames.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<ShaderStage::StageType, ShaderStage::STAGE_MAX_ENUM>::Entry ShaderStage::stageNameEntries[] =
|
||||
{
|
||||
{ "vertex", STAGE_VERTEX },
|
||||
{ "pixel", STAGE_PIXEL },
|
||||
};
|
||||
|
||||
StringMap<ShaderStage::StageType, ShaderStage::STAGE_MAX_ENUM> ShaderStage::stageNames(ShaderStage::stageNameEntries, sizeof(ShaderStage::stageNameEntries));
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2017 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Object.h"
|
||||
#include "common/StringMap.h"
|
||||
#include "Volatile.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
namespace glslang
|
||||
{
|
||||
class TShader;
|
||||
}
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
class Graphics;
|
||||
|
||||
class ShaderStage : public love::Object, public Volatile
|
||||
{
|
||||
public:
|
||||
|
||||
enum StageType
|
||||
{
|
||||
STAGE_VERTEX,
|
||||
STAGE_PIXEL,
|
||||
STAGE_MAX_ENUM
|
||||
};
|
||||
|
||||
ShaderStage(Graphics *gfx, StageType stage, const std::string &glsl, bool gles, const std::string &cachekey);
|
||||
virtual ~ShaderStage();
|
||||
|
||||
StageType getStageType() const { return stageType; }
|
||||
const std::string &getSource() const { return source; }
|
||||
const std::string &getWarnings() const { return warnings; }
|
||||
glslang::TShader *getGLSLangShader() const { return glslangShader; }
|
||||
|
||||
virtual ptrdiff_t getHandle() const = 0;
|
||||
|
||||
static bool getConstant(const char *in, StageType &out);
|
||||
static bool getConstant(StageType in, const char *&out);
|
||||
|
||||
protected:
|
||||
|
||||
std::string warnings;
|
||||
|
||||
private:
|
||||
|
||||
StageType stageType;
|
||||
std::string source;
|
||||
std::string cacheKey;
|
||||
glslang::TShader *glslangShader;
|
||||
|
||||
static StringMap<StageType, STAGE_MAX_ENUM>::Entry stageNameEntries[];
|
||||
static StringMap<StageType, STAGE_MAX_ENUM> stageNames;
|
||||
|
||||
}; // ShaderStage
|
||||
|
||||
class ShaderStageForValidation final : public ShaderStage
|
||||
{
|
||||
public:
|
||||
|
||||
ShaderStageForValidation(Graphics *gfx, StageType stage, const std::string &glsl, bool gles)
|
||||
: ShaderStage(gfx, stage, glsl, gles, "")
|
||||
{}
|
||||
|
||||
virtual ~ShaderStageForValidation() {}
|
||||
|
||||
ptrdiff_t getHandle() const override { return 0; }
|
||||
bool loadVolatile() override { return true; }
|
||||
void unloadVolatile() override { }
|
||||
|
||||
}; // ShaderStageForValidation
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -52,14 +52,6 @@ enum TextureType
|
||||
TEXTURE_MAX_ENUM
|
||||
};
|
||||
|
||||
class TextureTooLargeException : public love::Exception
|
||||
{
|
||||
public:
|
||||
TextureTooLargeException(const char *dimname, int pix)
|
||||
: Exception("Cannot create texture: %s of %d pixels is too large for this system.", dimname, pix)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for 2D textures. All textures can be drawn with Quads, have a
|
||||
* width and height, and have filter and wrap modes.
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "window/Window.h"
|
||||
#include "Buffer.h"
|
||||
#include "Text.h"
|
||||
#include "ShaderStage.h"
|
||||
|
||||
#include "libraries/xxHash/xxhash.h"
|
||||
|
||||
@@ -126,9 +127,14 @@ love::graphics::Canvas *Graphics::newCanvas(const Canvas::Settings &settings)
|
||||
return new Canvas(settings);
|
||||
}
|
||||
|
||||
love::graphics::Shader *Graphics::newShader(const Shader::ShaderSource &source)
|
||||
love::graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles)
|
||||
{
|
||||
return new Shader(source);
|
||||
return new ShaderStage(this, stage, source, gles, cachekey);
|
||||
}
|
||||
|
||||
love::graphics::Shader *Graphics::newShaderInternal(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel)
|
||||
{
|
||||
return new Shader(vertex, pixel);
|
||||
}
|
||||
|
||||
love::graphics::Buffer *Graphics::newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags)
|
||||
@@ -281,7 +287,10 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
|
||||
try
|
||||
{
|
||||
if (!Shader::standardShaders[i])
|
||||
Shader::standardShaders[i] = newShader(defaultShaderCode[i][target][gammacorrect]);
|
||||
{
|
||||
const auto &code = defaultShaderCode[i][target][gammacorrect];
|
||||
Shader::standardShaders[i] = love::graphics::Graphics::newShader(code.source[ShaderStage::STAGE_VERTEX], code.source[ShaderStage::STAGE_PIXEL]);
|
||||
}
|
||||
}
|
||||
catch (love::Exception &)
|
||||
{
|
||||
|
||||
@@ -68,7 +68,6 @@ public:
|
||||
love::graphics::ParticleSystem *newParticleSystem(Texture *texture, int size) override;
|
||||
|
||||
love::graphics::Canvas *newCanvas(const Canvas::Settings &settings) override;
|
||||
love::graphics::Shader *newShader(const Shader::ShaderSource &source) override;
|
||||
|
||||
love::graphics::Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) override;
|
||||
|
||||
@@ -126,6 +125,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
love::graphics::ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
|
||||
love::graphics::Shader *newShaderInternal(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel) override;
|
||||
love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override;
|
||||
void setCanvasInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas) override;
|
||||
void initCapabilities() override;
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace graphics
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
Shader::Shader(const ShaderSource &source)
|
||||
: love::graphics::Shader(source)
|
||||
Shader::Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel)
|
||||
: love::graphics::Shader(vertex, pixel)
|
||||
, program(0)
|
||||
, builtinUniforms()
|
||||
, builtinUniformInfo()
|
||||
@@ -73,71 +73,6 @@ Shader::~Shader()
|
||||
}
|
||||
}
|
||||
|
||||
GLuint Shader::compileCode(ShaderStage stage, const std::string &code)
|
||||
{
|
||||
GLenum glstage;
|
||||
const char *typestr;
|
||||
|
||||
if (!getConstant(stage, typestr))
|
||||
typestr = "";
|
||||
|
||||
switch (stage)
|
||||
{
|
||||
case STAGE_VERTEX:
|
||||
glstage = GL_VERTEX_SHADER;
|
||||
break;
|
||||
case STAGE_PIXEL:
|
||||
glstage = GL_FRAGMENT_SHADER;
|
||||
break;
|
||||
default:
|
||||
throw love::Exception("Cannot create shader object: unknown shader type.");
|
||||
break;
|
||||
}
|
||||
|
||||
GLuint shaderid = glCreateShader(glstage);
|
||||
|
||||
if (shaderid == 0)
|
||||
{
|
||||
if (glGetError() == GL_INVALID_ENUM)
|
||||
throw love::Exception("Cannot create %s shader object: %s shaders not supported.", typestr, typestr);
|
||||
else
|
||||
throw love::Exception("Cannot create %s shader object.", typestr);
|
||||
}
|
||||
|
||||
const char *src = code.c_str();
|
||||
GLint srclen = (GLint) code.length();
|
||||
glShaderSource(shaderid, 1, (const GLchar **)&src, &srclen);
|
||||
|
||||
glCompileShader(shaderid);
|
||||
|
||||
GLint infologlen;
|
||||
glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen);
|
||||
|
||||
// Get any warnings the shader compiler may have produced.
|
||||
if (infologlen > 0)
|
||||
{
|
||||
GLchar *infolog = new GLchar[infologlen];
|
||||
glGetShaderInfoLog(shaderid, infologlen, nullptr, infolog);
|
||||
|
||||
// Save any warnings for later querying.
|
||||
shaderWarnings[stage] = infolog;
|
||||
|
||||
delete[] infolog;
|
||||
}
|
||||
|
||||
GLint status;
|
||||
glGetShaderiv(shaderid, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
glDeleteShader(shaderid);
|
||||
throw love::Exception("Cannot compile %s shader code:\n%s",
|
||||
typestr, shaderWarnings[stage].c_str());
|
||||
}
|
||||
|
||||
return shaderid;
|
||||
}
|
||||
|
||||
void Shader::mapActiveUniforms()
|
||||
{
|
||||
// Built-in uniform locations default to -1 (nonexistent.)
|
||||
@@ -376,38 +311,22 @@ bool Shader::loadVolatile()
|
||||
textureUnits.clear();
|
||||
textureUnits.push_back(TextureUnit());
|
||||
|
||||
std::vector<GLuint> shaderids;
|
||||
|
||||
auto gfx = Module::getInstance<love::graphics::Graphics>(Module::M_GRAPHICS);
|
||||
const ShaderSource &defaults = gfx->getCurrentDefaultShaderCode();
|
||||
|
||||
// The shader program must have both vertex and pixel shader stages.
|
||||
const std::string &vertexcode = shaderSource.vertex.empty() ? defaults.vertex : shaderSource.vertex;
|
||||
const std::string &pixelcode = shaderSource.pixel.empty() ? defaults.pixel : shaderSource.pixel;
|
||||
|
||||
try
|
||||
for (const auto &stage : stages)
|
||||
{
|
||||
shaderids.push_back(compileCode(STAGE_VERTEX, vertexcode));
|
||||
shaderids.push_back(compileCode(STAGE_PIXEL, pixelcode));
|
||||
}
|
||||
catch (love::Exception &)
|
||||
{
|
||||
for (GLuint id : shaderids)
|
||||
glDeleteShader(id);
|
||||
throw;
|
||||
if (stage.get() != nullptr)
|
||||
stage->loadVolatile();
|
||||
}
|
||||
|
||||
program = glCreateProgram();
|
||||
|
||||
if (program == 0)
|
||||
{
|
||||
for (GLuint id : shaderids)
|
||||
glDeleteShader(id);
|
||||
throw love::Exception("Cannot create shader program object.");
|
||||
}
|
||||
|
||||
for (GLuint id : shaderids)
|
||||
glAttachShader(program, id);
|
||||
for (const auto &stage : stages)
|
||||
{
|
||||
if (stage.get() != nullptr)
|
||||
glAttachShader(program, (GLuint) stage->getHandle());
|
||||
}
|
||||
|
||||
// Bind generic vertex attribute indices to names in the shader.
|
||||
for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
|
||||
@@ -419,10 +338,6 @@ bool Shader::loadVolatile()
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
// Flag shaders for auto-deletion when the program object is deleted.
|
||||
for (GLuint id : shaderids)
|
||||
glDeleteShader(id);
|
||||
|
||||
GLint status;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||
|
||||
@@ -477,8 +392,6 @@ void Shader::unloadVolatile()
|
||||
// And the locations of any built-in uniform variables.
|
||||
for (int i = 0; i < int(BUILTIN_MAX_ENUM); i++)
|
||||
builtinUniforms[i] = -1;
|
||||
|
||||
shaderWarnings.clear();
|
||||
}
|
||||
|
||||
std::string Shader::getProgramWarnings() const
|
||||
@@ -506,11 +419,15 @@ std::string Shader::getWarnings() const
|
||||
std::string warnings;
|
||||
const char *stagestr;
|
||||
|
||||
// Get the individual shader stage warnings
|
||||
for (const auto &warning : shaderWarnings)
|
||||
for (const auto &stage : stages)
|
||||
{
|
||||
if (getConstant(warning.first, stagestr))
|
||||
warnings += std::string(stagestr) + std::string(" shader:\n") + warning.second;
|
||||
if (stage.get() == nullptr)
|
||||
continue;
|
||||
|
||||
const std::string &stagewarnings = stage->getWarnings();
|
||||
|
||||
if (ShaderStage::getConstant(stage->getStageType(), stagestr))
|
||||
warnings += std::string(stagestr) + std::string(" shader:\n") + stagewarnings;
|
||||
}
|
||||
|
||||
warnings += getProgramWarnings();
|
||||
|
||||
@@ -47,8 +47,7 @@ public:
|
||||
* Creates a new Shader using a list of source codes.
|
||||
* Source must contain either vertex or pixel shader code, or both.
|
||||
**/
|
||||
Shader(const ShaderSource &source);
|
||||
|
||||
Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel);
|
||||
virtual ~Shader();
|
||||
|
||||
// Implements Volatile
|
||||
@@ -96,16 +95,11 @@ private:
|
||||
TextureType getUniformTextureType(GLenum type) const;
|
||||
bool isDepthTextureType(GLenum type) const;
|
||||
|
||||
GLuint compileCode(ShaderStage stage, const std::string &code);
|
||||
|
||||
void flushStreamDraws() const;
|
||||
|
||||
// Get any warnings or errors generated only by the shader program object.
|
||||
std::string getProgramWarnings() const;
|
||||
|
||||
// Shader compiler warning strings for individual shader stages.
|
||||
std::map<ShaderStage, std::string> shaderWarnings;
|
||||
|
||||
// volatile
|
||||
GLuint program;
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2017 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "ShaderStage.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
ShaderStage::ShaderStage(love::graphics::Graphics *gfx, StageType stage, const std::string &source, bool gles, const std::string &cachekey)
|
||||
: love::graphics::ShaderStage(gfx, stage, source, gles, cachekey)
|
||||
, glShader(0)
|
||||
{
|
||||
loadVolatile();
|
||||
}
|
||||
|
||||
ShaderStage::~ShaderStage()
|
||||
{
|
||||
unloadVolatile();
|
||||
}
|
||||
|
||||
bool ShaderStage::loadVolatile()
|
||||
{
|
||||
if (glShader != 0)
|
||||
return true;
|
||||
|
||||
StageType stage = getStageType();
|
||||
const char *typestr = "unknown";
|
||||
getConstant(stage, typestr);
|
||||
|
||||
GLenum glstage = 0;
|
||||
if (stage == STAGE_VERTEX)
|
||||
glstage = GL_VERTEX_SHADER;
|
||||
else if (stage == STAGE_PIXEL)
|
||||
glstage = GL_FRAGMENT_SHADER;
|
||||
else
|
||||
throw love::Exception("%s shader stage is not handled in OpenGL backend code.", typestr);
|
||||
|
||||
glShader = glCreateShader(glstage);
|
||||
|
||||
if (glShader == 0)
|
||||
throw love::Exception("Cannot create OpenGL %s shader object.", typestr);
|
||||
|
||||
const std::string &sourcestring = getSource();
|
||||
const char *src = sourcestring.c_str();
|
||||
GLint srclen = (GLint) sourcestring.length();
|
||||
|
||||
glShaderSource(glShader, 1, (const GLchar **)&src, &srclen);
|
||||
glCompileShader(glShader);
|
||||
|
||||
GLint infologlen;
|
||||
glGetShaderiv(glShader, GL_INFO_LOG_LENGTH, &infologlen);
|
||||
|
||||
if (infologlen > 0)
|
||||
{
|
||||
GLchar *infolog = new GLchar[infologlen];
|
||||
glGetShaderInfoLog(glShader, infologlen, nullptr, infolog);
|
||||
|
||||
warnings = infolog;
|
||||
delete[] infolog;
|
||||
}
|
||||
|
||||
GLint status = GL_FALSE;
|
||||
glGetShaderiv(glShader, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (glShader == GL_FALSE)
|
||||
{
|
||||
glDeleteShader(glShader);
|
||||
throw love::Exception("Cannot compile %s shader code:\n%s", typestr, warnings.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderStage::unloadVolatile()
|
||||
{
|
||||
if (glShader != 0)
|
||||
glDeleteShader(glShader);
|
||||
|
||||
glShader = 0;
|
||||
}
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2017 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "graphics/ShaderStage.h"
|
||||
#include "graphics/Volatile.h"
|
||||
#include "OpenGL.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
class ShaderStage final : public love::graphics::ShaderStage
|
||||
{
|
||||
public:
|
||||
|
||||
ShaderStage(love::graphics::Graphics *gfx, StageType stage, const std::string &source, bool gles, const std::string &cachekey);
|
||||
virtual ~ShaderStage();
|
||||
|
||||
ptrdiff_t getHandle() const override { return glShader; }
|
||||
|
||||
// Implements Volatile.
|
||||
bool loadVolatile() override;
|
||||
void unloadVolatile() override;
|
||||
|
||||
private:
|
||||
|
||||
GLuint glShader;
|
||||
|
||||
}; // ShaderStage
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -1234,7 +1234,7 @@ int w_newCanvas(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int w_getShaderSource(lua_State *L, int startidx, bool gles, Shader::ShaderSource &source)
|
||||
static int w_getShaderSource(lua_State *L, int startidx, bool gles, std::string &vertexsource, std::string &pixelsource)
|
||||
{
|
||||
using namespace love::filesystem;
|
||||
|
||||
@@ -1315,17 +1315,17 @@ static int w_getShaderSource(lua_State *L, int startidx, bool gles, Shader::Shad
|
||||
|
||||
// vertex shader code
|
||||
if (lua_isstring(L, -2))
|
||||
source.vertex = luax_checkstring(L, -2);
|
||||
vertexsource = luax_checkstring(L, -2);
|
||||
else if (has_arg1 && has_arg2)
|
||||
return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)");
|
||||
|
||||
// pixel shader code
|
||||
if (lua_isstring(L, -1))
|
||||
source.pixel = luax_checkstring(L, -1);
|
||||
pixelsource = luax_checkstring(L, -1);
|
||||
else if (has_arg1 && has_arg2)
|
||||
return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)");
|
||||
|
||||
if (source.vertex.empty() && source.pixel.empty())
|
||||
if (vertexsource.empty() && pixelsource.empty())
|
||||
{
|
||||
// Original args had source code, but effectCodeToGLSL couldn't translate it
|
||||
for (int i = startidx; i < startidx + 2; i++)
|
||||
@@ -1342,13 +1342,13 @@ int w_newShader(lua_State *L)
|
||||
{
|
||||
bool gles = instance()->getRenderer() == Graphics::RENDERER_OPENGLES;
|
||||
|
||||
Shader::ShaderSource source;
|
||||
w_getShaderSource(L, 1, gles, source);
|
||||
std::string vertexsource, pixelsource;
|
||||
w_getShaderSource(L, 1, gles, vertexsource, pixelsource);
|
||||
|
||||
bool should_error = false;
|
||||
try
|
||||
{
|
||||
Shader *shader = instance()->newShader(source);
|
||||
Shader *shader = instance()->newShader(vertexsource, pixelsource);
|
||||
luax_pushtype(L, shader);
|
||||
shader->release();
|
||||
}
|
||||
@@ -1372,11 +1372,20 @@ int w_validateShader(lua_State *L)
|
||||
{
|
||||
bool gles = luax_checkboolean(L, 1);
|
||||
|
||||
Shader::ShaderSource source;
|
||||
w_getShaderSource(L, 2, gles, source);
|
||||
std::string vertexsource, pixelsource;
|
||||
w_getShaderSource(L, 2, gles, vertexsource, pixelsource);
|
||||
|
||||
bool success = true;
|
||||
std::string err;
|
||||
bool success = instance()->validateShader(gles, source, err);
|
||||
try
|
||||
{
|
||||
success = instance()->validateShader(gles, vertexsource, pixelsource, err);
|
||||
}
|
||||
catch (love::Exception &e)
|
||||
{
|
||||
success = false;
|
||||
err = e.what();
|
||||
}
|
||||
|
||||
luax_pushboolean(L, success);
|
||||
|
||||
@@ -2007,23 +2016,21 @@ int w_setDefaultShaderCode(lua_State *L)
|
||||
lua_getfield(L, -3, "videopixel");
|
||||
lua_getfield(L, -4, "arraypixel");
|
||||
|
||||
Shader::ShaderSource code;
|
||||
code.vertex = luax_checkstring(L, -4);
|
||||
code.pixel = luax_checkstring(L, -3);
|
||||
|
||||
Shader::ShaderSource videocode;
|
||||
videocode.vertex = luax_checkstring(L, -4);
|
||||
videocode.pixel = luax_checkstring(L, -2);
|
||||
|
||||
Shader::ShaderSource arraycode;
|
||||
arraycode.vertex = luax_checkstring(L, -4);
|
||||
arraycode.pixel = luax_checkstring(L, -1);
|
||||
std::string vertex = luax_checkstring(L, -4);
|
||||
std::string pixel = luax_checkstring(L, -3);
|
||||
std::string videopixel = luax_checkstring(L, -2);
|
||||
std::string arraypixel = luax_checkstring(L, -1);
|
||||
|
||||
lua_pop(L, 5);
|
||||
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_DEFAULT][lang][i] = code;
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_VIDEO][lang][i] = videocode;
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_ARRAY][lang][i] = arraycode;
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_DEFAULT][lang][i].source[ShaderStage::STAGE_VERTEX] = vertex;
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_DEFAULT][lang][i].source[ShaderStage::STAGE_PIXEL] = pixel;
|
||||
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_VIDEO][lang][i].source[ShaderStage::STAGE_VERTEX] = vertex;
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_VIDEO][lang][i].source[ShaderStage::STAGE_PIXEL] = videopixel;
|
||||
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_ARRAY][lang][i].source[ShaderStage::STAGE_VERTEX] = vertex;
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_ARRAY][lang][i].source[ShaderStage::STAGE_PIXEL] = arraypixel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user